cloesce 0.0.4-unstable.1 → 0.0.4-unstable.3
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.
- package/README.md +167 -7
- package/dist/cli.js +7 -4
- package/dist/common.d.ts +14 -8
- package/dist/common.d.ts.map +1 -1
- package/dist/common.js +12 -7
- package/dist/extractor/extract.d.ts +10 -9
- package/dist/extractor/extract.d.ts.map +1 -1
- package/dist/extractor/extract.js +51 -28
- package/dist/generator.wasm +0 -0
- package/dist/orm.wasm +0 -0
- package/dist/router/router.d.ts.map +1 -1
- package/dist/router/router.js +6 -3
- package/dist/ui/backend.d.ts +13 -2
- package/dist/ui/backend.d.ts.map +1 -1
- package/dist/ui/backend.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Cloesce is a full stack compiler for the Cloudflare developer platform, allowing class definitions in high level languages to serve as a metadata basis to create a database schema, backend REST API, frontend API client, and Cloudflare infrastructure (as of v0.0.4, D1 + Workers).
|
|
4
4
|
|
|
5
|
-
Cloesce is working towards
|
|
5
|
+
Cloesce is working towards a stable alpha MVP (v0.1.0), with the general milestones being [here](https://cloesce.pages.dev/schreiber/v0.1.0_milestones/).
|
|
6
6
|
|
|
7
7
|
Internal documentation going over design decisions and general thoughts for each milestone can be found [here](https://cloesce.pages.dev/).
|
|
8
8
|
|
|
@@ -18,7 +18,7 @@ Internal documentation going over design decisions and general thoughts for each
|
|
|
18
18
|
|
|
19
19
|
```sh
|
|
20
20
|
# check https://www.npmjs.com/package/cloesce/v/0.0.4-unstable.0?activeTab=versions for the most recent patch
|
|
21
|
-
npm i cloesce@0.0.4-unstable.
|
|
21
|
+
npm i cloesce@0.0.4-unstable.2
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
2. TypeScript
|
|
@@ -148,6 +148,19 @@ Note the output in `migrations`, ex after running `npx cloesce migrate Initial`
|
|
|
148
148
|
- `<date>_Initial.json` contains all model information necessary from SQL
|
|
149
149
|
- `<date>_Initial.sql` contains the acual SQL migrations. In this early version of Cloesce, it's important to check migrations every time.
|
|
150
150
|
|
|
151
|
+
#### Supported Column Types
|
|
152
|
+
|
|
153
|
+
Model columns must directly map to SQLite columns. The supported TypeScript types are:
|
|
154
|
+
|
|
155
|
+
- `number` => `Real` not null
|
|
156
|
+
- `string` => `Text` not null
|
|
157
|
+
- `boolean` and `Boolean` => `Integer` not null
|
|
158
|
+
- `Integer` => `Integer` not null
|
|
159
|
+
- `Date` => `Text` (ISO formatted) not null
|
|
160
|
+
- `N | null` => `N` (nullable)
|
|
161
|
+
|
|
162
|
+
Blob types will be added in v0.0.5 when R2 support is added.
|
|
163
|
+
|
|
151
164
|
## Features
|
|
152
165
|
|
|
153
166
|
### Wrangler Environment
|
|
@@ -155,8 +168,6 @@ Note the output in `migrations`, ex after running `npx cloesce migrate Initial`
|
|
|
155
168
|
In order to interact with your database, you will need to define a WranglerEnv
|
|
156
169
|
|
|
157
170
|
```ts
|
|
158
|
-
// horse.cloesce.ts
|
|
159
|
-
|
|
160
171
|
import { WranglerEnv } from "cloesce/backend";
|
|
161
172
|
|
|
162
173
|
@WranglerEnv
|
|
@@ -256,7 +267,7 @@ export class Person {
|
|
|
256
267
|
}
|
|
257
268
|
```
|
|
258
269
|
|
|
259
|
-
Data sources are just SQL views and can be invoked in your queries. They are aliased in such a way that its similiar to object properties. The frontend chooses which datasource to use in it's API client. `null` is a valid option, meaning no joins will occur.
|
|
270
|
+
Data sources are just SQL views and can be invoked in your queries. They are aliased in such a way that its similiar to object properties. The frontend chooses which datasource to use in it's API client (all instantiated methods have an implicit DataSource parameter). `null` is a valid option, meaning no joins will occur.
|
|
260
271
|
|
|
261
272
|
```ts
|
|
262
273
|
@D1
|
|
@@ -278,7 +289,7 @@ export class Person {
|
|
|
278
289
|
@GET
|
|
279
290
|
static async get(id: number, @Inject env: WranglerEnv): Promise<Person> {
|
|
280
291
|
let records = await env.db
|
|
281
|
-
.prepare("SELECT * FROM [Person.default] WHERE [
|
|
292
|
+
.prepare("SELECT * FROM [Person.default] WHERE [id] = ?") // Person.default is the SQL view generated from the IncludeTree
|
|
282
293
|
.bind(id)
|
|
283
294
|
.run();
|
|
284
295
|
|
|
@@ -288,7 +299,97 @@ export class Person {
|
|
|
288
299
|
}
|
|
289
300
|
```
|
|
290
301
|
|
|
291
|
-
Note that the `get` code can be simplified using CRUD methods or ORM
|
|
302
|
+
Note that the `get` code can be simplified using CRUD methods or the ORM primitive `get`.
|
|
303
|
+
|
|
304
|
+
#### View Aliasing
|
|
305
|
+
|
|
306
|
+
The generated views will always be aliased so that they can be accessed in an object like notation. For example, given some `Horse` that has a relationship with `Like`:
|
|
307
|
+
|
|
308
|
+
```ts
|
|
309
|
+
@D1
|
|
310
|
+
export class Horse {
|
|
311
|
+
@PrimaryKey
|
|
312
|
+
id: Integer;
|
|
313
|
+
|
|
314
|
+
name: string;
|
|
315
|
+
bio: string | null;
|
|
316
|
+
|
|
317
|
+
@OneToMany("horseId1")
|
|
318
|
+
likes: Like[];
|
|
319
|
+
|
|
320
|
+
@DataSource
|
|
321
|
+
static readonly default: IncludeTree<Horse> = {
|
|
322
|
+
likes: { horse2: {} },
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
@D1
|
|
327
|
+
export class Like {
|
|
328
|
+
@PrimaryKey
|
|
329
|
+
id: Integer;
|
|
330
|
+
|
|
331
|
+
@ForeignKey(Horse)
|
|
332
|
+
horseId1: Integer;
|
|
333
|
+
|
|
334
|
+
@ForeignKey(Horse)
|
|
335
|
+
horseId2: Integer;
|
|
336
|
+
|
|
337
|
+
@OneToOne("horseId2")
|
|
338
|
+
horse2: Horse | undefined;
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
If you wanted to find all horses that like one another, a valid SQL query using the `default` data source would look like:
|
|
343
|
+
|
|
344
|
+
```sql
|
|
345
|
+
SELECT * FROM [Horse.default] as H1
|
|
346
|
+
WHERE
|
|
347
|
+
H1.[id] = ?
|
|
348
|
+
AND EXISTS (
|
|
349
|
+
SELECT 1
|
|
350
|
+
FROM [Horse.default] AS H2
|
|
351
|
+
WHERE H2.[id] = H1.[likes.horse2.id]
|
|
352
|
+
AND H2.[likes.horse2.id] = H1.[id]
|
|
353
|
+
);
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
The actual generated view for `default` looks like:
|
|
357
|
+
|
|
358
|
+
```sql
|
|
359
|
+
CREATE VIEW IF NOT EXISTS "Horse.default" AS
|
|
360
|
+
SELECT
|
|
361
|
+
"Horse"."id" AS "id",
|
|
362
|
+
"Horse"."name" AS "name",
|
|
363
|
+
"Horse"."bio" AS "bio",
|
|
364
|
+
"Like"."id" AS "likes.id",
|
|
365
|
+
"Like"."horseId1" AS "likes.horseId1",
|
|
366
|
+
"Like"."horseId2" AS "likes.horseId2",
|
|
367
|
+
"Horse1"."id" AS "likes.horse2.id",
|
|
368
|
+
"Horse1"."name" AS "likes.horse2.name",
|
|
369
|
+
"Horse1"."bio" AS "likes.horse2.bio"
|
|
370
|
+
FROM
|
|
371
|
+
"Horse"
|
|
372
|
+
LEFT JOIN
|
|
373
|
+
"Like" ON "Horse"."id" = "Like"."horseId1"
|
|
374
|
+
LEFT JOIN
|
|
375
|
+
"Horse" AS "Horse1" ON "Like"."horseId2" = "Horse1"."id";
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
#### DataSourceOf<T>
|
|
379
|
+
|
|
380
|
+
If it is important to determine what data source the frontend called the instantiated method with, the type `DataSourceOf<T>` allows explicit data source parameters:
|
|
381
|
+
|
|
382
|
+
```ts
|
|
383
|
+
@D1
|
|
384
|
+
class Foo {
|
|
385
|
+
...
|
|
386
|
+
|
|
387
|
+
@POST
|
|
388
|
+
bar(ds: DataSourceOf<Foo>) {
|
|
389
|
+
// ds = "DataSource1" | "DataSource2" | ... | "none"
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
```
|
|
292
393
|
|
|
293
394
|
### One to Many
|
|
294
395
|
|
|
@@ -415,6 +516,65 @@ static async get(
|
|
|
415
516
|
): Promise<HttpResult<CrudHaver>>
|
|
416
517
|
```
|
|
417
518
|
|
|
519
|
+
### Middleware
|
|
520
|
+
|
|
521
|
+
Cloesce supports middleware at the global level (before routing to a model+method), the model level (before hydration) and the method level (before hydration). Middleware also exposes read/write access to the dependency injection instance that all models use.
|
|
522
|
+
|
|
523
|
+
Middleware is capable of exiting from the Cloesce Router early with an HTTP Result.
|
|
524
|
+
|
|
525
|
+
An example of all levels of middleware is below. All middleware must be defined in the file `app.cloesce.ts`.
|
|
526
|
+
|
|
527
|
+
```ts
|
|
528
|
+
@PlainOldObject
|
|
529
|
+
export class InjectedThing {
|
|
530
|
+
value: string;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
@WranglerEnv
|
|
534
|
+
export class Env {
|
|
535
|
+
db: D1Database;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
@D1
|
|
539
|
+
@CRUD(["POST"])
|
|
540
|
+
export class Model {
|
|
541
|
+
@PrimaryKey
|
|
542
|
+
id: number;
|
|
543
|
+
|
|
544
|
+
@GET
|
|
545
|
+
static blockedMethod() {}
|
|
546
|
+
|
|
547
|
+
@GET
|
|
548
|
+
static getInjectedThing(@Inject thing: InjectedThing): InjectedThing {
|
|
549
|
+
return thing;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Middleware instance
|
|
554
|
+
const app: CloesceApp = new CloesceApp();
|
|
555
|
+
|
|
556
|
+
app.useGlobal((request: Request, env, ir) => {
|
|
557
|
+
if (request.method === "POST") {
|
|
558
|
+
return { ok: false, status: 401, message: "POST methods aren't allowed." };
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
app.useModel(Model, (request, env, ir) => {
|
|
563
|
+
ir.set(InjectedThing.name, {
|
|
564
|
+
value: "hello world",
|
|
565
|
+
});
|
|
566
|
+
});
|
|
567
|
+
|
|
568
|
+
app.useMethod(Model, "blockedMethod", (request, env, ir) => {
|
|
569
|
+
return { ok: false, status: 401, message: "Blocked method" };
|
|
570
|
+
});
|
|
571
|
+
|
|
572
|
+
// Exporting the instance is required
|
|
573
|
+
export default app;
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
With this middleware, all POST methods will be blocked, and all methods for the model `Model` will be able to inject `InjectedThing`. Additionally, on the method level, `blockedMethod` will return a 401.
|
|
577
|
+
|
|
418
578
|
### Plain Old Objects
|
|
419
579
|
|
|
420
580
|
Simple non-model objects can be returned and serialized from a model method:
|
package/dist/cli.js
CHANGED
|
@@ -189,11 +189,11 @@ async function extract(opts) {
|
|
|
189
189
|
const json = JSON.stringify(ast, null, 4);
|
|
190
190
|
fs.mkdirSync(path.dirname(outPath), { recursive: true });
|
|
191
191
|
fs.writeFileSync(outPath, json);
|
|
192
|
-
console.log(`CIDL
|
|
192
|
+
console.log(`CIDL extracted to ${outPath}`);
|
|
193
193
|
return { outPath, projectName: cloesceProjectName };
|
|
194
194
|
}
|
|
195
195
|
catch (err) {
|
|
196
|
-
console.error("Critical uncaught error.
|
|
196
|
+
console.error("Critical uncaught error in generator. \nSubmit a ticket to https://github.com/bens-schreiber/cloesce\n\n", err?.message ?? "No error message.", "\n", err?.stack ?? "No error stack.");
|
|
197
197
|
process.exit(1);
|
|
198
198
|
}
|
|
199
199
|
}
|
|
@@ -293,10 +293,13 @@ function formatErr(e) {
|
|
|
293
293
|
const { description, suggestion } = getErrorInfo(e.code);
|
|
294
294
|
const contextLine = e.context ? `Context: ${e.context}\n` : "";
|
|
295
295
|
const snippetLine = e.snippet ? `${e.snippet}\n\n` : "";
|
|
296
|
-
return
|
|
296
|
+
return `
|
|
297
|
+
==== CLOESCE ERROR ====
|
|
297
298
|
Error [${ExtractorErrorCode[e.code]}]: ${description}
|
|
298
299
|
Phase: TypeScript IDL Extraction
|
|
299
|
-
${contextLine}${snippetLine}Suggested fix: ${suggestion}
|
|
300
|
+
${contextLine}${snippetLine}Suggested fix: ${suggestion}
|
|
301
|
+
|
|
302
|
+
`;
|
|
300
303
|
}
|
|
301
304
|
run(cmds, process.argv.slice(2)).catch((err) => {
|
|
302
305
|
console.error(err);
|
package/dist/common.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
[K in keyof T]?:
|
|
3
|
-
} : T;
|
|
1
|
+
type DeepPartialInner<T> = T extends (infer U)[] ? DeepPartialInner<U>[] : T extends object ? {
|
|
2
|
+
[K in keyof T]?: DeepPartialInner<T[K]>;
|
|
3
|
+
} : T | (null extends T ? null : never);
|
|
4
|
+
export type DeepPartial<T> = DeepPartialInner<T> & {
|
|
5
|
+
__brand?: "Partial";
|
|
6
|
+
};
|
|
4
7
|
export type Either<L, R> = {
|
|
5
8
|
ok: false;
|
|
6
9
|
value: L;
|
|
@@ -15,7 +18,7 @@ export declare enum ExtractorErrorCode {
|
|
|
15
18
|
AppMissingDefaultExport = 1,
|
|
16
19
|
UnknownType = 2,
|
|
17
20
|
MultipleGenericType = 3,
|
|
18
|
-
|
|
21
|
+
InvalidDataSourceDefinition = 4,
|
|
19
22
|
InvalidPartialType = 5,
|
|
20
23
|
InvalidIncludeTree = 6,
|
|
21
24
|
InvalidAttributeModifier = 7,
|
|
@@ -25,9 +28,10 @@ export declare enum ExtractorErrorCode {
|
|
|
25
28
|
MissingNavigationPropertyReference = 11,
|
|
26
29
|
MissingManyToManyUniqueId = 12,
|
|
27
30
|
MissingPrimaryKey = 13,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
MissingDatabaseBinding = 14,
|
|
32
|
+
MissingWranglerEnv = 15,
|
|
33
|
+
TooManyWranglerEnvs = 16,
|
|
34
|
+
MissingFile = 17
|
|
31
35
|
}
|
|
32
36
|
export declare function getErrorInfo(code: ExtractorErrorCode): {
|
|
33
37
|
description: string;
|
|
@@ -69,7 +73,7 @@ export declare class CloesceApp {
|
|
|
69
73
|
useMethod<T>(ctor: new () => T, method: KeysOfType<T, (...args: any) => any>, m: MiddlewareFn): void;
|
|
70
74
|
}
|
|
71
75
|
export type CrudKind = "POST" | "GET" | "LIST";
|
|
72
|
-
export type CidlType = "Void" | "Integer" | "Real" | "Text" | "Blob" | {
|
|
76
|
+
export type CidlType = "Void" | "Integer" | "Real" | "Text" | "Blob" | "DateIso" | "Boolean" | {
|
|
73
77
|
DataSource: string;
|
|
74
78
|
} | {
|
|
75
79
|
Inject: string;
|
|
@@ -151,6 +155,7 @@ export interface DataSource {
|
|
|
151
155
|
export interface WranglerEnv {
|
|
152
156
|
name: string;
|
|
153
157
|
source_path: string;
|
|
158
|
+
db_binding: string;
|
|
154
159
|
}
|
|
155
160
|
export interface CloesceAst {
|
|
156
161
|
version: string;
|
|
@@ -161,4 +166,5 @@ export interface CloesceAst {
|
|
|
161
166
|
poos: Record<string, PlainOldObject>;
|
|
162
167
|
app_source: string | null;
|
|
163
168
|
}
|
|
169
|
+
export {};
|
|
164
170
|
//# sourceMappingURL=common.d.ts.map
|
package/dist/common.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../src/common.ts"],"names":[],"mappings":"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"}
|
package/dist/common.js
CHANGED
|
@@ -10,7 +10,7 @@ export var ExtractorErrorCode;
|
|
|
10
10
|
ExtractorErrorCode[ExtractorErrorCode["AppMissingDefaultExport"] = 1] = "AppMissingDefaultExport";
|
|
11
11
|
ExtractorErrorCode[ExtractorErrorCode["UnknownType"] = 2] = "UnknownType";
|
|
12
12
|
ExtractorErrorCode[ExtractorErrorCode["MultipleGenericType"] = 3] = "MultipleGenericType";
|
|
13
|
-
ExtractorErrorCode[ExtractorErrorCode["
|
|
13
|
+
ExtractorErrorCode[ExtractorErrorCode["InvalidDataSourceDefinition"] = 4] = "InvalidDataSourceDefinition";
|
|
14
14
|
ExtractorErrorCode[ExtractorErrorCode["InvalidPartialType"] = 5] = "InvalidPartialType";
|
|
15
15
|
ExtractorErrorCode[ExtractorErrorCode["InvalidIncludeTree"] = 6] = "InvalidIncludeTree";
|
|
16
16
|
ExtractorErrorCode[ExtractorErrorCode["InvalidAttributeModifier"] = 7] = "InvalidAttributeModifier";
|
|
@@ -20,9 +20,10 @@ export var ExtractorErrorCode;
|
|
|
20
20
|
ExtractorErrorCode[ExtractorErrorCode["MissingNavigationPropertyReference"] = 11] = "MissingNavigationPropertyReference";
|
|
21
21
|
ExtractorErrorCode[ExtractorErrorCode["MissingManyToManyUniqueId"] = 12] = "MissingManyToManyUniqueId";
|
|
22
22
|
ExtractorErrorCode[ExtractorErrorCode["MissingPrimaryKey"] = 13] = "MissingPrimaryKey";
|
|
23
|
-
ExtractorErrorCode[ExtractorErrorCode["
|
|
24
|
-
ExtractorErrorCode[ExtractorErrorCode["
|
|
25
|
-
ExtractorErrorCode[ExtractorErrorCode["
|
|
23
|
+
ExtractorErrorCode[ExtractorErrorCode["MissingDatabaseBinding"] = 14] = "MissingDatabaseBinding";
|
|
24
|
+
ExtractorErrorCode[ExtractorErrorCode["MissingWranglerEnv"] = 15] = "MissingWranglerEnv";
|
|
25
|
+
ExtractorErrorCode[ExtractorErrorCode["TooManyWranglerEnvs"] = 16] = "TooManyWranglerEnvs";
|
|
26
|
+
ExtractorErrorCode[ExtractorErrorCode["MissingFile"] = 17] = "MissingFile";
|
|
26
27
|
})(ExtractorErrorCode || (ExtractorErrorCode = {}));
|
|
27
28
|
const errorInfoMap = {
|
|
28
29
|
[ExtractorErrorCode.MissingExport]: {
|
|
@@ -45,9 +46,9 @@ const errorInfoMap = {
|
|
|
45
46
|
description: "Cloesce does not yet support types with multiple generics",
|
|
46
47
|
suggestion: "Simplify your type to use only a single generic parameter, ie Foo<T>",
|
|
47
48
|
},
|
|
48
|
-
[ExtractorErrorCode.
|
|
49
|
-
description: "Data Sources must be
|
|
50
|
-
suggestion: "Declare your data source as `static readonly
|
|
49
|
+
[ExtractorErrorCode.InvalidDataSourceDefinition]: {
|
|
50
|
+
description: "Data Sources must be explicitly typed as a static Include Tree",
|
|
51
|
+
suggestion: "Declare your data source as `static readonly _: IncludeTree<Model>`",
|
|
51
52
|
},
|
|
52
53
|
[ExtractorErrorCode.InvalidIncludeTree]: {
|
|
53
54
|
description: "Invalid Include Tree",
|
|
@@ -81,6 +82,10 @@ const errorInfoMap = {
|
|
|
81
82
|
description: "Missing primary key on a model",
|
|
82
83
|
suggestion: "Add a primary key field to your model (e.g., `id: number`)",
|
|
83
84
|
},
|
|
85
|
+
[ExtractorErrorCode.MissingDatabaseBinding]: {
|
|
86
|
+
description: "Missing a database binding in the WranglerEnv definition",
|
|
87
|
+
suggestion: "Add a `D1Database` to your WranglerEnv",
|
|
88
|
+
},
|
|
84
89
|
[ExtractorErrorCode.MissingWranglerEnv]: {
|
|
85
90
|
description: "Missing a wrangler environment definition in the project",
|
|
86
91
|
suggestion: "Add a @WranglerEnv class in your project.",
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { Project } from "ts-morph";
|
|
2
|
-
import { CloesceAst, Either, ExtractorError } from "../common.js";
|
|
1
|
+
import { Project, Type, SourceFile, MethodDeclaration, ClassDeclaration, Expression } from "ts-morph";
|
|
2
|
+
import { CidlIncludeTree, CloesceAst, CidlType, Either, HttpVerb, Model, ModelMethod, NamedTypedValue, WranglerEnv, ExtractorError, PlainOldObject, CrudKind } from "../common.js";
|
|
3
3
|
export declare class CidlExtractor {
|
|
4
4
|
projectName: string;
|
|
5
5
|
version: string;
|
|
6
6
|
constructor(projectName: string, version: string);
|
|
7
7
|
extract(project: Project): Either<ExtractorError, CloesceAst>;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
static app(sourceFile: SourceFile): Either<ExtractorError, string>;
|
|
9
|
+
static model(classDecl: ClassDeclaration, sourceFile: SourceFile): Either<ExtractorError, Model>;
|
|
10
|
+
static poo(classDecl: ClassDeclaration, sourceFile: SourceFile): Either<ExtractorError, PlainOldObject>;
|
|
11
|
+
static env(classDecl: ClassDeclaration, sourceFile: SourceFile): Either<ExtractorError, WranglerEnv>;
|
|
11
12
|
private static readonly primTypeMap;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
static cidlType(type: Type, inject?: boolean): Either<ExtractorError, CidlType>;
|
|
14
|
+
static includeTree(expr: Expression | undefined, currentClass: ClassDeclaration, sf: SourceFile): Either<ExtractorError, CidlIncludeTree>;
|
|
15
|
+
static method(modelName: string, method: MethodDeclaration, httpVerb: HttpVerb): Either<ExtractorError, ModelMethod>;
|
|
16
|
+
static crudMethod(crud: CrudKind, primaryKey: NamedTypedValue, modelName: string): ModelMethod;
|
|
16
17
|
}
|
|
17
18
|
//# sourceMappingURL=extract.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/extractor/extract.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,OAAO,
|
|
1
|
+
{"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/extractor/extract.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,OAAO,EACP,IAAI,EACJ,UAAU,EAEV,iBAAiB,EAEjB,gBAAgB,EAEhB,UAAU,EAEX,MAAM,UAAU,CAAC;AAElB,OAAO,EACL,eAAe,EACf,UAAU,EACV,QAAQ,EAER,MAAM,EACN,QAAQ,EACR,KAAK,EAEL,WAAW,EACX,eAAe,EAEf,WAAW,EAGX,cAAc,EAEd,cAAc,EAEd,QAAQ,EACT,MAAM,cAAc,CAAC;AAuBtB,qBAAa,aAAa;IAEf,WAAW,EAAE,MAAM;IACnB,OAAO,EAAE,MAAM;gBADf,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM;IAGxB,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,cAAc,EAAE,UAAU,CAAC;IA8F7D,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC;IA8BlE,MAAM,CAAC,KAAK,CACV,SAAS,EAAE,gBAAgB,EAC3B,UAAU,EAAE,UAAU,GACrB,MAAM,CAAC,cAAc,EAAE,KAAK,CAAC;IAsQhC,MAAM,CAAC,GAAG,CACR,SAAS,EAAE,gBAAgB,EAC3B,UAAU,EAAE,UAAU,GACrB,MAAM,CAAC,cAAc,EAAE,cAAc,CAAC;IAmCzC,MAAM,CAAC,GAAG,CACR,SAAS,EAAE,gBAAgB,EAC3B,UAAU,EAAE,UAAU,GACrB,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC;IAuBtC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CASjC;IAEF,MAAM,CAAC,QAAQ,CACb,IAAI,EAAE,IAAI,EACV,MAAM,GAAE,OAAe,GACtB,MAAM,CAAC,cAAc,EAAE,QAAQ,CAAC;IAsJnC,MAAM,CAAC,WAAW,CAChB,IAAI,EAAE,UAAU,GAAG,SAAS,EAC5B,YAAY,EAAE,gBAAgB,EAC9B,EAAE,EAAE,UAAU,GACb,MAAM,CAAC,cAAc,EAAE,eAAe,CAAC;IAiF1C,MAAM,CAAC,MAAM,CACX,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,iBAAiB,EACzB,QAAQ,EAAE,QAAQ,GACjB,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC;IA2EtC,MAAM,CAAC,UAAU,CACf,IAAI,EAAE,QAAQ,EACd,UAAU,EAAE,eAAe,EAC3B,SAAS,EAAE,MAAM,GAChB,WAAW;CAkDf"}
|
|
@@ -73,8 +73,6 @@ export class CidlExtractor {
|
|
|
73
73
|
continue;
|
|
74
74
|
}
|
|
75
75
|
if (hasDecorator(classDecl, ClassDecoratorKind.WranglerEnv)) {
|
|
76
|
-
if (!classDecl.isExported())
|
|
77
|
-
return notExportedErr;
|
|
78
76
|
// Error: invalid attribute modifier
|
|
79
77
|
for (const prop of classDecl.getProperties()) {
|
|
80
78
|
const modifierRes = checkAttributeModifier(prop);
|
|
@@ -82,10 +80,11 @@ export class CidlExtractor {
|
|
|
82
80
|
return modifierRes;
|
|
83
81
|
}
|
|
84
82
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
83
|
+
const result = CidlExtractor.env(classDecl, sourceFile);
|
|
84
|
+
if (!result.ok) {
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
wranglerEnvs.push(result.value);
|
|
89
88
|
}
|
|
90
89
|
}
|
|
91
90
|
}
|
|
@@ -114,13 +113,14 @@ export class CidlExtractor {
|
|
|
114
113
|
return err(ExtractorErrorCode.AppMissingDefaultExport);
|
|
115
114
|
}
|
|
116
115
|
const getTypeText = () => {
|
|
116
|
+
let type = undefined;
|
|
117
117
|
if (MorphNode.isExportAssignment(decl)) {
|
|
118
|
-
|
|
118
|
+
type = decl.getExpression()?.getType();
|
|
119
119
|
}
|
|
120
120
|
if (MorphNode.isVariableDeclaration(decl)) {
|
|
121
|
-
|
|
121
|
+
type = decl.getInitializer()?.getType();
|
|
122
122
|
}
|
|
123
|
-
return undefined;
|
|
123
|
+
return type?.getText(undefined, TypeFormatFlags.UseAliasDefinedOutsideCurrentScope);
|
|
124
124
|
};
|
|
125
125
|
const typeText = getTypeText();
|
|
126
126
|
if (typeText === CloesceApp.name) {
|
|
@@ -172,15 +172,15 @@ export class CidlExtractor {
|
|
|
172
172
|
}
|
|
173
173
|
// TODO: Limiting to one decorator. Can't get too fancy on us.
|
|
174
174
|
const decorator = decorators[0];
|
|
175
|
-
const
|
|
175
|
+
const decoratorName = getDecoratorName(decorator);
|
|
176
176
|
// Error: invalid attribute modifier
|
|
177
177
|
if (checkModifierRes !== undefined &&
|
|
178
|
-
|
|
178
|
+
decoratorName !== AttributeDecoratorKind.DataSource) {
|
|
179
179
|
return checkModifierRes;
|
|
180
180
|
}
|
|
181
|
-
// Process
|
|
181
|
+
// Process decorator
|
|
182
182
|
const cidl_type = typeRes.value;
|
|
183
|
-
switch (
|
|
183
|
+
switch (decoratorName) {
|
|
184
184
|
case AttributeDecoratorKind.PrimaryKey: {
|
|
185
185
|
primary_key = {
|
|
186
186
|
name: prop.getName(),
|
|
@@ -270,9 +270,12 @@ export class CidlExtractor {
|
|
|
270
270
|
break;
|
|
271
271
|
}
|
|
272
272
|
case AttributeDecoratorKind.DataSource: {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
273
|
+
const isIncludeTree = prop
|
|
274
|
+
.getType()
|
|
275
|
+
.getText(undefined, TypeFormatFlags.UseAliasDefinedOutsideCurrentScope) === `IncludeTree<${name}>`;
|
|
276
|
+
// Error: data sources must be static include trees
|
|
277
|
+
if (!prop.isStatic() || !isIncludeTree) {
|
|
278
|
+
return err(ExtractorErrorCode.InvalidDataSourceDefinition, (e) => {
|
|
276
279
|
e.snippet = prop.getText();
|
|
277
280
|
e.context = prop.getName();
|
|
278
281
|
});
|
|
@@ -358,13 +361,30 @@ export class CidlExtractor {
|
|
|
358
361
|
source_path: sourceFile.getFilePath().toString(),
|
|
359
362
|
});
|
|
360
363
|
}
|
|
364
|
+
static env(classDecl, sourceFile) {
|
|
365
|
+
const binding = classDecl.getProperties().find((p) => {
|
|
366
|
+
return (p
|
|
367
|
+
.getType()
|
|
368
|
+
.getText(undefined, TypeFormatFlags.UseAliasDefinedOutsideCurrentScope) === "D1Database");
|
|
369
|
+
});
|
|
370
|
+
if (!binding) {
|
|
371
|
+
return err(ExtractorErrorCode.MissingDatabaseBinding);
|
|
372
|
+
}
|
|
373
|
+
return right({
|
|
374
|
+
name: classDecl.getName(),
|
|
375
|
+
source_path: sourceFile.getFilePath().toString(),
|
|
376
|
+
db_binding: binding.getName(),
|
|
377
|
+
});
|
|
378
|
+
}
|
|
361
379
|
static primTypeMap = {
|
|
362
|
-
number: "
|
|
363
|
-
Number: "
|
|
380
|
+
number: "Real",
|
|
381
|
+
Number: "Real",
|
|
382
|
+
Integer: "Integer",
|
|
364
383
|
string: "Text",
|
|
365
384
|
String: "Text",
|
|
366
|
-
boolean: "
|
|
367
|
-
Boolean: "
|
|
385
|
+
boolean: "Boolean",
|
|
386
|
+
Boolean: "Boolean",
|
|
387
|
+
Date: "DateIso",
|
|
368
388
|
};
|
|
369
389
|
static cidlType(type, inject = false) {
|
|
370
390
|
// Void
|
|
@@ -457,13 +477,17 @@ export class CidlExtractor {
|
|
|
457
477
|
return right(wrapNullable(wrapper(res.value), isNullable));
|
|
458
478
|
}
|
|
459
479
|
function unwrapNullable(ty) {
|
|
460
|
-
if (ty.isUnion())
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
480
|
+
if (!ty.isUnion())
|
|
481
|
+
return [ty, false];
|
|
482
|
+
const unions = ty.getUnionTypes();
|
|
483
|
+
const nonNulls = unions.filter((t) => !t.isNull() && !t.isUndefined());
|
|
484
|
+
const hasNullable = nonNulls.length < unions.length;
|
|
485
|
+
// Booleans seperate into [null, true, false] from the `getUnionTypes` call
|
|
486
|
+
if (nonNulls.length === 2 &&
|
|
487
|
+
nonNulls.every((t) => t.isBooleanLiteral())) {
|
|
488
|
+
return [nonNulls[0].getApparentType(), hasNullable];
|
|
465
489
|
}
|
|
466
|
-
return [ty,
|
|
490
|
+
return [nonNulls[0] ?? ty, hasNullable];
|
|
467
491
|
}
|
|
468
492
|
}
|
|
469
493
|
static includeTree(expr, currentClass, sf) {
|
|
@@ -558,8 +582,7 @@ export class CidlExtractor {
|
|
|
558
582
|
typeRes.value.context = param.getName();
|
|
559
583
|
return typeRes;
|
|
560
584
|
}
|
|
561
|
-
|
|
562
|
-
if (typeof rootType !== "string" && "DataSource" in rootType) {
|
|
585
|
+
if (typeof typeRes.value !== "string" && "DataSource" in typeRes.value) {
|
|
563
586
|
needsDataSource = false;
|
|
564
587
|
}
|
|
565
588
|
parameters.push({
|
package/dist/generator.wasm
CHANGED
|
Binary file
|
package/dist/orm.wasm
CHANGED
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,MAAM,EACN,WAAW,EAIX,UAAU,EAEV,KAAK,EAGL,UAAU,EACV,gBAAgB,EACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAwB,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC;;;;;GAKG;AACH,KAAK,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC;AAE9D;;;GAGG;AACH,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE/C;;GAEG;AACH,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,qBAAa,gBAAgB;aAGT,GAAG,EAAE,UAAU;aACf,mBAAmB,EAAE,wBAAwB;aAC7C,IAAI,EAAE,cAAc;IAJtC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA+B;IACtD,OAAO;WAMM,IAAI,CACf,GAAG,EAAE,UAAU,EACf,mBAAmB,EAAE,wBAAwB,EAC7C,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ;IAO7B,MAAM,CAAC,GAAG,IAAI,gBAAgB;CAG/B;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,UAAU,EACf,mBAAmB,EAAE,wBAAwB,EAC7C,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,QAAQ,CAAC,CAqFnB;AAED;;;;GAIG;AACH,iBAAS,UAAU,CACjB,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,GACf,MAAM,CACP,UAAU,EACV;IACE,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACnB,CACF,CAyCA;AAED;;;;GAIG;AACH,iBAAe,eAAe,CAC5B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,WAAW,EACnB,EAAE,EAAE,MAAM,GAAG,IAAI,GAChB,OAAO,CACR,MAAM,CAAC,UAAU,EAAE;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAC3E,CA4DA;AA2DD;;;GAGG;AACH,iBAAe,cAAc,CAC3B,OAAO,EAAE,WAAW,EACpB,gBAAgB,EAAE,gBAAgB,EAClC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAkD9B;
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/router/router.ts"],"names":[],"mappings":"AACA,OAAO,EACL,UAAU,EACV,MAAM,EACN,WAAW,EAIX,UAAU,EAEV,KAAK,EAGL,UAAU,EACV,gBAAgB,EACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAwB,MAAM,WAAW,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC;;;;;GAKG;AACH,KAAK,wBAAwB,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC;AAE9D;;;GAGG;AACH,KAAK,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE/C;;GAEG;AACH,UAAU,eAAe;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,qBAAa,gBAAgB;aAGT,GAAG,EAAE,UAAU;aACf,mBAAmB,EAAE,wBAAwB;aAC7C,IAAI,EAAE,cAAc;IAJtC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA+B;IACtD,OAAO;WAMM,IAAI,CACf,GAAG,EAAE,UAAU,EACf,mBAAmB,EAAE,wBAAwB,EAC7C,IAAI,CAAC,EAAE,WAAW,CAAC,QAAQ;IAO7B,MAAM,CAAC,GAAG,IAAI,gBAAgB;CAG/B;AAED;;;;;GAKG;AACH,wBAAsB,OAAO,CAC3B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,UAAU,EACf,GAAG,EAAE,UAAU,EACf,mBAAmB,EAAE,wBAAwB,EAC7C,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,QAAQ,CAAC,CAqFnB;AAED;;;;GAIG;AACH,iBAAS,UAAU,CACjB,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,MAAM,GACf,MAAM,CACP,UAAU,EACV;IACE,KAAK,EAAE,KAAK,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;IACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;CACnB,CACF,CAyCA;AAED;;;;GAIG;AACH,iBAAe,eAAe,CAC5B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,UAAU,EACf,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,WAAW,EACnB,EAAE,EAAE,MAAM,GAAG,IAAI,GAChB,OAAO,CACR,MAAM,CAAC,UAAU,EAAE;IAAE,MAAM,EAAE,eAAe,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAC3E,CA4DA;AA2DD;;;GAGG;AACH,iBAAe,cAAc,CAC3B,OAAO,EAAE,WAAW,EACpB,gBAAgB,EAAE,gBAAgB,EAClC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAkD9B;AAkID;;GAEG;AACH,eAAO,MAAM,gBAAgB;;;;;CAK5B,CAAC"}
|
package/dist/router/router.js
CHANGED
|
@@ -200,7 +200,7 @@ async function hydrateModel(constructorRegistry, d1, model, id, dataSource) {
|
|
|
200
200
|
const missingRecord = left(errorState(404, "Record not found"));
|
|
201
201
|
const pk = model.primary_key.name;
|
|
202
202
|
const query = dataSource !== NO_DATA_SOURCE
|
|
203
|
-
? `SELECT * FROM "${model.name}.${dataSource}" WHERE "${
|
|
203
|
+
? `SELECT * FROM "${model.name}.${dataSource}" WHERE "${pk}" = ?`
|
|
204
204
|
: `SELECT * FROM "${model.name}" WHERE "${pk}" = ?`;
|
|
205
205
|
// Query DB
|
|
206
206
|
let records;
|
|
@@ -281,8 +281,11 @@ function validateCidlType(ast, value, cidlType, isPartial) {
|
|
|
281
281
|
return !Number.isNaN(Number(value));
|
|
282
282
|
case "Text":
|
|
283
283
|
return typeof value === "string";
|
|
284
|
-
case "
|
|
285
|
-
return
|
|
284
|
+
case "Boolean":
|
|
285
|
+
return typeof value === "boolean";
|
|
286
|
+
case "DateIso":
|
|
287
|
+
const date = new Date(value);
|
|
288
|
+
return !isNaN(date.getTime());
|
|
286
289
|
default:
|
|
287
290
|
return false;
|
|
288
291
|
}
|
package/dist/ui/backend.d.ts
CHANGED
|
@@ -20,10 +20,21 @@ export declare const ForeignKey: <T>(_: T | string) => PropertyDecorator;
|
|
|
20
20
|
export declare const Inject: ParameterDecorator;
|
|
21
21
|
export declare const CRUD: (_kinds: CrudKind[]) => ClassDecorator;
|
|
22
22
|
type Primitive = string | number | boolean | bigint | symbol | null | undefined;
|
|
23
|
-
export type IncludeTree<T> = T extends Primitive ? never : {
|
|
23
|
+
export type IncludeTree<T> = (T extends Primitive ? never : {
|
|
24
24
|
[K in keyof T]?: T[K] extends (infer U)[] ? IncludeTree<NonNullable<U>> : IncludeTree<NonNullable<T[K]>>;
|
|
25
|
+
}) & {
|
|
26
|
+
__brand?: "IncludeTree";
|
|
27
|
+
};
|
|
28
|
+
export type DataSourceOf<T extends object> = (KeysOfType<T, IncludeTree<T>> | "none") & {
|
|
29
|
+
__brand?: "DataSource";
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* A JavaScript `number` that signals to Cloesce the SQL table type
|
|
33
|
+
* should be of Integer
|
|
34
|
+
*/
|
|
35
|
+
export type Integer = number & {
|
|
36
|
+
__brand?: "Integer";
|
|
25
37
|
};
|
|
26
|
-
export type DataSourceOf<T extends object> = KeysOfType<T, IncludeTree<T>> | "none";
|
|
27
38
|
/**
|
|
28
39
|
* ORM functions which use metadata to translate arguments to valid SQL queries.
|
|
29
40
|
*/
|
package/dist/ui/backend.d.ts.map
CHANGED
|
@@ -1 +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,
|
|
1
|
+
{"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/ui/backend.ts"],"names":[],"mappings":"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"}
|
package/dist/ui/backend.js
CHANGED
|
@@ -154,7 +154,7 @@ export class Orm {
|
|
|
154
154
|
static getQuery(ctor, includeTree) {
|
|
155
155
|
const { ast } = RuntimeContainer.get();
|
|
156
156
|
if (includeTree) {
|
|
157
|
-
return `${this.listQuery(ctor, includeTree)} WHERE [${
|
|
157
|
+
return `${this.listQuery(ctor, includeTree)} WHERE [${ast.models[ctor.name].primary_key.name}] = ?`;
|
|
158
158
|
}
|
|
159
159
|
return `${this.listQuery(ctor, includeTree)} WHERE [${ast.models[ctor.name].primary_key.name}] = ?`;
|
|
160
160
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cloesce",
|
|
3
|
-
"version": "0.0.4-unstable.
|
|
3
|
+
"version": "0.0.4-unstable.3",
|
|
4
4
|
"description": "A tool to extract and compile TypeScript code into something wrangler can consume and deploy for D1 Databases and Cloudflare Workers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|