@lunora/codegen 1.0.0-alpha.16 → 1.0.0-alpha.18

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.
@@ -2,7 +2,7 @@ import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
2
2
  import { join, dirname } from 'node:path';
3
3
  import { performance } from 'node:perf_hooks';
4
4
  import { Node, SyntaxKind, Project } from 'ts-morph';
5
- import { lintSchema } from './formatAdvisories-8NIv1k0I.mjs';
5
+ import { lintSchema } from './formatAdvisories-LM8-Ixjw.mjs';
6
6
  import { listLunoraSourceFiles, lunoraRelativePath, classifyProcedureCall, discoverFunctions } from './discoverFunctions-BWMczzBx.mjs';
7
7
  import discoverAuthApiCalls from './discoverAuthApiCalls-CoirYbg6.mjs';
8
8
  import { discoverContainers } from './CONTAINERS_FILENAME-DlP6YM_Q.mjs';
@@ -12,19 +12,21 @@ import discoverHttpRoutes from './discoverHttpRoutes-CfP6cMzt.mjs';
12
12
  import discoverInserts from './discoverInserts-C7zxXkUf.mjs';
13
13
  import discoverMaskProcedures, { discoverMaskMetadata } from './discoverMaskProcedures-Cm81kwrb.mjs';
14
14
  import discoverMigrations from './discoverMigrations-Bi5nJ0mJ.mjs';
15
+ import { MUTATORS_FILENAME, isDefineMutatorCallee, discoverMutators } from './MUTATORS_FILENAME-BhqdPtKp.mjs';
15
16
  import discoverNondeterministicCalls from './discoverNondeterministicCalls-C4M8AXmQ.mjs';
16
17
  import discoverQueries from './discoverQueries-B0wGT-xe.mjs';
17
18
  import { discoverQueues } from './QUEUES_FILENAME-B5_eWCRe.mjs';
18
19
  import discoverR2sqlCalls from './discoverR2sqlCalls-BVNMd428.mjs';
19
20
  import discoverRlsProcedures, { discoverRlsMetadata } from './discoverRlsMetadata-BS9GOGC5.mjs';
20
21
  import discoverSchema from './discoverSchema-BnWHHJ4T.mjs';
22
+ import { discoverShapes } from './SHAPES_FILENAME-ChV7MqgE.mjs';
21
23
  import discoverStorageRulesMetadata from './discoverStorageRulesMetadata-Da8BKXcI.mjs';
22
24
  import { e as enclosingExportName$1 } from './discover-ast-CT6BgBr4.mjs';
23
25
  import { discoverWorkflows } from './WORKFLOWS_FILENAME-D62dcBGg.mjs';
24
- import { buildStorageColumns, emitDataModel, emitApi, emitServer, emitFunctions, emitShard, emitContainers, emitWorkflows, emitQueues, emitCrons, emitVectors, emitDrizzleSchema, emitSeed, emitWranglerCronTriggers } from './GENERATED_HEADER-CkZUgM4_.mjs';
25
- import { emitApp } from './emitApp-DGmlt5fq.mjs';
26
- import { buildOpenApiDocument, emitOpenApiModule } from './buildOpenApiDocument-BSoDzIn8.mjs';
27
- import { buildOpenRpcDocument, emitOpenRpcModule } from './OPENRPC_VERSION-VINwUAxf.mjs';
26
+ import { buildStorageColumns, emitDataModel, emitApi, emitServer, emitFunctions, emitShard, emitCollections, emitContainers, emitWorkflows, emitQueues, emitCrons, emitVectors, emitDrizzleSchema, emitSeed, emitWranglerCronTriggers } from './GENERATED_HEADER-D-AbhmRh.mjs';
27
+ import { emitApp } from './emitApp-CV81L74c.mjs';
28
+ import { buildOpenApiDocument, emitOpenApiModule } from './buildOpenApiDocument-DoK7_x1g.mjs';
29
+ import { buildOpenRpcDocument, emitOpenRpcModule } from './OPENRPC_VERSION-DDT4mIzD.mjs';
28
30
  import { buildSchemaSnapshot, serializeSchemaSnapshot } from './SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs';
