cloesce 0.0.3 → 0.0.4-unstable.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +488 -23
  2. package/dist/cli.d.ts +1 -0
  3. package/dist/cli.js +221 -254
  4. package/dist/common.d.ts +69 -1
  5. package/dist/common.d.ts.map +1 -1
  6. package/dist/common.js +72 -11
  7. package/dist/{extract.d.ts → extractor/extract.d.ts} +5 -2
  8. package/dist/extractor/extract.d.ts.map +1 -0
  9. package/dist/{extract.js → extractor/extract.js} +242 -43
  10. package/dist/generator.wasm +0 -0
  11. package/dist/orm.wasm +0 -0
  12. package/dist/router/crud.d.ts +22 -0
  13. package/dist/router/crud.d.ts.map +1 -0
  14. package/dist/router/crud.js +65 -0
  15. package/dist/router/router.d.ts +77 -0
  16. package/dist/router/router.d.ts.map +1 -0
  17. package/dist/router/router.js +358 -0
  18. package/dist/router/wasm.d.ts +37 -0
  19. package/dist/router/wasm.d.ts.map +1 -0
  20. package/dist/router/wasm.js +98 -0
  21. package/dist/ui/backend.d.ts +124 -0
  22. package/dist/ui/backend.d.ts.map +1 -0
  23. package/dist/ui/backend.js +201 -0
  24. package/dist/ui/client.d.ts +5 -0
  25. package/dist/ui/client.d.ts.map +1 -0
  26. package/dist/ui/client.js +7 -0
  27. package/package.json +70 -58
  28. package/LICENSE +0 -201
  29. package/dist/cli.wasm +0 -0
  30. package/dist/cloesce.d.ts +0 -108
  31. package/dist/cloesce.d.ts.map +0 -1
  32. package/dist/cloesce.js +0 -453
  33. package/dist/decorators.d.ts +0 -13
  34. package/dist/decorators.d.ts.map +0 -1
  35. package/dist/decorators.js +0 -13
  36. package/dist/dog.cloesce.js +0 -111
  37. package/dist/extract.d.ts.map +0 -1
  38. package/dist/index.d.ts +0 -24
  39. package/dist/index.d.ts.map +0 -1
  40. package/dist/index.js +0 -24
  41. package/dist/types.d.ts +0 -4
  42. package/dist/types.d.ts.map +0 -1
  43. package/dist/types.js +0 -1
