@lunora/codegen 1.0.0-alpha.1 → 1.0.0-alpha.11

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 (30) hide show
  1. package/__assets__/package-og.svg +1 -1
  2. package/dist/index.d.mts +171 -14
  3. package/dist/index.d.ts +171 -14
  4. package/dist/index.mjs +24 -22
  5. package/dist/packem_shared/{CONTAINERS_FILENAME-0K-pjNb8.mjs → CONTAINERS_FILENAME-DlP6YM_Q.mjs} +1 -1
  6. package/dist/packem_shared/{CodegenDiagnosticError-54jWDxA9.mjs → CodegenDiagnosticError-DeblMkzO.mjs} +3 -2
  7. package/dist/packem_shared/{emitApi-hRVC-kE7.mjs → GENERATED_HEADER-r1OZrKAx.mjs} +451 -43
  8. package/dist/packem_shared/{buildOpenRpcDocument-BZGY1-jT.mjs → OPENRPC_VERSION-BYRhDy-7.mjs} +1 -1
  9. package/dist/packem_shared/QUEUES_FILENAME-B5_eWCRe.mjs +119 -0
  10. package/dist/packem_shared/{createCodegenProject-DGJm0_Pk.mjs → SCHEMA_SNAPSHOT_FILENAME-CgJUPhI3.mjs} +102 -43
  11. package/dist/packem_shared/{buildSchemaSnapshot-DzLDbWk3.mjs → SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs} +12 -0
  12. package/dist/packem_shared/{discoverWorkflows-DRDQdhfq.mjs → WORKFLOWS_FILENAME-D62dcBGg.mjs} +1 -1
  13. package/dist/packem_shared/{buildOpenApiDocument-yHVN66Xd.mjs → buildOpenApiDocument-C8NKrvpw.mjs} +1 -1
  14. package/dist/packem_shared/{discoverAuthApiCalls-C35R6z0T.mjs → discoverAuthApiCalls-CoirYbg6.mjs} +1 -1
  15. package/dist/packem_shared/{discoverCrons-BL6iGuJ3.mjs → discoverCrons-Cev7RRAf.mjs} +20 -17
  16. package/dist/packem_shared/{discoverFunctions-DEgAcRuD.mjs → discoverFunctions-BWMczzBx.mjs} +7 -2
  17. package/dist/packem_shared/{discoverHttpRoutes-C978pBiG.mjs → discoverHttpRoutes-CfP6cMzt.mjs} +2 -2
  18. package/dist/packem_shared/{discoverInserts-CRQdXvHO.mjs → discoverInserts-C7zxXkUf.mjs} +24 -2
  19. package/dist/packem_shared/{discoverMaskProcedures-B64zA740.mjs → discoverMaskProcedures-Cm81kwrb.mjs} +1 -1
  20. package/dist/packem_shared/{discoverMigrations-Doj_-BAA.mjs → discoverMigrations-Bi5nJ0mJ.mjs} +10 -4
  21. package/dist/packem_shared/{discoverNondeterministicCalls-4KiPQxQU.mjs → discoverNondeterministicCalls-C4M8AXmQ.mjs} +1 -1
  22. package/dist/packem_shared/{discoverQueries-BkIi0dBD.mjs → discoverQueries-B0wGT-xe.mjs} +1 -1
  23. package/dist/packem_shared/discoverR2sqlCalls-BVNMd428.mjs +80 -0
  24. package/dist/packem_shared/{discoverRlsMetadata-DpRB1HMe.mjs → discoverRlsMetadata-BS9GOGC5.mjs} +1 -1
  25. package/dist/packem_shared/{discoverSchema-BBulgGbH.mjs → discoverSchema-BnWHHJ4T.mjs} +296 -16
  26. package/dist/packem_shared/{discoverStorageRulesMetadata-DAqJUxUv.mjs → discoverStorageRulesMetadata-Da8BKXcI.mjs} +1 -1
  27. package/dist/packem_shared/{emitApp-CzZ6GbrD.mjs → emitApp-B1DgLrM8.mjs} +28 -4
  28. package/dist/packem_shared/{lintSchema-DicbOHvH.mjs → formatAdvisories-8NIv1k0I.mjs} +2 -1
  29. package/dist/packem_shared/{parse-validator-tuQtHrsr.mjs → parse-validator-Cabb60UV.mjs} +2 -1
  30. package/package.json +8 -7
package/dist/index.d.ts CHANGED
@@ -25,6 +25,15 @@ interface ValidatorIR {
25
25
  bucket?: string;
26
26
  /** Column modifiers (`.unique()`, `.default()`, `.nullable()`, …) when present. */
27
27
  column?: ColumnMetaIR;
28
+ /**
29
+ * `true` when this validator carries a `.check(...)` refinement. The predicate
30
+ * is a runtime closure the AST→IR step can't represent, so the node keeps its
31
+ * base `kind` but records the refinement's presence here. The AOT args-validator
32
+ * compiler declines any node with this flag (compiling it would silently skip
33
+ * the predicate). `.meta(...)` is pure metadata with no parse effect and does
34
+ * NOT set this.
35
+ */
36
+ hasRefinement?: boolean;
28
37
  /** For `v.optional(inner)` / `v.array(inner)`. */
29
38
  inner?: ValidatorIR;
30
39
  /** For `v.record(key, value)`. */
@@ -126,10 +135,23 @@ interface TableIR {
126
135
  field: string;
127
136
  kind: "shardBy";
128
137
  };
138
+ /** Set when the chain carried `.softDelete()` — the marker column's name (default `deletedAt`). The column is injected into `shape` so `Doc_*` carries it. */
139
+ softDelete?: {
140
+ field: string;
141
+ };
129
142
  /** Vector indexes declared inline via `.vectorize()` (DSL Shape A). */
130
143
  vectorIndexes: ReadonlyArray<VectorIndexIR>;
131
144
  }