29
31
 
30
32
  const HTTP_VERBS = /* @__PURE__ */ new Set(["delete", "get", "head", "options", "patch", "post", "put"]);
@@ -241,6 +243,11 @@ const discoverArgumentValidators = (project, lunoraDirectory) => {
241
243
  };
242
244
 
243
245
  const PROBES = {
246
+ // The middleware (`accessContext()` / `accessRoles()`) imports the `/context`
247
+ // and `/roles` subpaths, NOT the bare `@lunora/cloudflare-access` specifier —
248
+ // so the per-procedure middleware never trips the global `ctx.access` wiring.
249
+ // A handler reading `ctx.access` is the signal that wires it onto every ctx.
250
+ access: { contextProperty: "access", moduleSpecifier: "@lunora/cloudflare-access" },
244
251
  ai: { contextProperty: "ai", moduleSpecifier: "@lunora/ai" },
245
252
  analytics: { contextProperty: "analytics", moduleSpecifier: "@lunora/bindings/analytics" },
246
253
  browser: { contextProperty: "browser", moduleSpecifier: "@lunora/browser" },
@@ -277,6 +284,7 @@ const readsContextProperty = (sourceFile, property) => {
277
284
  };
278
285
  const discoverFeatureUsage = (project, lunoraDirectory) => {
279
286
  const usage = {
287
+ access: false,
280
288
  ai: false,
281
289
  analytics: false,
282
290
  browser: false,
@@ -329,6 +337,61 @@ const buildStudioFeatures = (usage, signals) => {
329
337
  };
330
338
  };
331
339
 
340
+ const isDatabaseReplaceCall = (call) => {
341
+ const callee = call.getExpression();
342
+ if (!Node.isPropertyAccessExpression(callee) || callee.getName() !== "replace") {
343
+ return false;
344
+ }
345
+ const receiver = callee.getExpression();
346
+ if (Node.isPropertyAccessExpression(receiver)) {
347
+ return receiver.getName() === "db";
348
+ }
349
+ return Node.isIdentifier(receiver) && receiver.getText() === "db";
350
+ };
351
+ const serverImplNode = (call) => {
352
+ const argument = call.getArguments()[0];
353
+ if (argument === void 0 || !Node.isObjectLiteralExpression(argument)) {
354
+ return void 0;
355
+ }
356
+ const property = argument.getProperty("server");
357
+ if (property === void 0) {
358
+ return void 0;
359
+ }
360
+ return Node.isPropertyAssignment(property) ? property.getInitializer() : property;
361
+ };
362
+ const exportedDefineMutatorCall = (declaration) => {
363
+ if (!declaration.isExported()) {
364
+ return void 0;
365
+ }
366
+ const initializer = declaration.getInitializer();
367
+ if (initializer?.getKind() !== SyntaxKind.CallExpression) {
368
+ return void 0;
369
+ }
370
+ const call = initializer;
371
+ return isDefineMutatorCallee(call.getExpression()) ? call : void 0;
372
+ };
373
+ const writesFromDeclaration = (declaration) => {
374
+ const call = exportedDefineMutatorCall(declaration);
375
+ const serverImpl = call === void 0 ? void 0 : serverImplNode(call);
376
+ if (serverImpl === void 0) {
377
+ return [];
378
+ }
379
+ const nameNode = declaration.getNameNode();
380
+ const exportName = Node.isIdentifier(nameNode) ? nameNode.getText() : "";
381
+ return serverImpl.getDescendantsOfKind(SyntaxKind.CallExpression).filter((replaceCall) => isDatabaseReplaceCall(replaceCall)).map((replaceCall) => {
382
+ return { exportName, file: "lunora/mutators.ts", line: replaceCall.getStartLineNumber() };
383
+ });
384
+ };
385
+ const mutatorWritesFromSource = (source) => source.getVariableDeclarations().flatMap((declaration) => writesFromDeclaration(declaration));
386
+ const discoverMutatorWrites = (project, lunoraDirectory) => {
387
+ const mutatorsPath = join(lunoraDirectory, MUTATORS_FILENAME);
388
+ if (!existsSync(mutatorsPath)) {
389
+ return [];
390
+ }
391
+ const source = project.getSourceFile(mutatorsPath) ?? project.addSourceFileAtPath(mutatorsPath);
392
+ return mutatorWritesFromSource(source);
393
+ };
394
+
332
395
  const discoverPackageDependencies = (projectRoot) => {
333
396
  const manifestPath = join(projectRoot, "package.json");
334
397
  if (!existsSync(manifestPath)) {
@@ -743,6 +806,8 @@ const runCodegen = (options) => {
743
806
  const functions = discoverFunctions(project, lunoraDirectory);
744
807
  const httpRoutes = discoverHttpRoutes(project, lunoraDirectory);
745
808
  const migrations = discoverMigrations(project, lunoraDirectory);
809
+ const shapes = discoverShapes(project, lunoraDirectory);
810
+ const mutators = discoverMutators(project, lunoraDirectory);
746
811
  const workflows = discoverWorkflows(project, lunoraDirectory);
747
812
  const queues = discoverQueues(project, lunoraDirectory);
748
813
  const crons = discoverCrons(project, lunoraDirectory, workflows);
@@ -763,7 +828,9 @@ const runCodegen = (options) => {
763
828
  discoverSecrets(project, lunoraDirectory),
764
829
  discoverSqlInterpolation(project, lunoraDirectory),
765
830
  discoverAdminRoutes(project, lunoraDirectory),
766
- discoverR2sqlCalls(project, lunoraDirectory)
831
+ discoverR2sqlCalls(project, lunoraDirectory),
832
+ shapes,
833
+ discoverMutatorWrites(project, lunoraDirectory)
767
834
  );
768
835
  const rlsMetadata = discoverRlsMetadata(project, lunoraDirectory);
769
836
  const maskMetadata = discoverMaskMetadata(project, lunoraDirectory);
@@ -772,6 +839,7 @@ const runCodegen = (options) => {
772
839
  const hasAi = featureUsage.ai;
773
840
  const hasPayments = featureUsage.payments;
774
841
  const hasKv = featureUsage.kv;
842
+ const hasAccessFacade = featureUsage.access;
775
843
  const hasFlags = existsSync(join(lunoraDirectory, "flags.ts"));
776
844
  const flagKeys = hasFlags ? discoverFlagKeys(project, lunoraDirectory) : [];
777
845
  const hasHyperdrive = featureUsage.hyperdrive;
@@ -796,6 +864,7 @@ const runCodegen = (options) => {
796
864
  const apiContent = emitApi(functions, workflows, useUmbrella);
797
865
  const serverContent = emitServer({
798
866
  containers,
867
+ hasAccessFacade,
799
868
  hasAi,
800
869
  hasAnalytics,
801
870
  hasBrowser,
@@ -812,11 +881,12 @@ const runCodegen = (options) => {
812
881
  useUmbrella,
813
882
  workflows
814
883
  });
815
- const functionsContent = emitFunctions(functions, migrations, useUmbrella);
884
+ const functionsContent = emitFunctions(functions, migrations, useUmbrella, mutators, shapes);
816
885
  const shardContent = emitShard({
817
886
  advisories,
818
887
  containers,
819
888
  flagKeys,
889
+ hasAccessFacade,
820
890
  hasAi,
821
891
  hasAnalytics,
822
892
  hasBrowser,
@@ -828,14 +898,17 @@ const runCodegen = (options) => {
828
898
  hasPipelines,
829
899
  hasR2sql,
830
900
  maskMetadata,
901
+ mutators,
831
902
  queues,
832
903
  rlsMetadata,
833
904
  schema,
905
+ shapes,
834
906
  storageRules: storageRulesMetadata,
835
907
  studioFeatures,
836
908
  useUmbrella,
837
909
  workflows
838
910
  });
911
+ const collectionsContent = emitCollections(shapes, dependencies.has("@lunora/db"), useUmbrella);
839
912
  const containersContent = emitContainers(containers, schema.jurisdiction);
840
913
  const workflowsContent = emitWorkflows(workflows);
841
914
  const queuesContent = emitQueues(queues);
@@ -847,6 +920,7 @@ const runCodegen = (options) => {
847
920
  const wantsOpenApi = apiSpec === "openapi" || apiSpec === "both";
848
921
  const wantsOpenRpc = apiSpec === "openrpc" || apiSpec === "both";
849
922
  const appContent = emitApp({
923
+ hasAccess: dependencies.has("@lunora/cloudflare-access"),
850
924
  hasAi,
851
925
  hasAnalytics,
852
926
  hasAuth: dependencies.has("@lunora/auth"),
@@ -909,6 +983,7 @@ const runCodegen = (options) => {
909
983
  writeIfPresent(join(outputDirectory, "workflows.ts"), workflowsContent);
910
984
  writeIfPresent(join(outputDirectory, "queues.ts"), queuesContent);
911
985
  writeIfPresent(join(outputDirectory, "seed.ts"), seedContent);
986
+ writeIfPresent(join(outputDirectory, "collections.ts"), collectionsContent);
912
987
  if (wantsOpenApi) {
913
988
  writeIfChanged(join(outputDirectory, "openapi.json"), openApiContent);
914
989
  writeIfChanged(join(outputDirectory, "openapi.ts"), openApiModuleContent);
@@ -935,6 +1010,7 @@ const runCodegen = (options) => {
935
1010
  generated: {
936
1011
  api: apiContent,
937
1012
  app: appContent,
1013
+ collections: collectionsContent,
938
1014
  containers: containersContent,
939
1015
  crons: cronsContent,
940
1016
  dataModel: dataModelContent,
@@ -0,0 +1,94 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { SyntaxKind, Node } from 'ts-morph';
4
+ import { diagnosticAt } from './CodegenDiagnosticError-DeblMkzO.mjs';
5
+
6
+ const SHAPES_FILENAME = "shapes.ts";
7
+ const SHAPE_MODULE_SPECIFIERS = /* @__PURE__ */ new Set(["@lunora/server", "lunorash/server"]);
8
+ const isDefineShape = (identifier) => {
9
+ const symbol = identifier.getSymbol();
10
+ if (!symbol) {
11
+ return identifier.getText() === "defineShape";
12
+ }
13
+ for (const declaration of symbol.getDeclarations()) {
14
+ if (!Node.isImportSpecifier(declaration)) {
15
+ continue;
16
+ }
17
+ if (!SHAPE_MODULE_SPECIFIERS.has(declaration.getImportDeclaration().getModuleSpecifierValue())) {
18
+ return false;
19
+ }
20
+ return declaration.getNameNode().getText() === "defineShape";
21
+ }
22
+ return false;
23
+ };
24
+ const isShapeNamespaceImport = (identifier) => {
25
+ const symbol = identifier.getSymbol();
26
+ if (!symbol) {
27
+ return false;
28
+ }
29
+ for (const declaration of symbol.getDeclarations()) {
30
+ if (!Node.isNamespaceImport(declaration)) {
31
+ continue;
32
+ }
33
+ const importDeclaration = declaration.getFirstAncestorByKind(SyntaxKind.ImportDeclaration);
34
+ return importDeclaration !== void 0 && SHAPE_MODULE_SPECIFIERS.has(importDeclaration.getModuleSpecifierValue());
35
+ }
36
+ return false;
37
+ };
38
+ const isDefineShapeCallee = (callee) => {
39
+ if (Node.isIdentifier(callee)) {
40
+ return isDefineShape(callee);
41
+ }
42
+ if (Node.isPropertyAccessExpression(callee)) {
43
+ const object = callee.getExpression();
44
+ return callee.getName() === "defineShape" && Node.isIdentifier(object) && isShapeNamespaceImport(object);
45
+ }
46
+ return false;
47
+ };
48
+ const tableLiteralFrom = (call) => {
49
+ const [config] = call.getArguments();
50
+ if (!config || !Node.isObjectLiteralExpression(config)) {
51
+ return void 0;
52
+ }
53
+ const tableProperty = config.getProperty("table");
54
+ if (!tableProperty || !Node.isPropertyAssignment(tableProperty)) {
55
+ return void 0;
56
+ }
57
+ const value = tableProperty.getInitializer();
58
+ return value && Node.isStringLiteral(value) ? value.getLiteralValue() : void 0;
59
+ };
60
+ const shapesFromSource = (source) => {
61
+ const shapes = [];
62
+ for (const declaration of source.getVariableDeclarations()) {
63
+ if (!declaration.isExported()) {
64
+ continue;
65
+ }
66
+ const initializer = declaration.getInitializer();
67
+ if (initializer?.getKind() !== SyntaxKind.CallExpression) {
68
+ continue;
69
+ }
70
+ const callExpression = initializer;
71
+ const callee = callExpression.getExpression();
72
+ if (!isDefineShapeCallee(callee)) {
73
+ continue;
74
+ }
75
+ const nameNode = declaration.getNameNode();
76
+ if (!Node.isIdentifier(nameNode)) {
77
+ throw diagnosticAt(nameNode, "defineShape exports must be plain named exports (no destructuring)");
78
+ }
79
+ shapes.push({ exportName: nameNode.getText(), filePath: "shapes", table: tableLiteralFrom(callExpression) });
80
+ }
81
+ return shapes;
82
+ };
83
+ const discoverShapes = (project, lunoraDirectory) => {
84
+ const shapesPath = join(lunoraDirectory, SHAPES_FILENAME);
85
+ if (!existsSync(shapesPath)) {
86
+ return [];
87
+ }
88
+ const source = project.getSourceFile(shapesPath) ?? project.addSourceFileAtPath(shapesPath);
89
+ const shapes = shapesFromSource(source);
90
+ shapes.sort((a, b) => a.exportName.localeCompare(b.exportName));
91
+ return shapes;
92
+ };
93
+
94
+ export { SHAPES_FILENAME, discoverShapes };
@@ -1,4 +1,4 @@
1
- import { GENERATED_HEADER } from './GENERATED_HEADER-CkZUgM4_.mjs';
1
+ import { GENERATED_HEADER } from './GENERATED_HEADER-D-AbhmRh.mjs';
2
2
  import { s as sanitizeNamespace } from './paths-BRd6JHuF.mjs';
3
3
  import { LUNORA_ERROR_CODES, objectSchema, argsObjectSchema, validatorIrToJsonSchema } from './LUNORA_ERROR_CODES-CySpQPD3.mjs';
4
4
 
@@ -1,4 +1,4 @@
1
- import { GENERATED_HEADER } from './GENERATED_HEADER-CkZUgM4_.mjs';
1
+ import { GENERATED_HEADER } from './GENERATED_HEADER-D-AbhmRh.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`)."],
@@ -22,8 +22,25 @@ const LONG_TAIL = [
22
22
  ["hasVectors", "vectors", "vectors", "Wire the Vectorize index map backing `ctx.vectors`."]
23
23
  ];
24
24
  const hasAnyLongTail = (options) => LONG_TAIL.some(([flag]) => options[flag]);
25
+ const buildAccessImports = (hasAccess, hasAuth) => hasAccess ? [
26
+ `import type { CreateAccessResolverOptions } from "@lunora/cloudflare-access";`,
27
+ `import { createAccessResolver${hasAuth ? ", composeResolvers" : ""} } from "@lunora/cloudflare-access";`
28
+ ] : [];
25
29
  const buildImportLines = (options) => {
26
- const { hasAuth, hasFramework, hasGlobal, hasHyperdriveGlobal, hasQueue, hasScheduler, hasStorage, hasWorkflow, useUmbrella, wantsOpenApi, wantsOpenRpc } = options;
30
+ const {
31
+ hasAccess,
32
+ hasAuth,
33
+ hasFramework,
34
+ hasGlobal,
35
+ hasHyperdriveGlobal,
36
+ hasQueue,
37
+ hasScheduler,
38
+ hasStorage,
39
+ hasWorkflow,
40
+ useUmbrella,
41
+ wantsOpenApi,
42
+ wantsOpenRpc
43
+ } = options;
27
44
  const runtimeModule = useUmbrella ? "lunorash/runtime" : "@lunora/runtime";
28
45
  const runtimeTypeImports = ["ExecutionContextLike", "LunoraWorker", "Route", "ScheduledControllerLike", "ShardNamespaceLike", "WorkerOptions"];
29
46
  if (hasGlobal) {
@@ -42,6 +59,7 @@ const buildImportLines = (options) => {
42
59
  `import type { LunoraAuth, LunoraAuthOptions } from "@lunora/auth";`,
43
60
  `import { createAuth, createAuthAdmin, ensureMigrated, handleAuthRequest, lunoraD1Adapter } from "@lunora/auth";`
44
61
  ] : [],
62
+ ...buildAccessImports(hasAccess, hasAuth),
45
63
  ...hasGlobal ? [
46
64
  `import type { D1CtxDbOptions, D1DatabaseLike, D1Exec } from "@lunora/d1";`,
47
65
  `import { createD1CtxDb, facetGlobalColumn, listGlobalTables, readGlobalTablePage } from "@lunora/d1";`
@@ -120,9 +138,10 @@ interface AuthDeclaration<Env> {
120
138
  ] : []
121
139
  ];
122
140
  const buildFieldLines = (options) => [
141
+ ...options.hasAccess ? [` private accessSelector?: Selector<Env, CreateAccessResolverOptions>;`] : [],
123
142
  ` private adminToken?: Selector<Env, string>;`,
124
143
  ...options.hasAuth ? [` private authDeclaration?: AuthDeclaration<Env>;`] : [],
125
- ` private readonly extendFns: ((env: Env) => Partial<WorkerOptions>)[] = [];`,
144
+ ` private readonly extendFns: ((env: Env, derived: Readonly<WorkerOptions>) => Partial<WorkerOptions>)[] = [];`,
126
145
  ...options.hasGlobal ? [` private globalDeclaration?: GlobalDeclaration<Env>;`] : [],
127
146
  ...options.hasHyperdriveGlobal ? [` private hyperdriveGlobalDeclaration?: HyperdriveGlobalDeclaration<Env>;`] : [],
128
147
  ` private readonly routeMap: Record<string, Route> = {};`,
@@ -140,6 +159,14 @@ const buildLongTailMethods = (options) => LONG_TAIL.filter(([flag]) => options[f
140
159
  }`
141
160
  );
142
161
  const buildMethodBlocks = (options) => [
162
+ ...options.hasAccess ? [
163
+ ` /** Wire Cloudflare Access (Zero Trust) — verifies the \`Cf-Access-Jwt-Assertion\` JWT and feeds the identity into \`ctx.auth\` / RLS via \`resolveIdentity\`. When \`.auth(...)\` is also configured, Access is composed ahead of it (Access wins when its JWT is present; everyone else falls through to the app session). */
164
+ public access(selector: Selector<Env, CreateAccessResolverOptions>): this {
165
+ this.accessSelector = selector;
166
+
167
+ return this;
168
+ }`
169
+ ] : [],
143
170
  ` /** Bearer token gating the \`/_lunora/admin/*\` endpoints the studio calls. */
144
171
  public admin(selector: Selector<Env, string>): this {
145
172
  this.adminToken = selector;
@@ -154,8 +181,8 @@ const buildMethodBlocks = (options) => [
154
181
  return this;
155
182
  }`
156
183
  ] : [],
157
- ` /** Escape hatch — merge raw \`WorkerOptions\` (anything not yet sugared) over the derived options at build time. */
158
- public extend(fn: (env: Env) => Partial<WorkerOptions>): this {
184
+ ` /** Escape hatch — merge raw \`WorkerOptions\` (anything not yet sugared) over the derived options at build time. The second \`derived\` argument is a snapshot of the options assembled so far (after \`.auth(...)\` etc.), so you can compose rather than clobber — e.g. wrap \`derived.resolveIdentity\` instead of replacing it. */
185
+ public extend(fn: (env: Env, derived: Readonly<WorkerOptions>) => Partial<WorkerOptions>): this {
159
186
  this.extendFns.push(fn);
160
187
 
161
188
  return this;
@@ -344,6 +371,21 @@ const buildWorkerOptionLines = (options) => [
344
371
 
345
372
  options.authAdmin = authInstance ? createAuthAdmin(authInstance) : undefined;
346
373
  }`
374
+ ] : [],
375
+ // Cloudflare Access — runs AFTER the auth block so it can compose ahead of
376
+ // the better-auth resolver rather than clobber it. With `.auth()` present,
377
+ // a request carrying a verified Access JWT is authenticated by Access and
378
+ // everyone else falls through to the app session; without it, Access is the
379
+ // sole resolver.
380
+ ...options.hasAccess ? [
381
+ options.hasAuth ? ` if (this.accessSelector) {
382
+ const accessResolver = createAccessResolver(this.accessSelector(env));
383
+ const fallback = options.resolveIdentity;
384
+
385
+ options.resolveIdentity = fallback ? composeResolvers(accessResolver, fallback) : accessResolver;
386
+ }` : ` if (this.accessSelector) {
387
+ options.resolveIdentity = createAccessResolver(this.accessSelector(env));
388
+ }`
347
389
  ] : []
348
390
  ];
349
391
  const buildBaseWorkerOptions = (options) => [
@@ -599,7 +641,7 @@ ${buildBaseWorkerOptions(options).join("\n")}
599
641
  }
600
642
 
601
643
  ${workerOptionLines.join("\n\n")}${workerOptionLines.length > 0 ? "\n\n" : ""} for (const fn of this.extendFns) {
602
- Object.assign(options, fn(env));
644
+ Object.assign(options, fn(env, { ...options }));
603
645
  }
604
646
 
605
647
  return options;
@@ -31,12 +31,16 @@ const toAdvisorSchema = (schema) => {
31
31
  references: relation.references,
32
32
  table: relation.table
33
33
  };
34
- })
34
+ }),
35
+ shardKind: typeof table.shardMode === "string" ? table.shardMode : "shardBy"
35
36
  };
36
37
  })
37
38
  };
38
39
  };
39
- const lintSchema = (schema, queries = [], inserts, authApiCalls, rlsProcedures, containers, workflows, workflowCalls, maskProcedures, nondeterministicCalls, procedureProtections, argumentValidators, secretLiterals, sqlInterpolations, adminRoutes, r2sqlCalls) => runAdvisor(
40
+ const toAdvisorShapes = (shapes) => shapes.map((shape) => {
41
+ return { exportName: shape.exportName, file: `lunora/${shape.filePath}.ts`, table: shape.table };
42
+ });
43
+ const lintSchema = (schema, queries = [], inserts, authApiCalls, rlsProcedures, containers, workflows, workflowCalls, maskProcedures, nondeterministicCalls, procedureProtections, argumentValidators, secretLiterals, sqlInterpolations, adminRoutes, r2sqlCalls, shapes, mutatorWrites) => runAdvisor(
40
44
  {
41
45
  adminRoutes,
42
46
  argValidators: argumentValidators,
@@ -44,6 +48,7 @@ const lintSchema = (schema, queries = [], inserts, authApiCalls, rlsProcedures,
44
48
  containers,
45
49
  inserts,
46
50
  maskProcedures,
51
+ mutatorWrites,
47
52
  nondeterministicCalls,
48
53
  procedureProtections,
49
54
  queries,
@@ -51,6 +56,7 @@ const lintSchema = (schema, queries = [], inserts, authApiCalls, rlsProcedures,
51
56
  rlsProcedures,
52
57
  schema: toAdvisorSchema(schema),
53
58
  secretLiterals,
59
+ shapes: shapes === void 0 ? void 0 : toAdvisorShapes(shapes),
54
60
  sqlInterpolations,
55
61
  workflowCalls,
56
62
  workflows
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/codegen",
3
- "version": "1.0.0-alpha.16",
3
+ "version": "1.0.0-alpha.18",
4
4
  "description": "Code generator for Lunora: emits _generated/{api,server,dataModel}.ts from your schema",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -46,7 +46,7 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@lunora/advisor": "1.0.0-alpha.7",
49
+ "@lunora/advisor": "1.0.0-alpha.8",
50
50
  "@lunora/container": "1.0.0-alpha.5",
51
51
  "@lunora/queue": "1.0.0-alpha.1",
52
52
  "@lunora/scheduler": "1.0.0-alpha.3",