@@ -0,0 +1,124 @@
1
+ import { D1Database } from "@cloudflare/workers-types/experimental/index.js";
2
+ import { CrudKind, Either, KeysOfType } from "../common.js";
3
+ export { cloesce } from "../router/router.js";
4
+ export type { HttpResult, Either, DeepPartial, InstanceRegistry, CrudKind, } from "../common.js";
5
+ export { CloesceApp } from "../common.js";
6
+ export declare const D1: ClassDecorator;
7
+ export declare const PlainOldObject: ClassDecorator;
8
+ export declare const WranglerEnv: ClassDecorator;
9
+ export declare const PrimaryKey: PropertyDecorator;
10
+ export declare const GET: MethodDecorator;
11
+ export declare const POST: MethodDecorator;
12
+ export declare const PUT: MethodDecorator;
13
+ export declare const PATCH: MethodDecorator;
14
+ export declare const DELETE: MethodDecorator;
15
+ export declare const DataSource: PropertyDecorator;
16
+ export declare const OneToMany: (_: string) => PropertyDecorator;
17
+ export declare const OneToOne: (_: string) => PropertyDecorator;
18
+ export declare const ManyToMany: (_: string) => PropertyDecorator;
19
+ export declare const ForeignKey: <T>(_: T | string) => PropertyDecorator;
20
+ export declare const Inject: ParameterDecorator;
21
+ export declare const CRUD: (_kinds: CrudKind[]) => ClassDecorator;
22
+ type Primitive = string | number | boolean | bigint | symbol | null | undefined;
23
+ export type IncludeTree<T> = T extends Primitive ? never : {
24
+ [K in keyof T]?: T[K] extends (infer U)[] ? IncludeTree<NonNullable<U>> : IncludeTree<NonNullable<T[K]>>;
25
+ };
26
+ export type DataSourceOf<T extends object> = KeysOfType<T, IncludeTree<T>> | "none";
27
+ /**
28
+ * ORM functions which use metadata to translate arguments to valid SQL queries.
29
+ */
30
+ export declare class Orm {
31
+ private db;
32
+ private constructor();
33
+ /**
34
+ * Creates an instance of an `Orm`
35
+ * @param db The database to use for ORM calls.
36
+ */
37
+ static fromD1(db: D1Database): Orm;
38
+ /**
39
+ * Maps SQL records to an instantiated Model. The records must be flat
40
+ * (e.g., of the form "id, name, address") or derive from a Cloesce data source view
41
+ * (e.g., of the form "Horse.id, Horse.name, Horse.address")
42
+ * @param ctor The model constructor
43
+ * @param records D1 Result records
44
+ * @param includeTree Include tree to define the relationships to join.
45
+ * @returns
46
+ */
47
+ static fromSql<T extends object>(ctor: new () => T, records: Record<string, any>[], includeTree: IncludeTree<T> | null): Either<string, T[]>;
48
+ /**
49
+ * Returns a SQL query to insert a model into the database. Uses an IncludeTree as a guide for
50
+ * foreign key relationships, only inserting the explicitly stated pattern in the tree.
51
+ *
52
+ * TODO: We should be able to leave primary keys and foreign keys undefined, with
53
+ * primary keys being auto incremented and foreign keys being assumed by navigation property
54
+ * context.
55
+ *
56
+ * @param ctor A model constructor.
57
+ * @param newModel The new model to insert.
58
+ * @param includeTree An include tree describing which foreign keys to join.
59
+ * @returns Either an error string, or the insert query string.
60
+ */
61
+ static upsertQuery<T extends object>(ctor: new () => T, newModel: T, includeTree: IncludeTree<T> | null): Either<string, string>;
62
+ /**
63
+ * Executes an "upsert" query, adding or augmenting a model in the database.
64
+ * If a model's primary key is not defined in `newModel`, the query is assumed to be an insert.
65
+ * If a model's primary key _is_ defined, but some attributes are missing, the query is assumed to be an update.
66
+ * Finally, if the primary key is defined, but all attributes are included, a SQLite upsert will be performed.
67
+ *
68
+ * Capable of inferring foreign keys from the surrounding context of the model. A missing primary key is allowed
69
+ * only if the primary key is an integer, in which case it will be auto incremented and assigned.
70
+ *
71
+ * ### Inserting a new Model
72
+ * ```ts
73
+ * const model = {name: "julio", lastname: "pumpkin"};
74
+ * const idRes = await orm.upsert(Person, model, null);
75
+ * ```
76
+ *
77
+ * ### Updating an existing model
78
+ * ```ts
79
+ * const model = {id: 1, name: "timothy"};
80
+ * const idRes = await orm.upsert(Person, model, null);
81
+ * // (in db)=> {id: 1, name: "timothy", lastname: "pumpkin"}
82
+ * ```
83
+ *
84
+ * ### Upserting a model
85
+ * ```ts
86
+ * // (assume a Person already exists)
87
+ * const model = {
88
+ * id: 1,
89
+ * lastname: "burger", // updates last name
90
+ * dog: {
91
+ * name: "fido" // insert dog relationship
92
+ * }
93
+ * };
94
+ * const idRes = await orm.upsert(Person, model, null);
95
+ * // (in db)=> Person: {id: 1, dogId: 1 ...} ; Dog: {id: 1, name: "fido"}
96
+ * ```
97
+ *
98
+ * @param ctor A model constructor.
99
+ * @param newModel The new or augmented model.
100
+ * @param includeTree An include tree describing which foreign keys to join.
101
+ * @returns An error string, or the primary key of the inserted model.
102
+ */
103
+ upsert<T extends object>(ctor: new () => T, newModel: T, includeTree: IncludeTree<T> | null): Promise<Either<string, any>>;
104
+ /**
105
+ * Returns a query of the form `SELECT * FROM [Model.DataSource]`
106
+ */
107
+ static listQuery<T extends object>(ctor: new () => T, includeTree: KeysOfType<T, IncludeTree<T>> | null): string;
108
+ /**
109
+ * Returns a query of the form `SELECT * FROM [Model.DataSource] WHERE [Model.PrimaryKey] = ?`.
110
+ * Requires the id parameter to be bound (use db.prepare().bind)
111
+ */
112
+ static getQuery<T extends object>(ctor: new () => T, includeTree: KeysOfType<T, IncludeTree<T>> | null): string;
113
+ /**
114
+ * Executes a query of the form `SELECT * FROM [Model.DataSource]`, returning all results
115
+ * as instantiated models.
116
+ */
117
+ list<T extends object>(ctor: new () => T, includeTreeKey: KeysOfType<T, IncludeTree<T>> | null): Promise<Either<string, T[]>>;
118
+ /**
119
+ * Executes a query of the form `SELECT * FROM [Model.DataSource] WHERE [Model.PrimaryKey] = ?`
120
+ * returning all results as instantiated models.
121
+ */
122
+ get<T extends object>(ctor: new () => T, id: any, includeTreeKey: KeysOfType<T, IncludeTree<T>> | null): Promise<Either<string, T>>;
123
+ }
124
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/ui/backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iDAAiD,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAe,MAAM,cAAc,CAAC;AAIzE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,YAAY,EACV,UAAU,EACV,MAAM,EACN,WAAW,EACX,gBAAgB,EAChB,QAAQ,GACT,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,eAAO,MAAM,EAAE,EAAE,cAAyB,CAAC;AAC3C,eAAO,MAAM,cAAc,EAAE,cAAyB,CAAC;AACvD,eAAO,MAAM,WAAW,EAAE,cAAyB,CAAC;AACpD,eAAO,MAAM,UAAU,EAAE,iBAA4B,CAAC;AACtD,eAAO,MAAM,GAAG,EAAE,eAA0B,CAAC;AAC7C,eAAO,MAAM,IAAI,EAAE,eAA0B,CAAC;AAC9C,eAAO,MAAM,GAAG,EAAE,eAA0B,CAAC;AAC7C,eAAO,MAAM,KAAK,EAAE,eAA0B,CAAC;AAC/C,eAAO,MAAM,MAAM,EAAE,eAA0B,CAAC;AAChD,eAAO,MAAM,UAAU,EAAE,iBAA4B,CAAC;AACtD,eAAO,MAAM,SAAS,GACnB,GAAG,MAAM,KAAG,iBACL,CAAC;AACX,eAAO,MAAM,QAAQ,GAClB,GAAG,MAAM,KAAG,iBACL,CAAC;AACX,eAAO,MAAM,UAAU,GACpB,GAAG,MAAM,KAAG,iBACL,CAAC;AACX,eAAO,MAAM,UAAU,GACpB,CAAC,EAAE,GAAG,CAAC,GAAG,MAAM,KAAG,iBACZ,CAAC;AACX,eAAO,MAAM,MAAM,EAAE,kBAA6B,CAAC;AACnD,eAAO,MAAM,IAAI,GACd,QAAQ,QAAQ,EAAE,KAAG,cACd,CAAC;AAGX,KAAK,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAChF,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,SAAS,GAC5C,KAAK,GACL;KACG,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,GACrC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAC3B,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CACnC,CAAC;AAGN,MAAM,MAAM,YAAY,CAAC,CAAC,SAAS,MAAM,IACrC,UAAU,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GAC7B,MAAM,CAAC;AAEX;;GAEG;AACH,qBAAa,GAAG;IACM,OAAO,CAAC,EAAE;IAA9B,OAAO;IAEP;;;OAGG;IACH,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,UAAU,GAAG,GAAG;IAIlC;;;;;;;;OAQG;IACH,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,MAAM,EAC7B,IAAI,EAAE,UAAU,CAAC,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,EAC9B,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,GACjC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;IAItB;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,WAAW,CAAC,CAAC,SAAS,MAAM,EACjC,IAAI,EAAE,UAAU,CAAC,EACjB,QAAQ,EAAE,CAAC,EACX,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,GACjC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAUzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwCG;IACG,MAAM,CAAC,CAAC,SAAS,MAAM,EAC3B,IAAI,EAAE,UAAU,CAAC,EACjB,QAAQ,EAAE,CAAC,EACX,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,GACjC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAuC/B;;OAEG;IACH,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,MAAM,EAC/B,IAAI,EAAE,UAAU,CAAC,EACjB,WAAW,EAAE,UAAU,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAChD,MAAM;IAQT;;;OAGG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,MAAM,EAC9B,IAAI,EAAE,UAAU,CAAC,EACjB,WAAW,EAAE,UAAU,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAChD,MAAM;IAST;;;OAGG;IACG,IAAI,CAAC,CAAC,SAAS,MAAM,EACzB,IAAI,EAAE,UAAU,CAAC,EACjB,cAAc,EAAE,UAAU,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GACnD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IAsB/B;;;OAGG;IACG,GAAG,CAAC,CAAC,SAAS,MAAM,EACxB,IAAI,EAAE,UAAU,CAAC,EACjB,EAAE,EAAE,GAAG,EACP,cAAc,EAAE,UAAU,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GACnD,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;CAqB9B"}
@@ -0,0 +1,201 @@
1
+ import { left, right } from "../common.js";
2
+ import { RuntimeContainer } from "../router/router.js";
3
+ import { WasmResource, fromSql, invokeOrmWasm } from "../router/wasm.js";
4
+ export { cloesce } from "../router/router.js";
5
+ export { CloesceApp } from "../common.js";
6
+ // Compiler hints
7
+ export const D1 = () => { };
8
+ export const PlainOldObject = () => { };
9
+ export const WranglerEnv = () => { };
10
+ export const PrimaryKey = () => { };
11
+ export const GET = () => { };
12
+ export const POST = () => { };
13
+ export const PUT = () => { };
14
+ export const PATCH = () => { };
15
+ export const DELETE = () => { };
16
+ export const DataSource = () => { };
17
+ export const OneToMany = (_) => () => { };
18
+ export const OneToOne = (_) => () => { };
19
+ export const ManyToMany = (_) => () => { };
20
+ export const ForeignKey = (_) => () => { };
21
+ export const Inject = () => { };
22
+ export const CRUD = (_kinds) => () => { };
23
+ /**
24
+ * ORM functions which use metadata to translate arguments to valid SQL queries.
25
+ */
26
+ export class Orm {
27
+ db;
28
+ constructor(db) {
29
+ this.db = db;
30
+ }
31
+ /**
32
+ * Creates an instance of an `Orm`
33
+ * @param db The database to use for ORM calls.
34
+ */
35
+ static fromD1(db) {
36
+ return new Orm(db);
37
+ }
38
+ /**
39
+ * Maps SQL records to an instantiated Model. The records must be flat
40
+ * (e.g., of the form "id, name, address") or derive from a Cloesce data source view
41
+ * (e.g., of the form "Horse.id, Horse.name, Horse.address")
42
+ * @param ctor The model constructor
43
+ * @param records D1 Result records
44
+ * @param includeTree Include tree to define the relationships to join.
45
+ * @returns
46
+ */
47
+ static fromSql(ctor, records, includeTree) {
48
+ return fromSql(ctor, records, includeTree);
49
+ }
50
+ /**
51
+ * Returns a SQL query to insert a model into the database. Uses an IncludeTree as a guide for
52
+ * foreign key relationships, only inserting the explicitly stated pattern in the tree.
53
+ *
54
+ * TODO: We should be able to leave primary keys and foreign keys undefined, with
55
+ * primary keys being auto incremented and foreign keys being assumed by navigation property
56
+ * context.
57
+ *
58
+ * @param ctor A model constructor.
59
+ * @param newModel The new model to insert.
60
+ * @param includeTree An include tree describing which foreign keys to join.
61
+ * @returns Either an error string, or the insert query string.
62
+ */
63
+ static upsertQuery(ctor, newModel, includeTree) {
64
+ const { wasm } = RuntimeContainer.get();
65
+ const args = [
66
+ WasmResource.fromString(ctor.name, wasm),
67
+ WasmResource.fromString(JSON.stringify(newModel), wasm),
68
+ WasmResource.fromString(JSON.stringify(includeTree), wasm),
69
+ ];
70
+ return invokeOrmWasm(wasm.upsert_model, args, wasm);
71
+ }
72
+ /**
73
+ * Executes an "upsert" query, adding or augmenting a model in the database.
74
+ * If a model's primary key is not defined in `newModel`, the query is assumed to be an insert.
75
+ * If a model's primary key _is_ defined, but some attributes are missing, the query is assumed to be an update.
76
+ * Finally, if the primary key is defined, but all attributes are included, a SQLite upsert will be performed.
77
+ *
78
+ * Capable of inferring foreign keys from the surrounding context of the model. A missing primary key is allowed
79
+ * only if the primary key is an integer, in which case it will be auto incremented and assigned.
80
+ *
81
+ * ### Inserting a new Model
82
+ * ```ts
83
+ * const model = {name: "julio", lastname: "pumpkin"};
84
+ * const idRes = await orm.upsert(Person, model, null);
85
+ * ```
86
+ *
87
+ * ### Updating an existing model
88
+ * ```ts
89
+ * const model = {id: 1, name: "timothy"};
90
+ * const idRes = await orm.upsert(Person, model, null);
91
+ * // (in db)=> {id: 1, name: "timothy", lastname: "pumpkin"}
92
+ * ```
93
+ *
94
+ * ### Upserting a model
95
+ * ```ts
96
+ * // (assume a Person already exists)
97
+ * const model = {
98
+ * id: 1,
99
+ * lastname: "burger", // updates last name
100
+ * dog: {
101
+ * name: "fido" // insert dog relationship
102
+ * }
103
+ * };
104
+ * const idRes = await orm.upsert(Person, model, null);
105
+ * // (in db)=> Person: {id: 1, dogId: 1 ...} ; Dog: {id: 1, name: "fido"}
106
+ * ```
107
+ *
108
+ * @param ctor A model constructor.
109
+ * @param newModel The new or augmented model.
110
+ * @param includeTree An include tree describing which foreign keys to join.
111
+ * @returns An error string, or the primary key of the inserted model.
112
+ */
113
+ async upsert(ctor, newModel, includeTree) {
114
+ let upsertQueryRes = Orm.upsertQuery(ctor, newModel, includeTree);
115
+ if (!upsertQueryRes.ok) {
116
+ return upsertQueryRes;
117
+ }
118
+ // Split the query into individual statements.
119
+ const statements = upsertQueryRes.value
120
+ .split(";")
121
+ .map((s) => s.trim())
122
+ .filter((s) => s.length > 0);
123
+ // One of these statements is a "SELECT", which is the root model id stmt.
124
+ let selectIndex;
125
+ for (let i = statements.length - 1; i >= 0; i--) {
126
+ if (/^SELECT/i.test(statements[i])) {
127
+ selectIndex = i;
128
+ break;
129
+ }
130
+ }
131
+ // Execute all statements in a batch.
132
+ const batchRes = await this.db.batch(statements.map((s) => this.db.prepare(s)));
133
+ if (!batchRes.every((r) => r.success)) {
134
+ const failed = batchRes.find((r) => !r.success);
135
+ return left(failed?.error ?? "D1 batch failed, but no error was returned.");
136
+ }
137
+ // Return the result of the SELECT statement
138
+ const selectResult = batchRes[selectIndex].results[0];
139
+ return right(selectResult.id);
140
+ }
141
+ /**
142
+ * Returns a query of the form `SELECT * FROM [Model.DataSource]`
143
+ */
144
+ static listQuery(ctor, includeTree) {
145
+ if (includeTree) {
146
+ return `SELECT * FROM [${ctor.name}.${includeTree.toString()}]`;
147
+ }
148
+ return `SELECT * FROM [${ctor.name}]`;
149
+ }
150
+ /**
151
+ * Returns a query of the form `SELECT * FROM [Model.DataSource] WHERE [Model.PrimaryKey] = ?`.
152
+ * Requires the id parameter to be bound (use db.prepare().bind)
153
+ */
154
+ static getQuery(ctor, includeTree) {
155
+ const { ast } = RuntimeContainer.get();
156
+ if (includeTree) {
157
+ return `${this.listQuery(ctor, includeTree)} WHERE [${ctor.name}.${ast.models[ctor.name].primary_key.name}] = ?`;
158
+ }
159
+ return `${this.listQuery(ctor, includeTree)} WHERE [${ast.models[ctor.name].primary_key.name}] = ?`;
160
+ }
161
+ /**
162
+ * Executes a query of the form `SELECT * FROM [Model.DataSource]`, returning all results
163
+ * as instantiated models.
164
+ */
165
+ async list(ctor, includeTreeKey) {
166
+ const q = Orm.listQuery(ctor, includeTreeKey);
167
+ const res = await this.db.prepare(q).run();
168
+ if (!res.success) {
169
+ return left(res.error ?? "D1 failed but no error was returned.");
170
+ }
171
+ const { ast } = RuntimeContainer.get();
172
+ const includeTree = includeTreeKey === null
173
+ ? null
174
+ : ast.models[ctor.name].data_sources[includeTreeKey.toString()].tree;
175
+ const fromSqlRes = fromSql(ctor, res.results, includeTree);
176
+ if (!fromSqlRes.ok) {
177
+ return fromSqlRes;
178
+ }
179
+ return right(fromSqlRes.value);
180
+ }
181
+ /**
182
+ * Executes a query of the form `SELECT * FROM [Model.DataSource] WHERE [Model.PrimaryKey] = ?`
183
+ * returning all results as instantiated models.
184
+ */
185
+ async get(ctor, id, includeTreeKey) {
186
+ const q = Orm.getQuery(ctor, includeTreeKey);
187
+ const res = await this.db.prepare(q).bind(id).run();
188
+ if (!res.success) {
189
+ return left(res.error ?? "D1 failed but no error was returned.");
190
+ }
191
+ const { ast } = RuntimeContainer.get();
192
+ const includeTree = includeTreeKey === null
193
+ ? null
194
+ : ast.models[ctor.name].data_sources[includeTreeKey.toString()].tree;
195
+ const fromSqlRes = fromSql(ctor, res.results, includeTree);
196
+ if (!fromSqlRes.ok) {
197
+ return fromSqlRes;
198
+ }
199
+ return right(fromSqlRes.value[0]);
200
+ }
201
+ }
@@ -0,0 +1,5 @@
1
+ export type { HttpResult, Either, DeepPartial } from "../common.js";
2
+ export declare function instantiateObjectArray<T extends object>(data: any, ctor: {
3
+ new (): T;
4
+ }): T[];
5
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/ui/client.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGpE,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,EACrD,IAAI,EAAE,GAAG,EACT,IAAI,EAAE;IAAE,QAAQ,CAAC,CAAA;CAAE,GAClB,CAAC,EAAE,CAKL"}
@@ -0,0 +1,7 @@
1
+ // Helpers
2
+ export function instantiateObjectArray(data, ctor) {
3
+ if (Array.isArray(data)) {
4
+ return data.map((x) => instantiateObjectArray(x, ctor)).flat();
5
+ }
6
+ return [Object.assign(new ctor(), data)];
7
+ }
package/package.json CHANGED
@@ -1,58 +1,70 @@
1
- {
2
- "name": "cloesce",
3
- "version": "0.0.3",
4
- "description": "A tool to extract and compile TypeScript code into something wrangler can consume and deploy for D1 Databases and Cloudflare Workers",
5
- "type": "module",
6
- "license": "Apache-2.0",
7
-
8
- "main": "./dist/index.js",
9
- "types": "./dist/index.d.ts",
10
- "exports": {
11
- ".": {
12
- "types": "./dist/index.d.ts",
13
- "import": "./dist/index.js"
14
- },
15
- "./cli": "./dist/cli.js"
16
- },
17
- "bin": {
18
- "cloesce": "./dist/cli.js"
19
- },
20
-
21
- "files": [
22
- "dist/**",
23
- "wasm/**",
24
- "README.md",
25
- "LICENSE"
26
- ],
27
- "sideEffects": false,
28
- "engines": { "node": ">=18.17" },
29
-
30
- "scripts": {
31
- "build": "tsc -p tsconfig.json",
32
- "typecheck": "tsc --noEmit",
33
- "test": "vitest --run",
34
- "format": "prettier --check .",
35
- "format:fix": "prettier --write .",
36
- "prepublishOnly": "npm run typecheck && npm run build && npm run test"
37
- },
38
-
39
- "dependencies": {
40
- "cmd-ts": "^0.14.1",
41
- "ts-morph": "^22.0.0"
42
- },
43
- "devDependencies": {
44
- "@cloudflare/workers-types": "^4.20250906.0",
45
- "prettier": "^3.6.2",
46
- "ts-node": "^10.9.2",
47
- "typescript": "^5.6.0",
48
- "vitest": "^3.2.4",
49
- "wrangler": "^4.34.0"
50
- },
51
-
52
- "repository": {
53
- "type": "git",
54
- "url": "git+https://github.com/bens-schreiber/cloesce.git"
55
- },
56
- "homepage": "https://github.com/bens-schreiber/cloesce",
57
- "keywords": ["cloudflare", "workers", "d1", "orm", "cli"]
58
- }
1
+ {
2
+ "name": "cloesce",
3
+ "version": "0.0.4-unstable.1",
4
+ "description": "A tool to extract and compile TypeScript code into something wrangler can consume and deploy for D1 Databases and Cloudflare Workers",
5
+ "type": "module",
6
+ "license": "Apache-2.0",
7
+ "scripts": {
8
+ "test": "vitest",
9
+ "format:fix": "prettier --write .",
10
+ "format": "prettier --check .",
11
+ "typecheck": "tsc --noEmit",
12
+ "build": "tsc -p tsconfig.json && npm run copy-rs-orm-wasm && npm run copy-generator-wasm && chmod +x dist/cli.js",
13
+ "copy-rs-orm-wasm": "cp ../orm/target/wasm32-unknown-unknown/release/orm.wasm ./dist/orm.wasm",
14
+ "copy-generator-wasm": "cp ../../generator/target/wasm32-wasip1/release/cli.wasm ./dist/generator.wasm"
15
+ },
16
+ "dependencies": {
17
+ "cmd-ts": "^0.14.1",
18
+ "ts-morph": "^22.0.0",
19
+ "wrangler": "^4.34.0"
20
+ },
21
+ "devDependencies": {
22
+ "@cloudflare/workers-types": "^4.20250906.0",
23
+ "ts-node": "^10.9.2",
24
+ "typescript": "^5.6.0",
25
+ "prettier": "^3.6.2",
26
+ "vitest": "^3.2.4"
27
+ },
28
+ "exports": {
29
+ "./client": {
30
+ "types": "./dist/ui/client.d.ts",
31
+ "import": "./dist/ui/client.js"
32
+ },
33
+ "./backend": {
34
+ "types": "./dist/ui/backend.d.ts",
35
+ "import": "./dist/ui/backend.js"
36
+ }
37
+ },
38
+ "bin": {
39
+ "cloesce": "dist/cli.js"
40
+ },
41
+ "typesVersions": {
42
+ "*": {
43
+ "backend": [
44
+ "dist/ui/backend.d.ts"
45
+ ],
46
+ "client": [
47
+ "dist/ui/client.d.ts"
48
+ ]
49
+ }
50
+ },
51
+ "files": [
52
+ "dist/**/*"
53
+ ],
54
+ "sideEffects": false,
55
+ "engines": {
56
+ "node": ">=18.17"
57
+ },
58
+ "repository": {
59
+ "type": "git",
60
+ "url": "git+https://github.com/bens-schreiber/cloesce.git"
61
+ },
62
+ "homepage": "https://github.com/bens-schreiber/cloesce",
63
+ "keywords": [
64
+ "cloudflare",
65
+ "workers",
66
+ "d1",
67
+ "orm",
68
+ "cli"
69
+ ]
70
+ }