@lunora/codegen 1.0.0-alpha.1 → 1.0.0-alpha.10
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/__assets__/package-og.svg +1 -1
- package/dist/index.d.mts +96 -7
- package/dist/index.d.ts +96 -7
- package/dist/index.mjs +23 -22
- package/dist/packem_shared/{CONTAINERS_FILENAME-0K-pjNb8.mjs → CONTAINERS_FILENAME-DlP6YM_Q.mjs} +1 -1
- package/dist/packem_shared/{CodegenDiagnosticError-54jWDxA9.mjs → CodegenDiagnosticError-DeblMkzO.mjs} +3 -2
- package/dist/packem_shared/{emitApi-hRVC-kE7.mjs → GENERATED_HEADER-BiFXNUvo.mjs} +285 -19
- package/dist/packem_shared/{buildOpenRpcDocument-BZGY1-jT.mjs → OPENRPC_VERSION-B4i9Qp3v.mjs} +1 -1
- package/dist/packem_shared/{createCodegenProject-DGJm0_Pk.mjs → SCHEMA_SNAPSHOT_FILENAME-Bvv7qa_u.mjs} +81 -37
- package/dist/packem_shared/{buildSchemaSnapshot-DzLDbWk3.mjs → SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs} +12 -0
- package/dist/packem_shared/{discoverWorkflows-DRDQdhfq.mjs → WORKFLOWS_FILENAME-D62dcBGg.mjs} +1 -1
- package/dist/packem_shared/{buildOpenApiDocument-yHVN66Xd.mjs → buildOpenApiDocument-Cu3mZl-8.mjs} +1 -1
- package/dist/packem_shared/{discoverAuthApiCalls-C35R6z0T.mjs → discoverAuthApiCalls-CoirYbg6.mjs} +1 -1
- package/dist/packem_shared/{discoverCrons-BL6iGuJ3.mjs → discoverCrons-Cev7RRAf.mjs} +20 -17
- package/dist/packem_shared/{discoverFunctions-DEgAcRuD.mjs → discoverFunctions-BWMczzBx.mjs} +7 -2
- package/dist/packem_shared/{discoverHttpRoutes-C978pBiG.mjs → discoverHttpRoutes-CfP6cMzt.mjs} +2 -2
- package/dist/packem_shared/{discoverInserts-CRQdXvHO.mjs → discoverInserts-C7zxXkUf.mjs} +24 -2
- package/dist/packem_shared/{discoverMaskProcedures-B64zA740.mjs → discoverMaskProcedures-Cm81kwrb.mjs} +1 -1
- package/dist/packem_shared/{discoverMigrations-Doj_-BAA.mjs → discoverMigrations-Bi5nJ0mJ.mjs} +10 -4
- package/dist/packem_shared/{discoverNondeterministicCalls-4KiPQxQU.mjs → discoverNondeterministicCalls-C4M8AXmQ.mjs} +1 -1
- package/dist/packem_shared/{discoverQueries-BkIi0dBD.mjs → discoverQueries-B0wGT-xe.mjs} +1 -1
- package/dist/packem_shared/discoverR2sqlCalls-BVNMd428.mjs +80 -0
- package/dist/packem_shared/{discoverRlsMetadata-DpRB1HMe.mjs → discoverRlsMetadata-BS9GOGC5.mjs} +1 -1
- package/dist/packem_shared/{discoverSchema-BBulgGbH.mjs → discoverSchema-BnWHHJ4T.mjs} +296 -16
- package/dist/packem_shared/{discoverStorageRulesMetadata-DAqJUxUv.mjs → discoverStorageRulesMetadata-Da8BKXcI.mjs} +1 -1
- package/dist/packem_shared/{emitApp-CzZ6GbrD.mjs → emitApp-KfMaKXWe.mjs} +12 -2
- package/dist/packem_shared/{lintSchema-DicbOHvH.mjs → formatAdvisories-8NIv1k0I.mjs} +2 -1
- package/dist/packem_shared/{parse-validator-tuQtHrsr.mjs → parse-validator-Cabb60UV.mjs} +2 -1
- package/package.json +6 -6
|
@@ -1,6 +1,212 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { diagnosticAt } from './CodegenDiagnosticError-
|
|
3
|
-
import { a as parseObjectShape } from './parse-validator-
|
|
1
|
+
import { Node, SyntaxKind } from 'ts-morph';
|
|
2
|
+
import { diagnosticAt } from './CodegenDiagnosticError-DeblMkzO.mjs';
|
|
3
|
+
import { a as parseObjectShape } from './parse-validator-Cabb60UV.mjs';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
|
|
7
|
+
const renderLiteralValue = (value) => {
|
|
8
|
+
switch (typeof value) {
|
|
9
|
+
case "bigint": {
|
|
10
|
+
return value.toString();
|
|
11
|
+
}
|
|
12
|
+
case "boolean":
|
|
13
|
+
case "number": {
|
|
14
|
+
return String(value);
|
|
15
|
+
}
|
|
16
|
+
case "string": {
|
|
17
|
+
return JSON.stringify(value);
|
|
18
|
+
}
|
|
19
|
+
default: {
|
|
20
|
+
return value === null ? "null" : void 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const columnMetaToIR = (column) => {
|
|
25
|
+
const hasDefault = column?.["defaultValue"] !== void 0 || column?.["defaultFn"] !== void 0 || column?.["serverDefault"] !== void 0;
|
|
26
|
+
return {
|
|
27
|
+
...hasDefault ? { hasDefault: true } : {},
|
|
28
|
+
...column?.["onUpdateFn"] === void 0 ? {} : { hasOnUpdate: true },
|
|
29
|
+
notNull: column?.["notNull"] ?? true,
|
|
30
|
+
...column?.["unique"] === true ? { unique: true } : {}
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
const runtimeValidatorToIR = (validator) => {
|
|
34
|
+
const meta = validator?._meta ?? {};
|
|
35
|
+
const kind = validator?.kind ?? "unknown";
|
|
36
|
+
const ir = { column: columnMetaToIR(meta["column"]), kind };
|
|
37
|
+
switch (kind) {
|
|
38
|
+
case "array":
|
|
39
|
+
case "optional": {
|
|
40
|
+
ir.inner = runtimeValidatorToIR(meta["inner"]);
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
case "id": {
|
|
44
|
+
ir.tableName = meta["tableName"];
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
case "literal": {
|
|
48
|
+
ir.literalValue = renderLiteralValue(meta["value"]);
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
case "object": {
|
|
52
|
+
const shape = meta["shape"] ?? {};
|
|
53
|
+
ir.shape = Object.fromEntries(Object.entries(shape).map(([name, child]) => [name, runtimeValidatorToIR(child)]));
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
case "record": {
|
|
57
|
+
ir.valueType = runtimeValidatorToIR(meta["valueValidator"]);
|
|
58
|
+
if (meta["keyValidator"] !== void 0) {
|
|
59
|
+
ir.keyType = runtimeValidatorToIR(meta["keyValidator"]);
|
|
60
|
+
}
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
case "storage": {
|
|
64
|
+
if (typeof meta["bucket"] === "string") {
|
|
65
|
+
ir.bucket = meta["bucket"];
|
|
66
|
+
}
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
case "union": {
|
|
70
|
+
const members = meta["members"] ?? [];
|
|
71
|
+
ir.members = members.map((member) => runtimeValidatorToIR(member));
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return ir;
|
|
76
|
+
};
|
|
77
|
+
const shardModeToIR = (shardMode) => {
|
|
78
|
+
if (shardMode?.kind === "global") {
|
|
79
|
+
return "global";
|
|
80
|
+
}
|
|
81
|
+
if (shardMode?.kind === "shardBy" && typeof shardMode.field === "string") {
|
|
82
|
+
return { field: shardMode.field, kind: "shardBy" };
|
|
83
|
+
}
|
|
84
|
+
return "root";
|
|
85
|
+
};
|
|
86
|
+
const warnDroppedTableFeatures = (builder, bareName) => {
|
|
87
|
+
const dropped = [];
|
|
88
|
+
if (builder.relationMap && Object.keys(builder.relationMap).length > 0) {
|
|
89
|
+
dropped.push("relations");
|
|
90
|
+
}
|
|
91
|
+
if (builder.rankIndexes && builder.rankIndexes.length > 0) {
|
|
92
|
+
dropped.push("rank indexes");
|
|
93
|
+
}
|
|
94
|
+
if (builder.vectorIndexes && builder.vectorIndexes.length > 0) {
|
|
95
|
+
dropped.push("vector indexes");
|
|
96
|
+
}
|
|
97
|
+
if (dropped.length > 0) {
|
|
98
|
+
console.warn(
|
|
99
|
+
`@lunora/codegen: package schema-extension table "${bareName}" declares ${dropped.join(" + ")}, which are not yet introspected from a node_modules extension — they will be absent from the generated types.`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const runtimeTableToIR = (builder, bareName) => {
|
|
104
|
+
const shape = builder.shape ?? {};
|
|
105
|
+
const indexes = (builder.indexes ?? []).map((index) => {
|
|
106
|
+
return { fields: index.fields, name: index.name, ...index.unique ? { unique: true } : {} };
|
|
107
|
+
});
|
|
108
|
+
warnDroppedTableFeatures(builder, bareName);
|
|
109
|
+
return {
|
|
110
|
+
...builder.isExternallyManaged ? { externallyManaged: true } : {},
|
|
111
|
+
indexes,
|
|
112
|
+
name: bareName,
|
|
113
|
+
rankIndexes: [],
|
|
114
|
+
relations: [],
|
|
115
|
+
searchIndexes: (builder.searchIndexes ?? []).map((index) => {
|
|
116
|
+
return {
|
|
117
|
+
field: index.field,
|
|
118
|
+
...index.filterFields ? { filterFields: index.filterFields } : {},
|
|
119
|
+
name: index.name
|
|
120
|
+
};
|
|
121
|
+
}),
|
|
122
|
+
shape: Object.fromEntries(Object.entries(shape).map(([name, validator]) => [name, runtimeValidatorToIR(validator)])),
|
|
123
|
+
shardMode: shardModeToIR(builder.shardMode),
|
|
124
|
+
// Inline vector/rank indexes and relations are not yet introspected from a
|
|
125
|
+
// package extension; their presence is surfaced via `warnDroppedTableFeatures`.
|
|
126
|
+
vectorIndexes: []
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
const resolvedExtensionToIR = (value) => {
|
|
130
|
+
const { key, tables } = value;
|
|
131
|
+
if (typeof key !== "string" || typeof tables !== "object" || tables === null) {
|
|
132
|
+
return void 0;
|
|
133
|
+
}
|
|
134
|
+
const bareTables = Object.entries(tables).map(([bareName, builder]) => runtimeTableToIR(builder, bareName));
|
|
135
|
+
const vectorIndexes = value["vectorIndexes"] ?? {};
|
|
136
|
+
const bareVectorIndexes = Object.entries(vectorIndexes ?? {}).map(([name, index]) => {
|
|
137
|
+
return {
|
|
138
|
+
...index.dimensions === void 0 ? {} : { dimensions: index.dimensions },
|
|
139
|
+
...index.field === void 0 ? {} : { field: index.field },
|
|
140
|
+
...index.metadata === void 0 ? {} : { metadata: index.metadata },
|
|
141
|
+
...index.metric === void 0 ? {} : { metric: index.metric },
|
|
142
|
+
name,
|
|
143
|
+
table: index.table ?? ""
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
return { bareTables, bareVectorIndexes, key };
|
|
147
|
+
};
|
|
148
|
+
const receiverIdentifierText = (argument) => {
|
|
149
|
+
if (Node.isIdentifier(argument)) {
|
|
150
|
+
return argument.getText();
|
|
151
|
+
}
|
|
152
|
+
if (Node.isPropertyAccessExpression(argument)) {
|
|
153
|
+
const receiver = argument.getExpression();
|
|
154
|
+
return Node.isIdentifier(receiver) ? receiver.getText() : void 0;
|
|
155
|
+
}
|
|
156
|
+
return void 0;
|
|
157
|
+
};
|
|
158
|
+
const accessPathOf = (argument) => {
|
|
159
|
+
const receiverName = receiverIdentifierText(argument);
|
|
160
|
+
if (receiverName === void 0) {
|
|
161
|
+
return void 0;
|
|
162
|
+
}
|
|
163
|
+
const property = Node.isPropertyAccessExpression(argument) ? argument.getName() : void 0;
|
|
164
|
+
const propertyPath = property === void 0 ? [] : [property];
|
|
165
|
+
for (const declaration of argument.getSourceFile().getImportDeclarations()) {
|
|
166
|
+
const moduleSpecifier = declaration.getModuleSpecifierValue();
|
|
167
|
+
for (const named of declaration.getNamedImports()) {
|
|
168
|
+
const localName = named.getAliasNode()?.getText() ?? named.getName();
|
|
169
|
+
if (localName === receiverName) {
|
|
170
|
+
return { importedName: named.getName(), moduleSpecifier, propertyPath };
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (declaration.getDefaultImport()?.getText() === receiverName) {
|
|
174
|
+
return { importedName: "default", moduleSpecifier, propertyPath };
|
|
175
|
+
}
|
|
176
|
+
if (declaration.getNamespaceImport()?.getText() === receiverName && property !== void 0) {
|
|
177
|
+
return { importedName: property, moduleSpecifier, propertyPath: [] };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return void 0;
|
|
181
|
+
};
|
|
182
|
+
const readExtensionValue = (module_, access) => {
|
|
183
|
+
let current = module_[access.importedName];
|
|
184
|
+
for (const segment of access.propertyPath) {
|
|
185
|
+
if (typeof current !== "object" || current === null) {
|
|
186
|
+
return void 0;
|
|
187
|
+
}
|
|
188
|
+
current = current[segment];
|
|
189
|
+
}
|
|
190
|
+
return current;
|
|
191
|
+
};
|
|
192
|
+
const resolvePackageExtension = (argument, projectRoot) => {
|
|
193
|
+
const access = accessPathOf(argument);
|
|
194
|
+
if (!access) {
|
|
195
|
+
return void 0;
|
|
196
|
+
}
|
|
197
|
+
try {
|
|
198
|
+
const projectRequire = createRequire(join(projectRoot, "noop.cjs"));
|
|
199
|
+
const resolved = projectRequire.resolve(access.moduleSpecifier);
|
|
200
|
+
const loadedModule = projectRequire(resolved);
|
|
201
|
+
const value = readExtensionValue(loadedModule, access);
|
|
202
|
+
if (typeof value !== "object" || value === null) {
|
|
203
|
+
return void 0;
|
|
204
|
+
}
|
|
205
|
+
return resolvedExtensionToIR(value);
|
|
206
|
+
} catch {
|
|
207
|
+
return void 0;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
4
210
|
|
|
5
211
|
const VECTOR_METRICS = /* @__PURE__ */ new Set(["cosine", "dot-product", "euclidean"]);
|
|
6
212
|
const ON_DELETE_ACTIONS = /* @__PURE__ */ new Set(["cascade", "restrict", "set null"]);
|
|
@@ -179,6 +385,18 @@ const parseGlobalBackend = (args) => {
|
|
|
179
385
|
}
|
|
180
386
|
return "d1";
|
|
181
387
|
};
|
|
388
|
+
const softDeleteFieldOf = (optionsArgument) => {
|
|
389
|
+
if (optionsArgument && Node.isObjectLiteralExpression(optionsArgument)) {
|
|
390
|
+
const fieldProperty = optionsArgument.getProperty("field");
|
|
391
|
+
if (fieldProperty && Node.isPropertyAssignment(fieldProperty)) {
|
|
392
|
+
const initializer = fieldProperty.getInitializer();
|
|
393
|
+
if (initializer && Node.isStringLiteral(initializer)) {
|
|
394
|
+
return initializer.getLiteralText();
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return "deletedAt";
|
|
399
|
+
};
|
|
182
400
|
const applyTableMethod = (accumulator, method, args, name) => {
|
|
183
401
|
switch (method) {
|
|
184
402
|
case "externallyManaged": {
|
|
@@ -214,6 +432,10 @@ const applyTableMethod = (accumulator, method, args, name) => {
|
|
|
214
432
|
accumulator.shardMode = { field: field && Node.isStringLiteral(field) ? field.getLiteralText() : "_unknown_", kind: "shardBy" };
|
|
215
433
|
break;
|
|
216
434
|
}
|
|
435
|
+
case "softDelete": {
|
|
436
|
+
accumulator.softDelete = { field: softDeleteFieldOf(args[0]) };
|
|
437
|
+
break;
|
|
438
|
+
}
|
|
217
439
|
case "vectorize": {
|
|
218
440
|
const vectorIndex = parseVectorizeCall(args, name);
|
|
219
441
|
if (vectorIndex) {
|
|
@@ -251,6 +473,9 @@ const parseTableBuilder = (expression, name) => {
|
|
|
251
473
|
break;
|
|
252
474
|
}
|
|
253
475
|
}
|
|
476
|
+
if (accumulator.softDelete && !(accumulator.softDelete.field in shape)) {
|
|
477
|
+
shape = { ...shape, [accumulator.softDelete.field]: { inner: { kind: "number" }, kind: "optional" } };
|
|
478
|
+
}
|
|
254
479
|
return {
|
|
255
480
|
externallyManaged: accumulator.externallyManaged,
|
|
256
481
|
globalBackend: accumulator.shardMode === "global" ? accumulator.globalBackend ?? "d1" : void 0,
|
|
@@ -261,6 +486,7 @@ const parseTableBuilder = (expression, name) => {
|
|
|
261
486
|
searchIndexes: accumulator.searchIndexes,
|
|
262
487
|
shape,
|
|
263
488
|
shardMode: accumulator.shardMode,
|
|
489
|
+
softDelete: accumulator.softDelete,
|
|
264
490
|
vectorIndexes: accumulator.vectorIndexes
|
|
265
491
|
};
|
|
266
492
|
};
|
|
@@ -354,7 +580,27 @@ const extensionTargetIdentifier = (argument) => {
|
|
|
354
580
|
return argument;
|
|
355
581
|
}
|
|
356
582
|
if (Node.isPropertyAccessExpression(argument)) {
|
|
357
|
-
|
|
583
|
+
const receiver = argument.getExpression();
|
|
584
|
+
return Node.isIdentifier(receiver) ? receiver : void 0;
|
|
585
|
+
}
|
|
586
|
+
return void 0;
|
|
587
|
+
};
|
|
588
|
+
const pluginConfigObject = (expression) => {
|
|
589
|
+
if (Node.isObjectLiteralExpression(expression)) {
|
|
590
|
+
return expression;
|
|
591
|
+
}
|
|
592
|
+
if (Node.isCallExpression(expression)) {
|
|
593
|
+
const callee = expression.getExpression();
|
|
594
|
+
let name;
|
|
595
|
+
if (Node.isIdentifier(callee)) {
|
|
596
|
+
name = callee.getText();
|
|
597
|
+
} else if (Node.isPropertyAccessExpression(callee)) {
|
|
598
|
+
name = callee.getName();
|
|
599
|
+
}
|
|
600
|
+
if (name === "definePlugin") {
|
|
601
|
+
const configArgument = expression.getArguments()[1];
|
|
602
|
+
return configArgument && Node.isObjectLiteralExpression(configArgument) ? configArgument : void 0;
|
|
603
|
+
}
|
|
358
604
|
}
|
|
359
605
|
return void 0;
|
|
360
606
|
};
|
|
@@ -363,8 +609,9 @@ const nextExpressionFromDeclaration = (declaration, argument) => {
|
|
|
363
609
|
if (!initializer) {
|
|
364
610
|
return void 0;
|
|
365
611
|
}
|
|
366
|
-
if (Node.isPropertyAccessExpression(argument)
|
|
367
|
-
|
|
612
|
+
if (Node.isPropertyAccessExpression(argument)) {
|
|
613
|
+
const configObject = pluginConfigObject(initializer);
|
|
614
|
+
return configObject ? objectPropertyInitializer(configObject, argument.getName()) : void 0;
|
|
368
615
|
}
|
|
369
616
|
return initializer;
|
|
370
617
|
};
|
|
@@ -434,24 +681,30 @@ const parseExtensionVectorIndexes = (options) => {
|
|
|
434
681
|
}
|
|
435
682
|
return parseStandaloneVectorIndexes(object);
|
|
436
683
|
};
|
|
437
|
-
const
|
|
438
|
-
const bareTables = parseExtensionTables(options);
|
|
684
|
+
const namespaceExtension = (key, bareTables, bareVectorIndexes) => {
|
|
439
685
|
const bareNames = new Set(bareTables.map((table) => table.name));
|
|
440
686
|
const tables = bareTables.map((table) => namespaceExtensionTable(table, key, bareNames));
|
|
441
|
-
const vectorIndexes =
|
|
687
|
+
const vectorIndexes = bareVectorIndexes.map((index) => {
|
|
442
688
|
return { ...index, name: prefixTableName(key, index.name), table: rewriteReference(index.table, key, bareNames) };
|
|
443
689
|
});
|
|
444
690
|
return { tables, vectorIndexes };
|
|
445
691
|
};
|
|
446
|
-
const
|
|
692
|
+
const mergeExtension = (key, options) => namespaceExtension(key, parseExtensionTables(options), parseExtensionVectorIndexes(options));
|
|
693
|
+
const mergeExtendCall = (extendCall, projectRoot) => {
|
|
447
694
|
const extendArgument = extendCall.getArguments()[0];
|
|
448
695
|
if (!extendArgument) {
|
|
449
696
|
return void 0;
|
|
450
697
|
}
|
|
451
698
|
const resolved = resolveSchemaExtensionCall(extendArgument);
|
|
452
699
|
if (!resolved) {
|
|
700
|
+
if (projectRoot !== void 0) {
|
|
701
|
+
const fromPackage = resolvePackageExtension(extendArgument, projectRoot);
|
|
702
|
+
if (fromPackage) {
|
|
703
|
+
return namespaceExtension(fromPackage.key, fromPackage.bareTables, fromPackage.bareVectorIndexes);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
453
706
|
console.warn(
|
|
454
|
-
`@lunora/codegen: skipping \`.extend(${extendArgument.getText()})\` — its \`defineSchemaExtension(...)\`
|
|
707
|
+
`@lunora/codegen: skipping \`.extend(${extendArgument.getText()})\` — its \`defineSchemaExtension(...)\` could not be resolved from local sources, and ${projectRoot === void 0 ? "no project root was available to resolve the package" : "the package could not be imported/introspected"}. Extension tables will be absent from the generated types.`
|
|
455
708
|
);
|
|
456
709
|
return void 0;
|
|
457
710
|
}
|
|
@@ -481,6 +734,33 @@ const extendCallsOf = (defineSchemaCall) => {
|
|
|
481
734
|
}
|
|
482
735
|
return calls;
|
|
483
736
|
};
|
|
737
|
+
const JURISDICTIONS = /* @__PURE__ */ new Set(["eu", "fedramp", "us"]);
|
|
738
|
+
const jurisdictionOf = (defineSchemaCall) => {
|
|
739
|
+
let current = defineSchemaCall;
|
|
740
|
+
for (; ; ) {
|
|
741
|
+
const parent = current.getParent();
|
|
742
|
+
if (!parent || !Node.isPropertyAccessExpression(parent)) {
|
|
743
|
+
break;
|
|
744
|
+
}
|
|
745
|
+
const callParent = parent.getParent();
|
|
746
|
+
if (!callParent || !Node.isCallExpression(callParent)) {
|
|
747
|
+
break;
|
|
748
|
+
}
|
|
749
|
+
if (parent.getName() === "jurisdiction") {
|
|
750
|
+
const argument = callParent.getArguments()[0];
|
|
751
|
+
if (!argument || !Node.isStringLiteral(argument)) {
|
|
752
|
+
throw diagnosticAt(callParent, '`.jurisdiction(...)` expects a string literal ("eu", "us", or "fedramp")');
|
|
753
|
+
}
|
|
754
|
+
const value = argument.getLiteralText();
|
|
755
|
+
if (!JURISDICTIONS.has(value)) {
|
|
756
|
+
throw diagnosticAt(argument, `unknown jurisdiction ${JSON.stringify(value)} — expected "eu", "us", or "fedramp"`);
|
|
757
|
+
}
|
|
758
|
+
return value;
|
|
759
|
+
}
|
|
760
|
+
current = callParent;
|
|
761
|
+
}
|
|
762
|
+
return void 0;
|
|
763
|
+
};
|
|
484
764
|
const parseBaseTables = (object) => {
|
|
485
765
|
const tables = [];
|
|
486
766
|
for (const property of object.getProperties()) {
|
|
@@ -496,11 +776,11 @@ const parseBaseTables = (object) => {
|
|
|
496
776
|
}
|
|
497
777
|
return tables;
|
|
498
778
|
};
|
|
499
|
-
const applyExtensions = (defineSchemaCall, tables) => {
|
|
779
|
+
const applyExtensions = (defineSchemaCall, tables, projectRoot) => {
|
|
500
780
|
const existingTableNames = new Set(tables.map((table) => table.name));
|
|
501
781
|
const vectorIndexes = [];
|
|
502
782
|
for (const extendCall of extendCallsOf(defineSchemaCall)) {
|
|
503
|
-
const merged = mergeExtendCall(extendCall);
|
|
783
|
+
const merged = mergeExtendCall(extendCall, projectRoot);
|
|
504
784
|
if (!merged) {
|
|
505
785
|
continue;
|
|
506
786
|
}
|
|
@@ -518,7 +798,7 @@ const applyExtensions = (defineSchemaCall, tables) => {
|
|
|
518
798
|
}
|
|
519
799
|
return vectorIndexes;
|
|
520
800
|
};
|
|
521
|
-
const discoverSchema = (project, schemaPath) => {
|
|
801
|
+
const discoverSchema = (project, schemaPath, projectRoot) => {
|
|
522
802
|
const file = project.addSourceFileAtPath(schemaPath);
|
|
523
803
|
const defineSchemaCall = file.getDescendantsOfKind(SyntaxKind.CallExpression).find((call) => {
|
|
524
804
|
const callee = call.getExpression();
|
|
@@ -534,9 +814,9 @@ const discoverSchema = (project, schemaPath) => {
|
|
|
534
814
|
const tables = parseBaseTables(argument);
|
|
535
815
|
const standaloneArgument = defineSchemaCall.getArguments()[1];
|
|
536
816
|
const standaloneVectorIndexes = standaloneArgument && Node.isObjectLiteralExpression(standaloneArgument) ? parseStandaloneVectorIndexes(standaloneArgument) : [];
|
|
537
|
-
const extensionStandaloneVectorIndexes = applyExtensions(defineSchemaCall, tables);
|
|
817
|
+
const extensionStandaloneVectorIndexes = applyExtensions(defineSchemaCall, tables, projectRoot);
|
|
538
818
|
const vectorIndexes = [...tables.flatMap((table) => table.vectorIndexes), ...standaloneVectorIndexes, ...extensionStandaloneVectorIndexes];
|
|
539
|
-
return { tables, vectorIndexes };
|
|
819
|
+
return { jurisdiction: jurisdictionOf(defineSchemaCall), tables, vectorIndexes };
|
|
540
820
|
};
|
|
541
821
|
|
|
542
822
|
export { discoverSchema as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Node } from 'ts-morph';
|
|
2
|
-
import { listLunoraSourceFiles, lunoraRelativePath, classifyProcedureCall } from './discoverFunctions-
|
|
2
|
+
import { listLunoraSourceFiles, lunoraRelativePath, classifyProcedureCall } from './discoverFunctions-BWMczzBx.mjs';
|
|
3
3
|
|
|
4
4
|
const STORAGE_OPERATIONS = /* @__PURE__ */ new Set(["delete", "list", "read", "write"]);
|
|
5
5
|
const isStorageRulesCall = (node) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GENERATED_HEADER } from './
|
|
1
|
+
import { GENERATED_HEADER } from './GENERATED_HEADER-BiFXNUvo.mjs';
|
|
2
2
|
|
|
3
3
|
const LONG_TAIL = [
|
|
4
4
|
["hasAi", "ai", "ai", "Override the Workers AI binding backing `ctx.ai` (defaults to `env.AI`)."],
|
|
@@ -13,6 +13,12 @@ const LONG_TAIL = [
|
|
|
13
13
|
["hasImages", "images", "images", "Override the Images binding backing `ctx.images` (defaults to `env.IMAGES`)."],
|
|
14
14
|
["hasKv", "kv", "kv", "Override the Workers KV binding backing `ctx.kv` (defaults to `env.KV`)."],
|
|
15
15
|
["hasPayments", "payment", "payment", "Wire the payment options backing `ctx.payments`."],
|
|
16
|
+
[
|
|
17
|
+
"hasR2sql",
|
|
18
|
+
"r2sql",
|
|
19
|
+
"r2sql",
|
|
20
|
+
"Wire the R2 SQL client backing `ctx.r2sql` — build it with `createR2Sql({ accountId, apiToken, bucket })` (defaults to env `R2_SQL_TOKEN` / `R2_SQL_ACCOUNT_ID` / `R2_SQL_BUCKET`)."
|
|
21
|
+
],
|
|
16
22
|
["hasVectors", "vectors", "vectors", "Wire the Vectorize index map backing `ctx.vectors`."]
|
|
17
23
|
];
|
|
18
24
|
const hasAnyLongTail = (options) => LONG_TAIL.some(([flag]) => options[flag]);
|
|
@@ -268,7 +274,7 @@ const buildShardFactoryBody = (options) => {
|
|
|
268
274
|
const namespace = this.schedulerDeclaration?.namespace(env);
|
|
269
275
|
const origin = this.schedulerDeclaration?.origin?.(env);
|
|
270
276
|
|
|
271
|
-
return namespace && origin ? createScheduler({ namespace, originUrl: origin }) : undefined;
|
|
277
|
+
return namespace && origin ? createScheduler({${options.jurisdiction ? ` jurisdiction: ${JSON.stringify(options.jurisdiction)},` : ""} namespace, originUrl: origin }) : undefined;
|
|
272
278
|
},
|
|
273
279
|
}
|
|
274
280
|
: {}),`
|
|
@@ -342,6 +348,10 @@ const buildWorkerOptionLines = (options) => [
|
|
|
342
348
|
const buildBaseWorkerOptions = (options) => [
|
|
343
349
|
` cronJobs: LUNORA_CRONS,`,
|
|
344
350
|
` functions: LUNORA_FUNCTIONS,`,
|
|
351
|
+
// Schema `.jurisdiction("…")` pins every DO the worker reaches to the
|
|
352
|
+
// Cloudflare data-residency region. Emitted only when declared, so apps
|
|
353
|
+
// without it keep the un-pinned global namespace (and unchanged output).
|
|
354
|
+
...options.jurisdiction ? [` jurisdiction: ${JSON.stringify(options.jurisdiction)},`] : [],
|
|
345
355
|
...options.wantsOpenApi ? [` openApiSpec,`] : [],
|
|
346
356
|
...options.wantsOpenRpc ? [` openRpcSpec,`] : [],
|
|
347
357
|
` routes: this.routeMap,`,
|
|
@@ -36,7 +36,7 @@ const toAdvisorSchema = (schema) => {
|
|
|
36
36
|
})
|
|
37
37
|
};
|
|
38
38
|
};
|
|
39
|
-
const lintSchema = (schema, queries = [], inserts, authApiCalls, rlsProcedures, containers, workflows, workflowCalls, maskProcedures, nondeterministicCalls, procedureProtections, argumentValidators, secretLiterals, sqlInterpolations, adminRoutes) => runAdvisor(
|
|
39
|
+
const lintSchema = (schema, queries = [], inserts, authApiCalls, rlsProcedures, containers, workflows, workflowCalls, maskProcedures, nondeterministicCalls, procedureProtections, argumentValidators, secretLiterals, sqlInterpolations, adminRoutes, r2sqlCalls) => runAdvisor(
|
|
40
40
|
{
|
|
41
41
|
adminRoutes,
|
|
42
42
|
argValidators: argumentValidators,
|
|
@@ -47,6 +47,7 @@ const lintSchema = (schema, queries = [], inserts, authApiCalls, rlsProcedures,
|
|
|
47
47
|
nondeterministicCalls,
|
|
48
48
|
procedureProtections,
|
|
49
49
|
queries,
|
|
50
|
+
r2sqlCalls,
|
|
50
51
|
rlsProcedures,
|
|
51
52
|
schema: toAdvisorSchema(schema),
|
|
52
53
|
secretLiterals,
|
|
@@ -124,7 +124,8 @@ const parseValidatorCall = (call) => {
|
|
|
124
124
|
}
|
|
125
125
|
if (TRANSPARENT_MODIFIERS.has(member)) {
|
|
126
126
|
const receiver = callee.getExpression();
|
|
127
|
-
|
|
127
|
+
const base = Node.isExpression(receiver) ? parseValidator(receiver) : { kind: "any" };
|
|
128
|
+
return member === "check" ? { ...base, hasRefinement: true } : base;
|
|
128
129
|
}
|
|
129
130
|
return parseBuilderMember(member, args);
|
|
130
131
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/codegen",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.10",
|
|
4
4
|
"description": "Code generator for Lunora: emits _generated/{api,server,dataModel}.ts from your schema",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@lunora/advisor": "1.0.0-alpha.
|
|
50
|
-
"@lunora/container": "1.0.0-alpha.
|
|
51
|
-
"@lunora/scheduler": "1.0.0-alpha.
|
|
52
|
-
"@lunora/values": "1.0.0-alpha.
|
|
53
|
-
"@lunora/workflow": "1.0.0-alpha.
|
|
49
|
+
"@lunora/advisor": "1.0.0-alpha.5",
|
|
50
|
+
"@lunora/container": "1.0.0-alpha.2",
|
|
51
|
+
"@lunora/scheduler": "1.0.0-alpha.2",
|
|
52
|
+
"@lunora/values": "1.0.0-alpha.2",
|
|
53
|
+
"@lunora/workflow": "1.0.0-alpha.2",
|
|
54
54
|
"ts-morph": "^28.0.0"
|
|
55
55
|
},
|
|
56
56
|
"engines": {
|