145
+ /** The Cloudflare DO data-residency jurisdictions the schema may declare. Canonical literal set for the codegen package. */
146
+ type JurisdictionIR = "eu" | "fedramp" | "us";
132
147
  interface SchemaIR {
148
+ /**
149
+ * Cloudflare data-residency jurisdiction declared via
150
+ * `defineSchema(...).jurisdiction("…")`. Emitted into the generated worker's
151
+ * `createWorker({ jurisdiction })` (and `ctx.scheduler` / `ctx.containers`).
152
+ * Absent ⇒ un-pinned.
153
+ */
154
+ jurisdiction?: JurisdictionIR;
133
155
  tables: ReadonlyArray<TableIR>;
134
156
  /** All vector indexes (inline Shape A hoisted + standalone Shape B), flattened. */
135
157
  vectorIndexes: ReadonlyArray<VectorIndexIR>;
@@ -290,6 +312,37 @@ interface WorkflowIR {
290
312
  name: string;
291
313
  }
292
314
  /**
315
+ * A queue lifted from a `defineQueue()` export in `lunora/queues.ts`. Carries
316
+ * what the emitters and the config layer need to wire the typed `ctx.queues`
317
+ * producer, the generated worker `queue()` dispatch, and the wrangler
318
+ * `queues.producers[]` / `queues.consumers[]` entries. Like workflows, a queue
319
+ * is NOT a Durable Object — wrangler gets only `queues.*` entries. Names are
320
+ * derived via `@lunora/queue`'s shared helpers so codegen and the config layer
321
+ * can never disagree.
322
+ */
323
+ interface QueueIR {
324
+ /** The Cloudflare `Queue` producer binding name, e.g. `QUEUE_EMAIL`. */
325
+ bindingName: string;
326
+ /** The `lunora/queues.ts` export name, e.g. `emailQueue`. */
327
+ exportName: string;
328
+ /** How the queue is consumed: `"push"` (a worker `queue()` handler) or `"pull"` (external HTTP). */
329
+ mode: "pull" | "push";
330
+ /**
331
+ * The stable wrangler queue name (`queues.producers[].queue`). Defaults to
332
+ * the kebab-cased export name (`emailQueue` → `email-queue`); a static
333
+ * `name:` literal in the definition overrides it.
334
+ */
335
+ name: string;
336
+ /** Push-consumer batch/retry tuning, mirrored onto the wrangler `queues.consumers[]` entry. */
337
+ tuning: {
338
+ deadLetterQueue?: string;
339
+ maxBatchSize?: number;
340
+ maxBatchTimeout?: number;
341
+ maxRetries?: number;
342
+ retryDelay?: number;
343
+ };
344
+ }
345
+ /**
293
346
  * A `ctx.workflows.get("name")…` call discovered in a function body — the
294
347
  * use-site analog of {@link WorkflowIR} (which is the declaration side). Feeds
295
348
  * the `workflow_unused` lint (a declared workflow with zero call sites) and the
@@ -384,6 +437,26 @@ interface NondeterministicCallIR {
384
437
  line: number;
385
438
  }
386
439
  /**
440
+ * One `ctx.r2sql` access lexically inside a `query`/`mutation` handler — the
441
+ * `r2sql_outside_action` advisor lint input. Structurally identical to the
442
+ * advisor's `AdvisorR2sqlCall` (same field set) so values pass straight through
443
+ * `lintSchema` without conversion, exactly as `NondeterministicCallIR` does.
444
+ * Only `query`/`mutation` handlers are recorded; `action(...)` is the intended
445
+ * home for `ctx.r2sql` and is skipped.
446
+ */
447
+ interface R2sqlCallIR {
448
+ /** The accessed `ctx.r2sql` surface, e.g. `ctx.r2sql.query` / `ctx.r2sql.from`. */
449
+ callee: string;
450
+ /** Export binding name of the function performing the access. */
451
+ exportName: string;
452
+ /** Source file relative to the lunora dir, without extension (the api namespace). */
453
+ file: string;
454
+ /** Which procedure kind the access lives in — only `query`/`mutation` handlers are recorded. */
455
+ kind: "mutation" | "query";
456
+ /** 1-based line of the access, or `0` when unknown. */
457
+ line: number;
458
+ }
459
+ /**
387
460
  * Per-procedure RLS usage snapshot, produced by `discoverRlsProcedures` for the
388
461
  * `rls_uncovered_table` advisor lint. Structurally identical to
389
462
  * `AdvisorRlsProcedure` (they share the same field set) so values pass straight
@@ -686,7 +759,7 @@ interface ProjectIR {
686
759
  * pass straight through without conversion. Returns the findings; surfacing them
687
760
  * (console, error overlay, studio Advisors table) is the caller's choice.
688
761
  */
689
- declare const lintSchema: (schema: SchemaIR, queries?: ReadonlyArray<QueryReadIR>, inserts?: ReadonlyArray<InsertWriteIR>, authApiCalls?: ReadonlyArray<AuthApiCallIR>, rlsProcedures?: ReadonlyArray<RlsProcedureIR>, containers?: ReadonlyArray<ContainerIR>, workflows?: ReadonlyArray<WorkflowIR>, workflowCalls?: ReadonlyArray<WorkflowCallIR>, maskProcedures?: ReadonlyArray<MaskProcedureIR>, nondeterministicCalls?: ReadonlyArray<NondeterministicCallIR>, procedureProtections?: ReadonlyArray<ProcedureMiddlewareIR>, argumentValidators?: ReadonlyArray<ArgumentValidatorIR>, secretLiterals?: ReadonlyArray<SecretLiteralIR>, sqlInterpolations?: ReadonlyArray<SqlInterpolationIR>, adminRoutes?: ReadonlyArray<AdminRouteIR>) => Finding[];
762
+ declare const lintSchema: (schema: SchemaIR, queries?: ReadonlyArray<QueryReadIR>, inserts?: ReadonlyArray<InsertWriteIR>, authApiCalls?: ReadonlyArray<AuthApiCallIR>, rlsProcedures?: ReadonlyArray<RlsProcedureIR>, containers?: ReadonlyArray<ContainerIR>, workflows?: ReadonlyArray<WorkflowIR>, workflowCalls?: ReadonlyArray<WorkflowCallIR>, maskProcedures?: ReadonlyArray<MaskProcedureIR>, nondeterministicCalls?: ReadonlyArray<NondeterministicCallIR>, procedureProtections?: ReadonlyArray<ProcedureMiddlewareIR>, argumentValidators?: ReadonlyArray<ArgumentValidatorIR>, secretLiterals?: ReadonlyArray<SecretLiteralIR>, sqlInterpolations?: ReadonlyArray<SqlInterpolationIR>, adminRoutes?: ReadonlyArray<AdminRouteIR>, r2sqlCalls?: ReadonlyArray<R2sqlCallIR>) => Finding[];
690
763
  /**
691
764
  * Render advisor findings as a single multi-line string for console surfacing:
692
765
  * a one-line summary header followed by one `[LEVEL] name: detail` line per
@@ -711,8 +784,14 @@ declare class CodegenDiagnosticError extends Error {
711
784
  * ts-morph `Node`'s position in its source file.
712
785
  *
713
786
  * Message format: `@lunora/codegen: &lt;detail> (&lt;file>:&lt;line>:&lt;column>)`
787
+ *
788
+ * `meta` is merged onto the returned error for callers that also carry the
789
+ * project-wide `LunoraError` envelope (`code`/`name`/`status`) — it never
790
+ * touches `file`/`line`/`column`, and the error stays an instance of
791
+ * {@link CodegenDiagnosticError} so the Vite overlay's `instanceof` location
792
+ * lookup is unaffected.
714
793
  */
715
- declare const diagnosticAt: (node: Node, detail: string) => CodegenDiagnosticError;
794
+ declare const diagnosticAt: (node: Node, detail: string, meta?: Record<string, unknown>) => CodegenDiagnosticError;
716
795
  /**
717
796
  * Discover `ctx.authApi.&lt;method>(...)` (and bare `authApi.&lt;method>(...)`) calls
718
797
  * under the lunora source directory and attribute each to the exported function
@@ -803,6 +882,28 @@ declare const discoverNondeterministicCalls: (project: Project, lunoraDirectory:
803
882
  * dropping the rest keeps the lint input small.
804
883
  */
805
884
  declare const discoverQueries: (project: Project, lunoraDirectory: string) => QueryReadIR[];
885
+ /** The only file queues may be declared in — mirrors `lunora/workflows.ts`. */
886
+ declare const QUEUES_FILENAME = "queues.ts";
887
+ /**
888
+ * Discover every queue the project declares: exported `defineQueue()` calls in
889
+ * `lunora/queues.ts`. Returns `[]` when the file doesn't exist. Only the
890
+ * wrangler-relevant literals (`name`/`mode`/batch tuning) are read; the handler
891
+ * body is runtime-only, so codegen never evaluates it.
892
+ */
893
+ declare const discoverQueues: (project: Project, lunoraDirectory: string) => QueueIR[];
894
+ /**
895
+ * Discover `ctx.r2sql` accesses lexically inside the handler body of every
896
+ * exported `query(...)` / `mutation(...)` registration under the lunora source
897
+ * directory — the `r2sql_outside_action` lint input. `action(...)` (and
898
+ * `stream(...)`) registrations are intentionally skipped: R2 SQL is the
899
+ * external, non-reactive surface that belongs in actions.
900
+ *
901
+ * Traversal is scoped to the handler node (not the whole declaration), mirroring
902
+ * `discoverNondeterministicCalls` — so a `ctx.r2sql` touch in a sibling helper
903
+ * outside the handler is not attributed to the query/mutation. One
904
+ * {@link R2sqlCallIR} is produced per access site.
905
+ */
906
+ declare const discoverR2sqlCalls: (project: Project, lunoraDirectory: string) => R2sqlCallIR[];
806
907
  declare const discoverRlsProcedures: (project: Project, lunoraDirectory: string) => RlsProcedureIR[];
807
908
  /**
808
909
  * Aggregate the schema-wide RLS metadata the studio's read-only inspector reads:
@@ -822,7 +923,7 @@ declare const discoverRlsMetadata: (project: Project, lunoraDirectory: string) =
822
923
  * Load `&lt;projectRoot>/lunora/schema.ts`, find `defineSchema({...})`, and
823
924
  * return a structural IR. Throws if the file or call cannot be found.
824
925
  */
825
- declare const discoverSchema: (project: Project, schemaPath: string) => SchemaIR;
926
+ declare const discoverSchema: (project: Project, schemaPath: string, projectRoot?: string) => SchemaIR;
826
927
  /**
827
928
  * Aggregate the schema-wide storage-rule metadata the studio's inspector reads:
828
929
  * every statically-discovered `(bucket, on, prefix, procedure)` entry across all
@@ -864,19 +965,23 @@ declare const emitApi: (functions: ReadonlyArray<FunctionIR>, workflows?: Readon
864
965
  interface EmitServerOptions {
865
966
  containers?: ReadonlyArray<ContainerIR>;
866
967
  hasAi?: boolean;
867
- /** A `lunora/` source uses `@lunora/analytics` / `ctx.analytics` — wires the write helper onto every ctx. */
968
+ /** A `lunora/` source uses `@lunora/bindings/analytics` / `ctx.analytics` — wires the write helper onto every ctx. */
868
969
  hasAnalytics?: boolean;
869
970
  /** A `lunora/` source uses `@lunora/browser` / `ctx.browser` — wires `ctx.browser` onto ActionCtx only. */
870
971
  hasBrowser?: boolean;
871
972
  /** A `lunora/` source uses `@lunora/hyperdrive` / `ctx.sql` — wires `ctx.sql` onto ActionCtx only. */
872
973
  hasHyperdrive?: boolean;
873
- /** A `lunora/` source uses `@lunora/images` / `ctx.images` — wires `ctx.images` onto ActionCtx only. */
974
+ /** A `lunora/` source uses `@lunora/bindings/images` / `ctx.images` — wires `ctx.images` onto ActionCtx only. */
874
975
  hasImages?: boolean;
875
- /** A `lunora/` source uses `@lunora/kv` / `ctx.kv` — wires `ctx.kv` onto every ctx. */
976
+ /** A `lunora/` source uses `@lunora/bindings/kv` / `ctx.kv` — wires `ctx.kv` onto every ctx. */
876
977
  hasKv?: boolean;
877
978
  hasPayments?: boolean;
878
- /** A `lunora/` source uses `@lunora/pipelines` / `ctx.pipelines` — wires `ctx.pipelines` onto ActionCtx only. */
979
+ /** A `lunora/` source uses `@lunora/bindings/pipelines` / `ctx.pipelines` — wires `ctx.pipelines` onto ActionCtx only. */
879
980
  hasPipelines?: boolean;
981
+ /** A `lunora/` source uses `@lunora/bindings/r2sql` / `ctx.r2sql` — wires `ctx.r2sql` onto ActionCtx only. */
982
+ hasR2sql?: boolean;
983
+ /** Queues declared via `defineQueue` exports — wires the typed `ctx.queues` producers onto Mutation/Action contexts. */
984
+ queues?: ReadonlyArray<QueueIR>;
880
985
  schema?: SchemaIR;
881
986
  storageRuleBuckets?: ReadonlyArray<string>;
882
987
  /** The project depends on the `lunora` umbrella — import base packages via its subpaths. */
@@ -893,12 +998,14 @@ declare const emitServer: ({
893
998
  hasKv,
894
999
  hasPayments,
895
1000
  hasPipelines,
1001
+ hasR2sql,
1002
+ queues,
896
1003
  schema,
897
1004
  storageRuleBuckets,
898
1005
  useUmbrella,
899
1006
  workflows
900
1007
  }?: EmitServerOptions) => string;
901
- declare const emitFunctions: (functions: ReadonlyArray<FunctionIR>, migrations?: ReadonlyArray<MigrationIR>) => string;
1008
+ declare const emitFunctions: (functions: ReadonlyArray<FunctionIR>, migrations?: ReadonlyArray<MigrationIR>, useUmbrella?: boolean) => string;
902
1009
  /**
903
1010
  * Storage-column map per table for the file browser: `{ table: [field, …] }` for
904
1011
  * every field declared `v.storage(...)` (unwrapping `v.optional(...)`). The
@@ -916,7 +1023,7 @@ declare const emitFunctions: (functions: ReadonlyArray<FunctionIR>, migrations?:
916
1023
  * `containers[].class_name` to be exported by the deployed worker. Returns ""
917
1024
  * when the project declares no containers (the file is not written then).
918
1025
  */
919
- declare const emitContainers: (containers: ReadonlyArray<ContainerIR>) => string;
1026
+ declare const emitContainers: (containers: ReadonlyArray<ContainerIR>, jurisdiction?: JurisdictionIR) => string;
920
1027
  /**
921
1028
  * Emit `_generated/workflows.ts` — one `WorkflowEntrypoint` class per
922
1029
  * `defineWorkflow` export, each a thin subclass of `LunoraWorkflow`
@@ -926,6 +1033,14 @@ declare const emitContainers: (containers: ReadonlyArray<ContainerIR>) => string
926
1033
  * when the project declares no workflows (the file is not written then).
927
1034
  */
928
1035
  declare const emitWorkflows: (workflows: ReadonlyArray<WorkflowIR>) => string;
1036
+ /**
1037
+ * Emit `_generated/queues.ts` — the push-consumer registry the worker `queue()`
1038
+ * handler dispatches through. Maps each push queue's stable wrangler name (which
1039
+ * `batch.queue` carries) to its `defineQueue` definition + export name. Pull
1040
+ * queues are consumed by an external worker, so they carry no handler and are
1041
+ * omitted here. Returns "" (and the file is not written) when no push queues are
1042
+ * declared — a pull-only or queue-free app keeps a clean `_generated/`.
1043
+ */
929
1044
  interface EmitShardOptions {
930
1045
  advisories?: ReadonlyArray<Finding>;
931
1046
  containers?: ReadonlyArray<ContainerIR>;
@@ -941,7 +1056,13 @@ interface EmitShardOptions {
941
1056
  /** A `lunora/` source reads `ctx.kv` — wires `ctx.kv` onto every ctx. */
942
1057
  hasKv?: boolean;
943
1058
  hasPayments?: boolean;
1059
+ /** A `lunora/` source reads `ctx.pipelines` — wires `ctx.pipelines` onto the ActionCtx only. */
1060
+ hasPipelines?: boolean;
1061
+ /** A `lunora/` source reads `ctx.r2sql` (R2 SQL) — wires `ctx.r2sql` onto the ActionCtx only. */
1062
+ hasR2sql?: boolean;
944
1063
  maskMetadata?: MaskMetadataIR;
1064
+ /** Queues declared via `defineQueue` exports in `lunora/queues.ts` — wires the typed `ctx.queues` producers. */
1065
+ queues?: ReadonlyArray<QueueIR>;
945
1066
  rlsMetadata?: RlsMetadataIR;
946
1067
  schema: SchemaIR;
947
1068
  storageRules?: StorageRulesMetadataIR;
@@ -960,7 +1081,10 @@ declare const emitShard: ({
960
1081
  hasImages,
961
1082
  hasKv,
962
1083
  hasPayments,
1084
+ hasPipelines,
1085
+ hasR2sql,
963
1086
  maskMetadata,
1087
+ queues,
964
1088
  rlsMetadata,
965
1089
  schema,
966
1090
  storageRules,
@@ -1029,7 +1153,7 @@ declare const emitWranglerCronTriggers: (crons: ReadonlyArray<CronJobIR>) => str
1029
1153
  interface EmitAppOptions {
1030
1154
  /** App uses `@lunora/ai` / `ctx.ai` → emit `.ai()` (override the Workers AI binding backing `ctx.ai`). */
1031
1155
  hasAi: boolean;
1032
- /** App uses `@lunora/analytics` / `ctx.analytics` → emit `.analytics()` (override the dataset backing `ctx.analytics`). */
1156
+ /** App uses `@lunora/bindings/analytics` / `ctx.analytics` → emit `.analytics()` (override the dataset backing `ctx.analytics`). */
1033
1157
  hasAnalytics: boolean;
1034
1158
  /** App depends on `@lunora/auth` → emit `.auth()` + the lazy build/migrate dance. */
1035
1159
  hasAuth: boolean;
@@ -1043,12 +1167,16 @@ interface EmitAppOptions {
1043
1167
  hasHyperdrive: boolean;
1044
1168
  /** Schema declares **Hyperdrive-backed** `.global({ backend: "hyperdrive" })` tables → emit `.hyperdriveGlobal()` (reactive Postgres/MySQL ctx-db over Hyperdrive). */
1045
1169
  hasHyperdriveGlobal: boolean;
1046
- /** App uses `@lunora/images` / `ctx.images` → emit `.images()`. */
1170
+ /** App uses `@lunora/bindings/images` / `ctx.images` → emit `.images()`. */
1047
1171
  hasImages: boolean;
1048
- /** App uses `@lunora/kv` / `ctx.kv` → emit `.kv()`. */
1172
+ /** App uses `@lunora/bindings/kv` / `ctx.kv` → emit `.kv()`. */
1049
1173
  hasKv: boolean;
1050
1174
  /** App uses `@lunora/payment` / `ctx.payments` → emit `.payment()`. */
1051
1175
  hasPayments: boolean;
1176
+ /** App declares push queues (`defineQueue`) → wire `LUNORA_QUEUE_REGISTRY` into the worker's `queue()` consumer entry. */
1177
+ hasQueue: boolean;
1178
+ /** App uses `@lunora/bindings/r2sql` / `ctx.r2sql` → emit `.r2sql()`. */
1179
+ hasR2sql: boolean;
1052
1180
  /** App imports `@lunora/scheduler` / declares crons → emit `.scheduler()`. */
1053
1181
  hasScheduler: boolean;
1054
1182
  /** App uses `@lunora/storage` → emit `.storage()` (DO `ctx.storage` + studio file browser). */
@@ -1057,6 +1185,8 @@ interface EmitAppOptions {
1057
1185
  hasVectors: boolean;
1058
1186
  /** App declares Cloudflare Workflows (`defineWorkflow`) → wire `options.workflowsClient` so the studio's workflow-instance proxy can reach the CF REST API. */
1059
1187
  hasWorkflow: boolean;
1188
+ /** Schema declares `.jurisdiction("…")` → pin every DO the worker reaches (shards, fan-out, scheduler, containers) to the Cloudflare data-residency jurisdiction. */
1189
+ jurisdiction?: JurisdictionIR;
1060
1190
  /** Project depends on the unscoped `lunorash` umbrella → import the runtime via `lunorash/runtime` instead of `@lunora/runtime`. */
1061
1191
  useUmbrella: boolean;
1062
1192
  /** An OpenAPI spec is emitted (`openapi.ts`) → wire `openApiSpec` into the worker. */
@@ -1201,6 +1331,19 @@ interface TableSnapshot {
1201
1331
  }
1202
1332
  /** The committed baseline — a deterministic structural view of the whole schema. */
1203
1333
  interface SchemaSnapshot {
1334
+ /**
1335
+ * Cloudflare DO data-residency jurisdiction declared via `.jurisdiction("…")`,
1336
+ * or absent. Tracked because changing it strands all existing Durable Object
1337
+ * data (a DO name maps to a different ID per jurisdiction). Optional, so old
1338
+ * baselines written before this field parse cleanly (absent ⇒ undefined).
1339
+ *
1340
+ * Typed as a plain `string` (not the authoring union) on purpose: this is
1341
+ * STORED data that a newer Lunora may have written with a jurisdiction this
1342
+ * version doesn't yet know. Preserving the raw value keeps the breaking
1343
+ * `changedJurisdiction` diff correct under a downgrade — coercing an unknown
1344
+ * value to `undefined` would fail OPEN and hide the most destructive change.
1345
+ */
1346
+ jurisdiction?: string;
1204
1347
  /** Sorted list of every declared `defineMigration` id at capture time. */
1205
1348
  migrationIds: ReadonlyArray<string>;
1206
1349
  /** Table name → {@link TableSnapshot}, keys sorted for stable serialization. */
@@ -1214,7 +1357,7 @@ interface DriftChange {
1214
1357
  /** Human-readable, actionable description (used in the gate message). */
1215
1358
  summary: string;
1216
1359
  /** A machine-readable change discriminator. */
1217
- type: "addedIndex" | "addedOptionalField" | "addedRelation" | "addedRequiredField" | "addedTable" | "changedFieldKind" | "changedIndex" | "changedShardMode" | "fieldOptionalToRequired" | "fieldRequiredToOptional" | "removedField" | "removedIndex" | "removedRelation" | "removedTable";
1360
+ type: "addedIndex" | "addedOptionalField" | "addedRelation" | "addedRequiredField" | "addedTable" | "changedJurisdiction" | "changedFieldKind" | "changedIndex" | "changedShardMode" | "fieldOptionalToRequired" | "fieldRequiredToOptional" | "removedField" | "removedIndex" | "removedRelation" | "removedTable";
1218
1361
  }
1219
1362
  /** The result of diffing two snapshots: every classified change. */
1220
1363
  interface SchemaDrift {
@@ -1316,6 +1459,11 @@ declare const refreshCodegenProject: (project: Project, lunoraDirectory: string)
1316
1459
  * Top-level codegen entry. Parses `&lt;projectRoot>/lunora/schema.ts` and every
1317
1460
  * function file under `&lt;projectRoot>/lunora/`, then writes
1318
1461
  * `_generated/{api,server,dataModel}.ts` next to them.
1462
+ *
1463
+ * When `LUNORA_CODEGEN_TIMING` is set (truthy), a single diagnostic summary
1464
+ * line is written to stderr with the total wall time and the discovery-vs-emit
1465
+ * split — opt-in instrumentation that is otherwise zero-cost and side-effect-free
1466
+ * on the returned {@link CodegenResult}.
1319
1467
  */
1320
1468
  declare const runCodegen: (options: CodegenOptions) => CodegenResult;
1321
1469
  interface CodegenOptions {
@@ -1416,6 +1564,8 @@ interface CodegenResult {
1416
1564
  * `apiSpec` includes `openrpc`.
1417
1565
  */
1418
1566
  openRpcModule: string;
1567
+ /** Push-consumer queue registry (`_generated/queues.ts`); `""` (and not written) when no push queues are declared. */
1568
+ queues: string;
1419
1569
  /** Project-bound seed client (`_generated/seed.ts`); `""` (and not written) when `@lunora/seed` is not a declared dependency. */
1420
1570
  seed: string;
1421
1571
  server: string;
@@ -1426,6 +1576,13 @@ interface CodegenResult {
1426
1576
  };
1427
1577
  outputDirectory: string;
1428
1578
  /**
1579
+ * Queues discovered from `defineQueue` exports in `lunora/queues.ts` — the
1580
+ * list the config layer reconciles into wrangler's `queues.producers[]` /
1581
+ * `queues.consumers[]`. Queues are NOT Durable Objects, so this adds no
1582
+ * binding or migration. Empty when the project declares no queues.
1583
+ */
1584
+ queues: ReadonlyArray<QueueIR>;
1585
+ /**
1429
1586
  * The CURRENT structural schema snapshot computed this run (tables + field
1430
1587
  * kinds/optionality + indexes/relations/shard mode + declared migration ids).
1431
1588
  * The pre-deploy drift gate diffs this against the committed baseline read
@@ -1470,4 +1627,4 @@ declare const validatorIrToJsonSchema: (validator: ValidatorIR) => JsonSchema;
1470
1627
  */
1471
1628
  declare const LUNORA_ERROR_CODES: ReadonlyArray<string>;
1472
1629
  declare const VERSION = "0.0.0";
1473
- export { type AuthApiCallIR, CONTAINERS_FILENAME, CodegenDiagnosticError, type CodegenOptions, type CodegenResult, type ContainerIR, type CronJobIR, type DriftChange, type EmitAppOptions, type FieldSnapshot, type FunctionIR, GENERATED_HEADER, type HttpRouteIR, type IndexIR, type IndexSnapshot, type InsertWriteIR, LUNORA_ERROR_CODES, type MaskProcedureIR, type MigrationIR, OPENRPC_VERSION, type OpenApiEmitInput, type OpenRpcEmitInput, type ProjectIR, type QueryReadIR, type RelationSnapshot, type RlsMetadataIR, type RlsPolicyIR, type RlsProcedureIR, type RlsRoleIR, SCHEMA_SNAPSHOT_FILENAME, SCHEMA_SNAPSHOT_VERSION, type SchemaDrift, type SchemaDriftDecision, type SchemaIR, type SchemaSnapshot, SchemaSnapshotParseError, type StorageRuleIR, type StorageRulesMetadataIR, type TableIR, type TableSnapshot, VERSION, type ValidatorIR, type VectorIndexIR, WORKFLOWS_FILENAME, type WorkflowIR, buildOpenApiDocument, buildOpenRpcDocument, buildSchemaSnapshot, createCodegenProject, diagnosticAt, diffSchemaSnapshots, discoverAuthApiCalls, discoverContainers, discoverCrons, discoverFunctions, discoverHttpRoutes, discoverInserts, discoverMaskProcedures, discoverMigrations, discoverNondeterministicCalls, discoverQueries, discoverRlsMetadata, discoverRlsProcedures, discoverSchema, discoverStorageRulesMetadata, discoverWorkflows, emitApi, emitApp, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitOpenApi, emitOpenApiModule, emitOpenRpc, emitOpenRpcModule, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers, evaluateSchemaDrift, formatAdvisories, lintSchema, parseSchemaSnapshot, refreshCodegenProject, runCodegen, schemaFromIr, serializeSchemaSnapshot, validatorIrToJsonSchema };
1630
+ export { type AuthApiCallIR, CONTAINERS_FILENAME, CodegenDiagnosticError, type CodegenOptions, type CodegenResult, type ContainerIR, type CronJobIR, type DriftChange, type EmitAppOptions, type FieldSnapshot, type FunctionIR, GENERATED_HEADER, type HttpRouteIR, type IndexIR, type IndexSnapshot, type InsertWriteIR, LUNORA_ERROR_CODES, type MaskProcedureIR, type MigrationIR, OPENRPC_VERSION, type OpenApiEmitInput, type OpenRpcEmitInput, type ProjectIR, QUEUES_FILENAME, type QueryReadIR, type QueueIR, type R2sqlCallIR, type RelationSnapshot, type RlsMetadataIR, type RlsPolicyIR, type RlsProcedureIR, type RlsRoleIR, SCHEMA_SNAPSHOT_FILENAME, SCHEMA_SNAPSHOT_VERSION, type SchemaDrift, type SchemaDriftDecision, type SchemaIR, type SchemaSnapshot, SchemaSnapshotParseError, type StorageRuleIR, type StorageRulesMetadataIR, type TableIR, type TableSnapshot, VERSION, type ValidatorIR, type VectorIndexIR, WORKFLOWS_FILENAME, type WorkflowIR, buildOpenApiDocument, buildOpenRpcDocument, buildSchemaSnapshot, createCodegenProject, diagnosticAt, diffSchemaSnapshots, discoverAuthApiCalls, discoverContainers, discoverCrons, discoverFunctions, discoverHttpRoutes, discoverInserts, discoverMaskProcedures, discoverMigrations, discoverNondeterministicCalls, discoverQueries, discoverQueues, discoverR2sqlCalls, discoverRlsMetadata, discoverRlsProcedures, discoverSchema, discoverStorageRulesMetadata, discoverWorkflows, emitApi, emitApp, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitOpenApi, emitOpenApiModule, emitOpenRpc, emitOpenRpcModule, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers, evaluateSchemaDrift, formatAdvisories, lintSchema, parseSchemaSnapshot, refreshCodegenProject, runCodegen, schemaFromIr, serializeSchemaSnapshot, validatorIrToJsonSchema };
package/dist/index.mjs CHANGED
@@ -1,25 +1,27 @@
1
- export { formatAdvisories, lintSchema } from './packem_shared/lintSchema-DicbOHvH.mjs';
2
- export { CodegenDiagnosticError, diagnosticAt } from './packem_shared/CodegenDiagnosticError-54jWDxA9.mjs';
3
- export { default as discoverAuthApiCalls } from './packem_shared/discoverAuthApiCalls-C35R6z0T.mjs';
4
- export { CONTAINERS_FILENAME, discoverContainers } from './packem_shared/CONTAINERS_FILENAME-0K-pjNb8.mjs';
5
- export { default as discoverCrons } from './packem_shared/discoverCrons-BL6iGuJ3.mjs';
6
- export { discoverFunctions } from './packem_shared/discoverFunctions-DEgAcRuD.mjs';
7
- export { default as discoverHttpRoutes } from './packem_shared/discoverHttpRoutes-C978pBiG.mjs';
8
- export { default as discoverInserts } from './packem_shared/discoverInserts-CRQdXvHO.mjs';
9
- export { default as discoverMaskProcedures } from './packem_shared/discoverMaskProcedures-B64zA740.mjs';
10
- export { default as discoverMigrations } from './packem_shared/discoverMigrations-Doj_-BAA.mjs';
11
- export { default as discoverNondeterministicCalls } from './packem_shared/discoverNondeterministicCalls-4KiPQxQU.mjs';
12
- export { default as discoverQueries } from './packem_shared/discoverQueries-BkIi0dBD.mjs';
13
- export { discoverRlsMetadata, default as discoverRlsProcedures } from './packem_shared/discoverRlsMetadata-DpRB1HMe.mjs';
14
- export { default as discoverSchema } from './packem_shared/discoverSchema-BBulgGbH.mjs';
15
- export { default as discoverStorageRulesMetadata } from './packem_shared/discoverStorageRulesMetadata-DAqJUxUv.mjs';
16
- export { WORKFLOWS_FILENAME, discoverWorkflows } from './packem_shared/discoverWorkflows-DRDQdhfq.mjs';
17
- export { GENERATED_HEADER, emitApi, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers } from './packem_shared/emitApi-hRVC-kE7.mjs';
18
- export { emitApp } from './packem_shared/emitApp-CzZ6GbrD.mjs';
19
- export { buildOpenApiDocument, emitOpenApi, emitOpenApiModule } from './packem_shared/buildOpenApiDocument-yHVN66Xd.mjs';
20
- export { OPENRPC_VERSION, buildOpenRpcDocument, emitOpenRpc, emitOpenRpcModule } from './packem_shared/buildOpenRpcDocument-BZGY1-jT.mjs';
21
- export { SCHEMA_SNAPSHOT_FILENAME, createCodegenProject, refreshCodegenProject, runCodegen } from './packem_shared/createCodegenProject-DGJm0_Pk.mjs';
22
- export { SCHEMA_SNAPSHOT_VERSION, SchemaSnapshotParseError, buildSchemaSnapshot, diffSchemaSnapshots, evaluateSchemaDrift, parseSchemaSnapshot, serializeSchemaSnapshot } from './packem_shared/buildSchemaSnapshot-DzLDbWk3.mjs';
1
+ export { formatAdvisories, lintSchema } from './packem_shared/formatAdvisories-8NIv1k0I.mjs';
2
+ export { CodegenDiagnosticError, diagnosticAt } from './packem_shared/CodegenDiagnosticError-DeblMkzO.mjs';
3
+ export { default as discoverAuthApiCalls } from './packem_shared/discoverAuthApiCalls-CoirYbg6.mjs';
4
+ export { CONTAINERS_FILENAME, discoverContainers } from './packem_shared/CONTAINERS_FILENAME-DlP6YM_Q.mjs';
5
+ export { default as discoverCrons } from './packem_shared/discoverCrons-Cev7RRAf.mjs';
6
+ export { discoverFunctions } from './packem_shared/discoverFunctions-BWMczzBx.mjs';
7
+ export { default as discoverHttpRoutes } from './packem_shared/discoverHttpRoutes-CfP6cMzt.mjs';
8
+ export { default as discoverInserts } from './packem_shared/discoverInserts-C7zxXkUf.mjs';
9
+ export { default as discoverMaskProcedures } from './packem_shared/discoverMaskProcedures-Cm81kwrb.mjs';
10
+ export { default as discoverMigrations } from './packem_shared/discoverMigrations-Bi5nJ0mJ.mjs';
11
+ export { default as discoverNondeterministicCalls } from './packem_shared/discoverNondeterministicCalls-C4M8AXmQ.mjs';
12
+ export { default as discoverQueries } from './packem_shared/discoverQueries-B0wGT-xe.mjs';
13
+ export { QUEUES_FILENAME, discoverQueues } from './packem_shared/QUEUES_FILENAME-B5_eWCRe.mjs';
14
+ export { default as discoverR2sqlCalls } from './packem_shared/discoverR2sqlCalls-BVNMd428.mjs';
15
+ export { discoverRlsMetadata, default as discoverRlsProcedures } from './packem_shared/discoverRlsMetadata-BS9GOGC5.mjs';
16
+ export { default as discoverSchema } from './packem_shared/discoverSchema-BnWHHJ4T.mjs';
17
+ export { default as discoverStorageRulesMetadata } from './packem_shared/discoverStorageRulesMetadata-Da8BKXcI.mjs';
18
+ export { WORKFLOWS_FILENAME, discoverWorkflows } from './packem_shared/WORKFLOWS_FILENAME-D62dcBGg.mjs';
19
+ export { GENERATED_HEADER, emitApi, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers } from './packem_shared/GENERATED_HEADER-r1OZrKAx.mjs';
20
+ export { emitApp } from './packem_shared/emitApp-B1DgLrM8.mjs';
21
+ export { buildOpenApiDocument, emitOpenApi, emitOpenApiModule } from './packem_shared/buildOpenApiDocument-C8NKrvpw.mjs';
22
+ export { OPENRPC_VERSION, buildOpenRpcDocument, emitOpenRpc, emitOpenRpcModule } from './packem_shared/OPENRPC_VERSION-BYRhDy-7.mjs';
23
+ export { SCHEMA_SNAPSHOT_FILENAME, createCodegenProject, refreshCodegenProject, runCodegen } from './packem_shared/SCHEMA_SNAPSHOT_FILENAME-CgJUPhI3.mjs';
24
+ export { SCHEMA_SNAPSHOT_VERSION, SchemaSnapshotParseError, buildSchemaSnapshot, diffSchemaSnapshots, evaluateSchemaDrift, parseSchemaSnapshot, serializeSchemaSnapshot } from './packem_shared/SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs';
23
25
  export { schemaFromIr } from './packem_shared/schemaFromIr-DTYsLBaA.mjs';
24
26
  export { LUNORA_ERROR_CODES, validatorIrToJsonSchema } from './packem_shared/LUNORA_ERROR_CODES-CySpQPD3.mjs';
25
27
 
@@ -2,7 +2,7 @@ import { existsSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { containerClassName, containerBindingName, normalizeContainerImage } from '@lunora/container';
4
4
  import { SyntaxKind, Node } from 'ts-morph';
5
- import { diagnosticAt } from './CodegenDiagnosticError-54jWDxA9.mjs';
5
+ import { diagnosticAt } from './CodegenDiagnosticError-DeblMkzO.mjs';
6
6
 
7
7
  const CONTAINERS_FILENAME = "containers.ts";
8
8
  const isDefineContainer = (identifier) => {
@@ -10,13 +10,14 @@ class CodegenDiagnosticError extends Error {
10
10
  this.column = column;
11
11
  }
12
12
  }
13
- const diagnosticAt = (node, detail) => {
13
+ const diagnosticAt = (node, detail, meta) => {
14
14
  const sourceFile = node.getSourceFile();
15
15
  const file = sourceFile.getFilePath();
16
16
  const line = node.getStartLineNumber();
17
17
  const { column } = sourceFile.getLineAndColumnAtPos(node.getStart());
18
18
  const message = `@lunora/codegen: ${detail} (${file}:${line.toString()}:${column.toString()})`;
19
- return new CodegenDiagnosticError(message, file, line, column);
19
+ const error = new CodegenDiagnosticError(message, file, line, column);
20
+ return meta ? Object.assign(error, meta) : error;
20
21
  };
21
22
 
22
23
  export { CodegenDiagnosticError, diagnosticAt };