Skip to content

Commit

Permalink
most basic example for exploring features in real time / for presenta…
Browse files Browse the repository at this point in the history
…tions
  • Loading branch information
tantaman committed Oct 25, 2022
1 parent b173086 commit a7dcd81
Show file tree
Hide file tree
Showing 16 changed files with 351 additions and 1 deletion.
18 changes: 18 additions & 0 deletions examples/demo/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html lang="en">
<html>

<head>
<meta charset="utf-8" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="viewport" content="width=device-width, initial-scale=1.0,
user-scalable=no">
<title>demo</title>
</head>

<body>
<div id="app"></div>
<script type="module" src="./src/main.tsx"></script>
</body>

</html>
1 change: 1 addition & 0 deletions examples/demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"dependencies": {
"@aphro/react": "workspace:*",
"@aphro/runtime-ts": "workspace:*",
"@aphro/wa-sqlite-connector": "workspace:*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
Expand Down
7 changes: 7 additions & 0 deletions examples/demo/src/domain.aphro
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
engine: sqlite
db: demo

User as Node {
1 id: ID<User>
2 email: string
}
6 changes: 6 additions & 0 deletions examples/demo/src/domain/User.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import UserBase from './generated/UserBase.js';
export type { Data } from './generated/UserBase.js';

export default class User extends UserBase {
// insert any manual method you may have here
}
12 changes: 12 additions & 0 deletions examples/demo/src/domain/generated/User.sqlite.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- SIGNED-SOURCE: <9a3800acf2a1c2b8d75c64180549682e>
-- STATEMENT
CREATE TABLE
"user" (
"id"
/* n=1 */
,
"email"
/* n=2 */
,
PRIMARY KEY ("id")
);
77 changes: 77 additions & 0 deletions examples/demo/src/domain/generated/UserBase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SIGNED-SOURCE: <643f43b65949f7e1c92d77efcc3d40e4>
/**
* AUTO-GENERATED FILE
* Do not modify. Update your schema and re-generate for changes.
*/
import User from "../User.js";
import { default as s } from "./UserSpec.js";
import { P } from "@aphro/runtime-ts";
import { UpdateMutationBuilder } from "@aphro/runtime-ts";
import { CreateMutationBuilder } from "@aphro/runtime-ts";
import { DeleteMutationBuilder } from "@aphro/runtime-ts";
import { makeSavable } from "@aphro/runtime-ts";
import { modelGenMemo } from "@aphro/runtime-ts";
import { Node } from "@aphro/runtime-ts";
import { NodeSpecWithCreate } from "@aphro/runtime-ts";
import { SID_of } from "@aphro/runtime-ts";
import UserQuery from "./UserQuery.js";
import { Context } from "@aphro/runtime-ts";

export type Data = {
id: SID_of<User>;
email: string;
};

// @Sealed(User)
export default abstract class UserBase extends Node<Data> {
readonly spec = s as unknown as NodeSpecWithCreate<this, Data>;

get id(): SID_of<this> {
return this.data.id as unknown as SID_of<this>;
}

get email(): string {
return this.data.email;
}

static queryAll(ctx: Context): UserQuery {
return UserQuery.create(ctx);
}

static genx = modelGenMemo(
"demo",
"user",
(ctx: Context, id: SID_of<User>): Promise<User> =>
this.queryAll(ctx).whereId(P.equals(id)).genxOnlyValue()
);

static gen = modelGenMemo<User, User | null>(
"demo",
"user",
(ctx: Context, id: SID_of<User>): Promise<User | null> =>
this.queryAll(ctx).whereId(P.equals(id)).genOnlyValue()
);

update(data: Partial<Data>) {
return makeSavable(
this.ctx,
new UpdateMutationBuilder(this.ctx, this.spec, this)
.set(data)
.toChangesets()[0]
);
}

static create(ctx: Context, data: Partial<Data>) {
return makeSavable(
ctx,
new CreateMutationBuilder(ctx, s).set(data).toChangesets()[0]
);
}

delete() {
return makeSavable(
this.ctx,
new DeleteMutationBuilder(this.ctx, this.spec, this).toChangesets()[0]
);
}
}
73 changes: 73 additions & 0 deletions examples/demo/src/domain/generated/UserQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SIGNED-SOURCE: <6963e704d931441dc118eeee2a245a6d>
/**
* AUTO-GENERATED FILE
* Do not modify. Update your schema and re-generate for changes.
*/
import { Context } from "@aphro/runtime-ts";
import { DerivedQuery } from "@aphro/runtime-ts";
import { QueryFactory } from "@aphro/runtime-ts";
import { modelLoad } from "@aphro/runtime-ts";
import { filter } from "@aphro/runtime-ts";
import { Predicate } from "@aphro/runtime-ts";
import { take } from "@aphro/runtime-ts";
import { orderBy } from "@aphro/runtime-ts";
import { P } from "@aphro/runtime-ts";
import { ModelFieldGetter } from "@aphro/runtime-ts";
import { Expression } from "@aphro/runtime-ts";
import { EmptyQuery } from "@aphro/runtime-ts";
import { SID_of } from "@aphro/runtime-ts";
import User from "../User.js";
import { Data } from "./UserBase.js";
import UserSpec from "./UserSpec.js";

export default class UserQuery extends DerivedQuery<User> {
static create(ctx: Context) {
return new UserQuery(
ctx,
QueryFactory.createSourceQueryFor(ctx, UserSpec),
modelLoad(ctx, UserSpec.createFrom)
);
}

static empty(ctx: Context) {
return new UserQuery(ctx, new EmptyQuery(ctx));
}

protected derive(expression: Expression): UserQuery {
return new UserQuery(this.ctx, this, expression);
}

static fromId(ctx: Context, id: SID_of<User>) {
return this.create(ctx).whereId(P.equals(id));
}

whereId(p: Predicate<Data["id"]>) {
return this.derive(
// @ts-ignore #43
filter(new ModelFieldGetter<"id", Data, User>("id"), p)
);
}

whereEmail(p: Predicate<Data["email"]>) {
return this.derive(
// @ts-ignore #43
filter(new ModelFieldGetter<"email", Data, User>("email"), p)
);
}

take(n: number) {
return new UserQuery(this.ctx, this, take(n));
}

orderById(direction: "asc" | "desc" = "asc") {
return this.derive(
orderBy(new ModelFieldGetter<"id", Data, User>("id"), direction)
);
}

orderByEmail(direction: "asc" | "desc" = "asc") {
return this.derive(
orderBy(new ModelFieldGetter<"email", Data, User>("email"), direction)
);
}
}
49 changes: 49 additions & 0 deletions examples/demo/src/domain/generated/UserSpec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// SIGNED-SOURCE: <72ba0b61f5f639e2d931229bbd8882a4>
/**
* AUTO-GENERATED FILE
* Do not modify. Update your schema and re-generate for changes.
*/
import { Context } from "@aphro/runtime-ts";
import { decodeModelData } from "@aphro/runtime-ts";
import { encodeModelData } from "@aphro/runtime-ts";
import { SID_of } from "@aphro/runtime-ts";
import { NodeSpecWithCreate } from "@aphro/runtime-ts";
import User from "../User.js";
import { Data } from "./UserBase.js";

const fields = {
id: {
encoding: "none",
},
email: {
encoding: "none",
},
} as const;
const UserSpec: NodeSpecWithCreate<User, Data> = {
type: "node",
createFrom(ctx: Context, data: Data, raw: boolean = true) {
const existing = ctx.cache.get(data["id"], "demo", "user");
if (existing) {
return existing;
}
if (raw) data = decodeModelData(data, fields);
const result = new User(ctx, data);
ctx.cache.set(data["id"], result, "demo", "user");
return result;
},

primaryKey: "id",

storage: {
engine: "sqlite",
db: "demo",
type: "sql",
tablish: "user",
},

fields,

outboundEdges: {},
};

export default UserSpec;
30 changes: 30 additions & 0 deletions examples/demo/src/domain/generated/exports-node-sql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SIGNED-SOURCE: <e7cb79b9d903b464f44bc57b708063c5>
/**
* AUTO-GENERATED FILE
* Do not modify. Update your schema and re-generate for changes.
*/

// @ts-ignore
import * as path from "path";
// @ts-ignore
import * as fs from "fs";

// @ts-ignore
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const [User] = await Promise.all([
fs.promises.readFile(path.join(__dirname, "User.sqlite.sql"), {
encoding: "utf8",
}),
]);

export default {
sqlite: {
demo: {
User,
},
},
};
13 changes: 13 additions & 0 deletions examples/demo/src/domain/generated/exports-sql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SIGNED-SOURCE: <f9c06d1c37038f6b503515beeb67b539>
/**
* AUTO-GENERATED FILE
* Do not modify. Update your schema and re-generate for changes.
*/
import User from "./User.sqlite.sql?raw";
export default {
sqlite: {
demo: {
User,
},
},
};
8 changes: 8 additions & 0 deletions examples/demo/src/domain/generated/exports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SIGNED-SOURCE: <1c6e2363775cb1812578ec35d4cdfd47>
/**
* AUTO-GENERATED FILE
* Do not modify. Update your schema and re-generate for changes.
*/
export { default as User } from "../User.js";
export { default as UserSpec } from "./UserSpec.js";
export { default as UserQuery } from "./UserQuery.js";
6 changes: 6 additions & 0 deletions examples/demo/src/domain/generated/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SIGNED-SOURCE: <7946820adce4295e4ffad7d91d8edf9a>
/**
* AUTO-GENERATED FILE
* Do not modify. Update your schema and re-generate for changes.
*/
declare module "*.sql?raw";
5 changes: 5 additions & 0 deletions examples/demo/src/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type FetchFrag<T extends { fetch: (...args: any) => any }, K extends string> = Awaited<
ReturnType<T['fetch']>
>[K];

type Frags<T extends { fetch: (...args: any) => any }> = Awaited<ReturnType<T['fetch']>>;
43 changes: 43 additions & 0 deletions examples/demo/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import { createRoot } from 'react-dom/client';
import { anonymous, Context, context, bootstrap } from '@aphro/runtime-ts';
import { openDbAndCreateResolver } from '@aphro/wa-sqlite-connector';

import * as domain from './domain/generated/exports';
import sqlFiles from './domain/generated/exports-sql';
import { useLiveResult } from '@aphro/react';
(window as any).domain = domain;

openDbAndCreateResolver('demo')
.then(resolver => {
// TODO: framework should take care of viewer creation?
start(context(anonymous(), resolver));
})
.catch(e => console.error(e));

async function start(ctx: Context) {
(window as any).ctx = ctx;
const root = createRoot(document.getElementById('app')!);
await bootstrap.createAutomigrateIfExists(ctx.dbResolver, sqlFiles);

const appData = await App.fetch(ctx);
root.render(<App data={appData} />);
}

function App({ data }: { data: Frags<typeof App> }) {
const users = useLiveResult(data.liveUsers);
return (
<ul>
{users.map(u => (
<li key={u.id}>{u.email}</li>
))}
</ul>
);
}

App.fetch = async (ctx: Context) => {
const liveUsers = await domain.User.queryAll(ctx).genLive();
return {
liveUsers,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default class GenTypescriptModelManualMethodsClass extends CodegenStep {
return new TypescriptFile(
filename,
`import ${this.schema.name}Base from './${generatedDir}/${this.schema.name}Base.js';
export {Data} from './${generatedDir}/${this.schema.name}Base.js';
export type {Data} from './${generatedDir}/${this.schema.name}Base.js';
export default class ${this.schema.name} extends ${this.schema.name}Base {
// insert any manual method you may have here
Expand Down
2 changes: 2 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a7dcd81

Please sign in to comment.