@lunora/codegen 1.0.0-alpha.2 → 1.0.0-alpha.20
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 +444 -16
- package/dist/index.d.ts +444 -16
- package/dist/index.mjs +28 -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/FLAGS_FILENAME-B1vE0LIo.mjs +139 -0
- package/dist/packem_shared/{emitApi-hRVC-kE7.mjs → GENERATED_HEADER-CI272wRm.mjs} +873 -54
- package/dist/packem_shared/LUNORA_SOLUTION_RULES-BTejmZp-.mjs +131 -0
- package/dist/packem_shared/MUTATORS_FILENAME-BhqdPtKp.mjs +81 -0
- package/dist/packem_shared/{buildOpenRpcDocument-BZGY1-jT.mjs → OPENRPC_VERSION-t5pV2NIN.mjs} +1 -1
- package/dist/packem_shared/QUEUES_FILENAME-B5_eWCRe.mjs +119 -0
- package/dist/packem_shared/{createCodegenProject-DGJm0_Pk.mjs → SCHEMA_SNAPSHOT_FILENAME-BMez-jgr.mjs} +187 -43
- package/dist/packem_shared/{buildSchemaSnapshot-DzLDbWk3.mjs → SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs} +12 -0
- package/dist/packem_shared/SHAPES_FILENAME-ChV7MqgE.mjs +94 -0
- package/dist/packem_shared/{discoverWorkflows-DRDQdhfq.mjs → WORKFLOWS_FILENAME-CCisG0Vy.mjs} +42 -2
- package/dist/packem_shared/{buildOpenApiDocument-yHVN66Xd.mjs → buildOpenApiDocument-Dx5QftUn.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-KYq55qu3.mjs} +338 -16
- package/dist/packem_shared/{discoverStorageRulesMetadata-DAqJUxUv.mjs → discoverStorageRulesMetadata-Da8BKXcI.mjs} +1 -1
- package/dist/packem_shared/{emitApp-CzZ6GbrD.mjs → emitApp-cOSypPuO.mjs} +74 -8
- package/dist/packem_shared/{lintSchema-DicbOHvH.mjs → formatAdvisories-DdjK7sgh.mjs} +15 -2
- package/dist/packem_shared/{parse-validator-tuQtHrsr.mjs → parse-validator-Cabb60UV.mjs} +2 -1
- package/package.json +8 -7
package/dist/index.d.mts
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)`. */
|
|
@@ -100,6 +109,36 @@ interface RelationIR {
|
|
|
100
109
|
/** Target table name. */
|
|
101
110
|
table: string;
|
|
102
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Statically-discovered `.source(...)` config (plan 077). Only the bits the
|
|
114
|
+
* advisor lints + DO wiring need are captured; `map`/`tenantBy` are functions and
|
|
115
|
+
* cannot be serialized, so their presence is recorded as `hasTenantBy` rather than
|
|
116
|
+
* the function itself.
|
|
117
|
+
*/
|
|
118
|
+
interface ExternalSourceIR {
|
|
119
|
+
/** The wrangler Hyperdrive binding name. */
|
|
120
|
+
binding: string;
|
|
121
|
+
/** Whether a `columns` projection allow-list was given. */
|
|
122
|
+
columns?: ReadonlyArray<string>;
|
|
123
|
+
/** `true` when a `reconcileEveryMs` was given (the incremental-mode delete-visibility companion). */
|
|
124
|
+
hasReconcile?: boolean;
|
|
125
|
+
/** `true` when a `tenantBy` mapper was given — the tenant-isolation boundary the `external_source_unscoped` lint checks. */
|
|
126
|
+
hasTenantBy: boolean;
|
|
127
|
+
/** The `idColumn` literal, when given (defaults to `"id"` at runtime). */
|
|
128
|
+
idColumn?: string;
|
|
129
|
+
/** Delete-detection mode literal, when given (`"full-pull"` | `"incremental"`). */
|
|
130
|
+
mode?: string;
|
|
131
|
+
/** The membership query literal, when statically knowable. */
|
|
132
|
+
query?: string;
|
|
133
|
+
/**
|
|
134
|
+
* `true` when `.source(...)` was present but its argument was **not** a static
|
|
135
|
+
* object literal (e.g. `.source(buildConfig())`), so none of the fields above
|
|
136
|
+
* could be read. The source still exists — this flag lets `hasSourcedTables`
|
|
137
|
+
* (codegen) and the `external_source_*` lints treat it as a source that can't be
|
|
138
|
+
* verified, instead of mistaking it for no `.source()` at all.
|
|
139
|
+
*/
|
|
140
|
+
unanalyzable?: boolean;
|
|
141
|
+
}
|
|
103
142
|
interface TableIR {
|
|
104
143
|
/**
|
|
105
144
|
* `true` when the table chain carried `.externallyManaged()` — its rows are
|
|
@@ -109,6 +148,13 @@ interface TableIR {
|
|
|
109
148
|
*/
|
|
110
149
|
externallyManaged?: boolean;
|
|
111
150
|
/**
|
|
151
|
+
* Set when the chain carried `.source(...)` — the table is materialized from an
|
|
152
|
+
* external Hyperdrive-backed database by a system poll loop (plan 077). Carries
|
|
153
|
+
* the statically-knowable bits the advisor lints read; the functions (`map`,
|
|
154
|
+
* `tenantBy`) are not serialized, only their presence (`hasTenantBy`).
|
|
155
|
+
*/
|
|
156
|
+
externalSource?: ExternalSourceIR;
|
|
157
|
+
/**
|
|
112
158
|
* Storage backend for a `.global()` table: `"d1"` (default) or
|
|
113
159
|
* `"hyperdrive"` (a Postgres/MySQL database via Cloudflare Hyperdrive). Only
|
|
114
160
|
* meaningful when `shardMode === "global"`; absent for sharded/root tables.
|
|
@@ -126,10 +172,23 @@ interface TableIR {
|
|
|
126
172
|
field: string;
|
|
127
173
|
kind: "shardBy";
|
|
128
174
|
};
|
|
175
|
+
/** Set when the chain carried `.softDelete()` — the marker column's name (default `deletedAt`). The column is injected into `shape` so `Doc_*` carries it. */
|
|
176
|
+
softDelete?: {
|
|
177
|
+
field: string;
|
|
178
|
+
};
|
|
129
179
|
/** Vector indexes declared inline via `.vectorize()` (DSL Shape A). */
|
|
130
180
|
vectorIndexes: ReadonlyArray<VectorIndexIR>;
|
|
131
181
|
}
|
|
182
|
+
/** The Cloudflare DO data-residency jurisdictions the schema may declare. Canonical literal set for the codegen package. */
|
|
183
|
+
type JurisdictionIR = "eu" | "fedramp" | "us";
|
|
132
184
|
interface SchemaIR {
|
|
185
|
+
/**
|
|
186
|
+
* Cloudflare data-residency jurisdiction declared via
|
|
187
|
+
* `defineSchema(...).jurisdiction("…")`. Emitted into the generated worker's
|
|
188
|
+
* `createWorker({ jurisdiction })` (and `ctx.scheduler` / `ctx.containers`).
|
|
189
|
+
* Absent ⇒ un-pinned.
|
|
190
|
+
*/
|
|
191
|
+
jurisdiction?: JurisdictionIR;
|
|
133
192
|
tables: ReadonlyArray<TableIR>;
|
|
134
193
|
/** All vector indexes (inline Shape A hoisted + standalone Shape B), flattened. */
|
|
135
194
|
vectorIndexes: ReadonlyArray<VectorIndexIR>;
|
|
@@ -179,6 +238,59 @@ interface MigrationIR {
|
|
|
179
238
|
table: string;
|
|
180
239
|
}
|
|
181
240
|
/**
|
|
241
|
+
* A `defineShape({...})` declaration discovered in `lunora/shapes.ts`
|
|
242
|
+
* (local-first sync engine, Phase 7). The emitted `LUNORA_SHAPES` registry keys
|
|
243
|
+
* on {@link ShapeIR.exportName}; the generated DO's `resolveShape` override
|
|
244
|
+
* dispatches a `shape_subscribe` to the matching registered shape. Discovery is
|
|
245
|
+
* marker-driven (the `__lunoraShape` brand) — no field metadata is lifted here
|
|
246
|
+
* because the runtime object (`columns`/`compileWhere`) carries the authority.
|
|
247
|
+
*/
|
|
248
|
+
interface ShapeIR {
|
|
249
|
+
/** Export binding name — the shape's registry key and import member. */
|
|
250
|
+
exportName: string;
|
|
251
|
+
/** Path relative to `<projectRoot>/lunora/` without extension — always `"shapes"`. */
|
|
252
|
+
filePath: string;
|
|
253
|
+
/**
|
|
254
|
+
* The `table` string literal from the `defineShape({ table })` call, lifted
|
|
255
|
+
* only for static advisor lints (the runtime object stays authoritative).
|
|
256
|
+
* `undefined` when `table` is not a plain string literal — lints skip those.
|
|
257
|
+
*/
|
|
258
|
+
table?: string;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* A `defineMutator({...})` declaration discovered in `lunora/mutators.ts`
|
|
262
|
+
* (local-first sync engine, Phase 7). The emitted registry registers the
|
|
263
|
+
* authoritative `server` impl into the DO's `LUNORA_FUNCTIONS` table (so
|
|
264
|
+
* `handleRpc` transaction-wraps it) and records its path in
|
|
265
|
+
* `LUNORA_MUTATOR_PATHS` so the DO's `isCustomMutator` override routes the
|
|
266
|
+
* client-watermark push protocol. The client `client` impl is split into the
|
|
267
|
+
* browser bundle separately — only the path crosses to the server side.
|
|
268
|
+
*/
|
|
269
|
+
interface MutatorIR {
|
|
270
|
+
/** Export binding name — the mutator's registry key and import member. */
|
|
271
|
+
exportName: string;
|
|
272
|
+
/** Path relative to `<projectRoot>/lunora/` without extension — always `"mutators"`. */
|
|
273
|
+
filePath: string;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* A whole-row `ctx.db.replace(id, document)` write discovered inside a custom
|
|
277
|
+
* mutator's inline `server` impl (`lunora/mutators.ts`) — the input the
|
|
278
|
+
* `mutator_full_row_replace` advisor lint consumes. A `replace` overwrites the
|
|
279
|
+
* entire row, so a concurrent edit to a different column on a synced table is
|
|
280
|
+
* clobbered; `ctx.db.patch(id, { field })` merges at the column level instead.
|
|
281
|
+
* Structurally identical to `AdvisorMutatorWrite` so it passes straight through
|
|
282
|
+
* to the advisor without conversion, exactly as `InsertWriteIR` does for
|
|
283
|
+
* `AdvisorInsertWrite`.
|
|
284
|
+
*/
|
|
285
|
+
interface MutatorWriteIR {
|
|
286
|
+
/** The mutator export whose `server` impl performs the replace, e.g. `renameChannel`. */
|
|
287
|
+
exportName: string;
|
|
288
|
+
/** Openable source path the replace appears in — always `lunora/mutators.ts`. */
|
|
289
|
+
file: string;
|
|
290
|
+
/** 1-based line of the `replace(...)` call. */
|
|
291
|
+
line: number;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
182
294
|
* A single cron job lifted from a `cronJobs()` builder in `lunora/crons.ts`.
|
|
183
295
|
* Mirrors `@lunora/scheduler`'s `CronJob`: {@link CronJobIR.cron} is the compiled
|
|
184
296
|
* standard cron expression, {@link CronJobIR.functionPath} is the target
|
|
@@ -288,6 +400,79 @@ interface WorkflowIR {
|
|
|
288
400
|
* definition overrides it.
|
|
289
401
|
*/
|
|
290
402
|
name: string;
|
|
403
|
+
/**
|
|
404
|
+
* Durable step labels lifted from the handler body — the first string-literal
|
|
405
|
+
* argument of every `ctx.step.do` / `.sleep` / `.sleepUntil` / `.waitForEvent`
|
|
406
|
+
* call. Feeds the duplicate-step-name lint, which flags a name used twice
|
|
407
|
+
* (Cloudflare memoizes by name, so the second call silently returns the
|
|
408
|
+
* first's cached result). Calls with a non-literal name are omitted (not
|
|
409
|
+
* statically comparable).
|
|
410
|
+
*/
|
|
411
|
+
steps: ReadonlyArray<WorkflowStepIR>;
|
|
412
|
+
}
|
|
413
|
+
/** One durable step call lifted from a workflow handler body (the use side of {@link WorkflowIR.steps}). */
|
|
414
|
+
interface WorkflowStepIR {
|
|
415
|
+
/** 1-based line of the durable step call. */
|
|
416
|
+
line: number;
|
|
417
|
+
/** The native step method invoked: `do` / `sleep` / `sleepUntil` / `waitForEvent`. */
|
|
418
|
+
method: string;
|
|
419
|
+
/** The step's static label (the first string-literal argument). */
|
|
420
|
+
name: string;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* A queue lifted from a `defineQueue()` export in `lunora/queues.ts`. Carries
|
|
424
|
+
* what the emitters and the config layer need to wire the typed `ctx.queues`
|
|
425
|
+
* producer, the generated worker `queue()` dispatch, and the wrangler
|
|
426
|
+
* `queues.producers[]` / `queues.consumers[]` entries. Like workflows, a queue
|
|
427
|
+
* is NOT a Durable Object — wrangler gets only `queues.*` entries. Names are
|
|
428
|
+
* derived via `@lunora/queue`'s shared helpers so codegen and the config layer
|
|
429
|
+
* can never disagree.
|
|
430
|
+
*/
|
|
431
|
+
interface QueueIR {
|
|
432
|
+
/** The Cloudflare `Queue` producer binding name, e.g. `QUEUE_EMAIL`. */
|
|
433
|
+
bindingName: string;
|
|
434
|
+
/** The `lunora/queues.ts` export name, e.g. `emailQueue`. */
|
|
435
|
+
exportName: string;
|
|
436
|
+
/** How the queue is consumed: `"push"` (a worker `queue()` handler) or `"pull"` (external HTTP). */
|
|
437
|
+
mode: "pull" | "push";
|
|
438
|
+
/**
|
|
439
|
+
* The stable wrangler queue name (`queues.producers[].queue`). Defaults to
|
|
440
|
+
* the kebab-cased export name (`emailQueue` → `email-queue`); a static
|
|
441
|
+
* `name:` literal in the definition overrides it.
|
|
442
|
+
*/
|
|
443
|
+
name: string;
|
|
444
|
+
/** Push-consumer batch/retry tuning, mirrored onto the wrangler `queues.consumers[]` entry. */
|
|
445
|
+
tuning: {
|
|
446
|
+
deadLetterQueue?: string;
|
|
447
|
+
maxBatchSize?: number;
|
|
448
|
+
maxBatchTimeout?: number;
|
|
449
|
+
maxRetries?: number;
|
|
450
|
+
retryDelay?: number;
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* The feature-flag provider declared by the default export of `lunora/flags.ts`
|
|
455
|
+
* (`defineFlags({ provider, … })`). Discovery is **metadata-only** — codegen
|
|
456
|
+
* imports the real module at runtime for the provider value; this IR exists so
|
|
457
|
+
* the config layer can reconcile/validate the wrangler `flagship` binding when
|
|
458
|
+
* the app uses Flagship in binding mode. A `custom` provider (any other
|
|
459
|
+
* OpenFeature factory) carries no binding to reconcile.
|
|
460
|
+
*/
|
|
461
|
+
interface FlagsIR {
|
|
462
|
+
/**
|
|
463
|
+
* The wrangler `flagship[].binding` name — set **only** for a flagship
|
|
464
|
+
* `provider` in binding mode (`flagshipProvider({ binding: "FLAGS" })`). The
|
|
465
|
+
* config layer hints/validates a matching `flagship` binding from this.
|
|
466
|
+
*/
|
|
467
|
+
bindingName?: string;
|
|
468
|
+
/**
|
|
469
|
+
* Flagship operating mode — `"binding"` (wrangler binding, needs a
|
|
470
|
+
* `flagship` entry) or `"http"` (no binding); `undefined` for a `custom`
|
|
471
|
+
* provider or when the mode can't be read statically.
|
|
472
|
+
*/
|
|
473
|
+
mode?: "binding" | "http";
|
|
474
|
+
/** `"flagship"` when the provider is `flagshipProvider(...)`, else `"custom"` (any other OpenFeature provider factory). */
|
|
475
|
+
provider: "custom" | "flagship";
|
|
291
476
|
}
|
|
292
477
|
/**
|
|
293
478
|
* A `ctx.workflows.get("name")…` call discovered in a function body — the
|
|
@@ -384,6 +569,26 @@ interface NondeterministicCallIR {
|
|
|
384
569
|
line: number;
|
|
385
570
|
}
|
|
386
571
|
/**
|
|
572
|
+
* One `ctx.r2sql` access lexically inside a `query`/`mutation` handler — the
|
|
573
|
+
* `r2sql_outside_action` advisor lint input. Structurally identical to the
|
|
574
|
+
* advisor's `AdvisorR2sqlCall` (same field set) so values pass straight through
|
|
575
|
+
* `lintSchema` without conversion, exactly as `NondeterministicCallIR` does.
|
|
576
|
+
* Only `query`/`mutation` handlers are recorded; `action(...)` is the intended
|
|
577
|
+
* home for `ctx.r2sql` and is skipped.
|
|
578
|
+
*/
|
|
579
|
+
interface R2sqlCallIR {
|
|
580
|
+
/** The accessed `ctx.r2sql` surface, e.g. `ctx.r2sql.query` / `ctx.r2sql.from`. */
|
|
581
|
+
callee: string;
|
|
582
|
+
/** Export binding name of the function performing the access. */
|
|
583
|
+
exportName: string;
|
|
584
|
+
/** Source file relative to the lunora dir, without extension (the api namespace). */
|
|
585
|
+
file: string;
|
|
586
|
+
/** Which procedure kind the access lives in — only `query`/`mutation` handlers are recorded. */
|
|
587
|
+
kind: "mutation" | "query";
|
|
588
|
+
/** 1-based line of the access, or `0` when unknown. */
|
|
589
|
+
line: number;
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
387
592
|
* Per-procedure RLS usage snapshot, produced by `discoverRlsProcedures` for the
|
|
388
593
|
* `rls_uncovered_table` advisor lint. Structurally identical to
|
|
389
594
|
* `AdvisorRlsProcedure` (they share the same field set) so values pass straight
|
|
@@ -678,15 +883,16 @@ interface ProjectIR {
|
|
|
678
883
|
* feed `table_without_insert`, authApi calls feed `auth_api_call_without_headers`,
|
|
679
884
|
* rls procedure snapshots feed `rls_uncovered_table`, and mask procedure
|
|
680
885
|
* snapshots feed `mask_uncovered_pii_column`; declared containers
|
|
681
|
-
* feed the `container_*` lints; declared workflows
|
|
682
|
-
* sites feed the `workflow_unused` /
|
|
886
|
+
* feed the `container_*` lints; declared workflows (with their durable step labels)
|
|
887
|
+
* + `ctx.workflows.get(...)` call sites feed the `workflow_unused` /
|
|
888
|
+
* `workflow_unknown_target` / duplicate-step-name lints; non-deterministic
|
|
683
889
|
* calls inside query/mutation handlers feed the `nondeterministic_query_mutation` lint
|
|
684
890
|
* (all default empty for callers that don't analyze functions/containers/workflows).
|
|
685
891
|
* The IR types are structurally identical to the advisor's evidence types so they
|
|
686
892
|
* pass straight through without conversion. Returns the findings; surfacing them
|
|
687
893
|
* (console, error overlay, studio Advisors table) is the caller's choice.
|
|
688
894
|
*/
|
|
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[];
|
|
895
|
+
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>, shapes?: ReadonlyArray<ShapeIR>, mutatorWrites?: ReadonlyArray<MutatorWriteIR>) => Finding[];
|
|
690
896
|
/**
|
|
691
897
|
* Render advisor findings as a single multi-line string for console surfacing:
|
|
692
898
|
* a one-line summary header followed by one `[LEVEL] name: detail` line per
|
|
@@ -711,8 +917,14 @@ declare class CodegenDiagnosticError extends Error {
|
|
|
711
917
|
* ts-morph `Node`'s position in its source file.
|
|
712
918
|
*
|
|
713
919
|
* Message format: `@lunora/codegen: <detail> (<file>:<line>:<column>)`
|
|
920
|
+
*
|
|
921
|
+
* `meta` is merged onto the returned error for callers that also carry the
|
|
922
|
+
* project-wide `LunoraError` envelope (`code`/`name`/`status`) — it never
|
|
923
|
+
* touches `file`/`line`/`column`, and the error stays an instance of
|
|
924
|
+
* {@link CodegenDiagnosticError} so the Vite overlay's `instanceof` location
|
|
925
|
+
* lookup is unaffected.
|
|
714
926
|
*/
|
|
715
|
-
declare const diagnosticAt: (node: Node, detail: string) => CodegenDiagnosticError;
|
|
927
|
+
declare const diagnosticAt: (node: Node, detail: string, meta?: Record<string, unknown>) => CodegenDiagnosticError;
|
|
716
928
|
/**
|
|
717
929
|
* Discover `ctx.authApi.<method>(...)` (and bare `authApi.<method>(...)`) calls
|
|
718
930
|
* under the lunora source directory and attribute each to the exported function
|
|
@@ -738,6 +950,21 @@ declare const discoverContainers: (project: Project, lunoraDirectory: string) =>
|
|
|
738
950
|
* workflow start. Names must be unique across the project.
|
|
739
951
|
*/
|
|
740
952
|
declare const discoverCrons: (project: Project, lunoraDirectory: string, workflows?: ReadonlyArray<WorkflowIR>) => CronJobIR[];
|
|
953
|
+
/** The only file a feature-flag provider may be declared in — mirrors `lunora/queues.ts`. */
|
|
954
|
+
declare const FLAGS_FILENAME = "flags.ts";
|
|
955
|
+
/** One statically-discovered flag read: the key plus the value type its `ctx.flags.<type>` call implies. */
|
|
956
|
+
|
|
957
|
+
/**
|
|
958
|
+
* Discover the feature-flag provider a project declares in `lunora/flags.ts`.
|
|
959
|
+
* Returns `undefined` when the file doesn't exist (the app has no flags). The
|
|
960
|
+
* read is metadata-only and lenient: codegen wires `ctx.flags` purely from the
|
|
961
|
+
* file's *existence* (`run-codegen.ts`) and imports the real module for the
|
|
962
|
+
* provider value — this IR exists solely so the config layer can reconcile the
|
|
963
|
+
* wrangler `flagship` binding for the Flagship binding-mode provider. Anything
|
|
964
|
+
* it can't read statically degrades to a `custom` provider (no binding), never
|
|
965
|
+
* a thrown error.
|
|
966
|
+
*/
|
|
967
|
+
declare const discoverFlags: (project: Project, lunoraDirectory: string) => FlagsIR | undefined;
|
|
741
968
|
/**
|
|
742
969
|
* Scan all .ts files under `lunoraDir` (skipping `_generated/` and `schema.ts`)
|
|
743
970
|
* for top-level `export const x = query/mutation/action({...})` registrations.
|
|
@@ -780,6 +1007,23 @@ declare const discoverMaskProcedures: (project: Project, lunoraDirectory: string
|
|
|
780
1007
|
* key); `table` is best-effort and left `""` when not a literal.
|
|
781
1008
|
*/
|
|
782
1009
|
declare const discoverMigrations: (project: Project, lunoraDirectory: string) => MigrationIR[];
|
|
1010
|
+
/** The only file custom mutators may be declared in — mirrors `lunora/queues.ts`. */
|
|
1011
|
+
declare const MUTATORS_FILENAME = "mutators.ts";
|
|
1012
|
+
/**
|
|
1013
|
+
* Decide whether a call's callee is `defineMutator` — either the bare imported
|
|
1014
|
+
* identifier (`defineMutator(...)`) or a namespace member access
|
|
1015
|
+
* (`server.defineMutator(...)`). Both are valid ES module syntax, so discovery
|
|
1016
|
+
* must see mutators declared either way.
|
|
1017
|
+
*/
|
|
1018
|
+
|
|
1019
|
+
/**
|
|
1020
|
+
* Discover every custom mutator the project declares: exported
|
|
1021
|
+
* `defineMutator()` calls in `lunora/mutators.ts`. Returns `[]` when the file
|
|
1022
|
+
* doesn't exist. Only the export binding is lifted — the runtime object carries
|
|
1023
|
+
* the authoritative `server` impl + `handler`, so codegen never evaluates the
|
|
1024
|
+
* body. The client `client` impl is split into the browser bundle separately.
|
|
1025
|
+
*/
|
|
1026
|
+
declare const discoverMutators: (project: Project, lunoraDirectory: string) => MutatorIR[];
|
|
783
1027
|
/**
|
|
784
1028
|
* Discover non-deterministic API calls (`Date.now`, `new Date()`, `Date()`,
|
|
785
1029
|
* `Math.random`, `crypto.randomUUID`, `crypto.getRandomValues` — including
|
|
@@ -803,6 +1047,28 @@ declare const discoverNondeterministicCalls: (project: Project, lunoraDirectory:
|
|
|
803
1047
|
* dropping the rest keeps the lint input small.
|
|
804
1048
|
*/
|
|
805
1049
|
declare const discoverQueries: (project: Project, lunoraDirectory: string) => QueryReadIR[];
|
|
1050
|
+
/** The only file queues may be declared in — mirrors `lunora/workflows.ts`. */
|
|
1051
|
+
declare const QUEUES_FILENAME = "queues.ts";
|
|
1052
|
+
/**
|
|
1053
|
+
* Discover every queue the project declares: exported `defineQueue()` calls in
|
|
1054
|
+
* `lunora/queues.ts`. Returns `[]` when the file doesn't exist. Only the
|
|
1055
|
+
* wrangler-relevant literals (`name`/`mode`/batch tuning) are read; the handler
|
|
1056
|
+
* body is runtime-only, so codegen never evaluates it.
|
|
1057
|
+
*/
|
|
1058
|
+
declare const discoverQueues: (project: Project, lunoraDirectory: string) => QueueIR[];
|
|
1059
|
+
/**
|
|
1060
|
+
* Discover `ctx.r2sql` accesses lexically inside the handler body of every
|
|
1061
|
+
* exported `query(...)` / `mutation(...)` registration under the lunora source
|
|
1062
|
+
* directory — the `r2sql_outside_action` lint input. `action(...)` (and
|
|
1063
|
+
* `stream(...)`) registrations are intentionally skipped: R2 SQL is the
|
|
1064
|
+
* external, non-reactive surface that belongs in actions.
|
|
1065
|
+
*
|
|
1066
|
+
* Traversal is scoped to the handler node (not the whole declaration), mirroring
|
|
1067
|
+
* `discoverNondeterministicCalls` — so a `ctx.r2sql` touch in a sibling helper
|
|
1068
|
+
* outside the handler is not attributed to the query/mutation. One
|
|
1069
|
+
* {@link R2sqlCallIR} is produced per access site.
|
|
1070
|
+
*/
|
|
1071
|
+
declare const discoverR2sqlCalls: (project: Project, lunoraDirectory: string) => R2sqlCallIR[];
|
|
806
1072
|
declare const discoverRlsProcedures: (project: Project, lunoraDirectory: string) => RlsProcedureIR[];
|
|
807
1073
|
/**
|
|
808
1074
|
* Aggregate the schema-wide RLS metadata the studio's read-only inspector reads:
|
|
@@ -822,7 +1088,17 @@ declare const discoverRlsMetadata: (project: Project, lunoraDirectory: string) =
|
|
|
822
1088
|
* Load `<projectRoot>/lunora/schema.ts`, find `defineSchema({...})`, and
|
|
823
1089
|
* return a structural IR. Throws if the file or call cannot be found.
|
|
824
1090
|
*/
|
|
825
|
-
declare const discoverSchema: (project: Project, schemaPath: string) => SchemaIR;
|
|
1091
|
+
declare const discoverSchema: (project: Project, schemaPath: string, projectRoot?: string) => SchemaIR;
|
|
1092
|
+
/** The only file shapes may be declared in — mirrors `lunora/queues.ts`. */
|
|
1093
|
+
declare const SHAPES_FILENAME = "shapes.ts";
|
|
1094
|
+
/**
|
|
1095
|
+
* Discover every replication shape the project declares: exported
|
|
1096
|
+
* `defineShape()` calls in `lunora/shapes.ts`. Returns `[]` when the file
|
|
1097
|
+
* doesn't exist. Only the export binding is lifted — the runtime object carries
|
|
1098
|
+
* the authoritative `table`/`columns`/`compileWhere`, so codegen never
|
|
1099
|
+
* evaluates the predicate.
|
|
1100
|
+
*/
|
|
1101
|
+
declare const discoverShapes: (project: Project, lunoraDirectory: string) => ShapeIR[];
|
|
826
1102
|
/**
|
|
827
1103
|
* Aggregate the schema-wide storage-rule metadata the studio's inspector reads:
|
|
828
1104
|
* every statically-discovered `(bucket, on, prefix, procedure)` entry across all
|
|
@@ -861,22 +1137,51 @@ declare const emitApi: (functions: ReadonlyArray<FunctionIR>, workflows?: Readon
|
|
|
861
1137
|
* Returns `""` when `@lunora/seed` is not a declared dependency, so projects
|
|
862
1138
|
* that don't use it keep a clean `_generated/` and never import the package.
|
|
863
1139
|
*/
|
|
1140
|
+
|
|
1141
|
+
/**
|
|
1142
|
+
* Emit `_generated/collections.ts` — one TanStack DB collection factory per
|
|
1143
|
+
* `defineShape` in `lunora/shapes.ts` (the local-first partial-replication
|
|
1144
|
+
* surface). Each factory builds a live collection that syncs its shape's rowset
|
|
1145
|
+
* through the client's poke protocol (`subscribeShape`), so an app feeds the
|
|
1146
|
+
* result straight to `useLiveQuery`.
|
|
1147
|
+
*
|
|
1148
|
+
* Returns `""` (so `writeIfPresent` skips the file) unless the project both
|
|
1149
|
+
* declares shapes AND installs `@lunora/db` — the add-on that ships
|
|
1150
|
+
* `lunoraCollectionOptions`. `@lunora/db` stays a scoped install even under the
|
|
1151
|
+
* `lunorash` umbrella (an opt-in add-on, like `@lunora/auth`), so its import is
|
|
1152
|
+
* always `@lunora/db/collections`; only the in-umbrella `@lunora/client` import
|
|
1153
|
+
* is remapped to `lunorash/client`.
|
|
1154
|
+
*/
|
|
1155
|
+
declare const emitCollections: (shapes: ReadonlyArray<ShapeIR>, hasDatabase: boolean, useUmbrella?: boolean) => string;
|
|
864
1156
|
interface EmitServerOptions {
|
|
865
1157
|
containers?: ReadonlyArray<ContainerIR>;
|
|
1158
|
+
/**
|
|
1159
|
+
* A `lunora/` source reads `ctx.access` — wires the verified Cloudflare Access
|
|
1160
|
+
* facade (`@lunora/cloudflare-access/context`) onto every ctx. Distinct from
|
|
1161
|
+
* `emitApp`'s `hasAccess` (which gates the worker's `.access()` resolveIdentity
|
|
1162
|
+
* method); this one gates the per-request `ctx.access` read surface.
|
|
1163
|
+
*/
|
|
1164
|
+
hasAccessFacade?: boolean;
|
|
866
1165
|
hasAi?: boolean;
|
|
867
|
-
/** A `lunora/` source uses `@lunora/analytics` / `ctx.analytics` — wires the write helper onto every ctx. */
|
|
1166
|
+
/** A `lunora/` source uses `@lunora/bindings/analytics` / `ctx.analytics` — wires the write helper onto every ctx. */
|
|
868
1167
|
hasAnalytics?: boolean;
|
|
869
1168
|
/** A `lunora/` source uses `@lunora/browser` / `ctx.browser` — wires `ctx.browser` onto ActionCtx only. */
|
|
870
1169
|
hasBrowser?: boolean;
|
|
1170
|
+
/** The project declares `lunora/flags.ts` — wires `ctx.flags` (OpenFeature) onto every ctx. */
|
|
1171
|
+
hasFlags?: boolean;
|
|
871
1172
|
/** A `lunora/` source uses `@lunora/hyperdrive` / `ctx.sql` — wires `ctx.sql` onto ActionCtx only. */
|
|
872
1173
|
hasHyperdrive?: boolean;
|
|
873
|
-
/** A `lunora/` source uses `@lunora/images` / `ctx.images` — wires `ctx.images` onto ActionCtx only. */
|
|
1174
|
+
/** A `lunora/` source uses `@lunora/bindings/images` / `ctx.images` — wires `ctx.images` onto ActionCtx only. */
|
|
874
1175
|
hasImages?: boolean;
|
|
875
|
-
/** A `lunora/` source uses `@lunora/kv` / `ctx.kv` — wires `ctx.kv` onto every ctx. */
|
|
1176
|
+
/** A `lunora/` source uses `@lunora/bindings/kv` / `ctx.kv` — wires `ctx.kv` onto every ctx. */
|
|
876
1177
|
hasKv?: boolean;
|
|
877
1178
|
hasPayments?: boolean;
|
|
878
|
-
/** A `lunora/` source uses `@lunora/pipelines` / `ctx.pipelines` — wires `ctx.pipelines` onto ActionCtx only. */
|
|
1179
|
+
/** A `lunora/` source uses `@lunora/bindings/pipelines` / `ctx.pipelines` — wires `ctx.pipelines` onto ActionCtx only. */
|
|
879
1180
|
hasPipelines?: boolean;
|
|
1181
|
+
/** A `lunora/` source uses `@lunora/bindings/r2sql` / `ctx.r2sql` — wires `ctx.r2sql` onto ActionCtx only. */
|
|
1182
|
+
hasR2sql?: boolean;
|
|
1183
|
+
/** Queues declared via `defineQueue` exports — wires the typed `ctx.queues` producers onto Mutation/Action contexts. */
|
|
1184
|
+
queues?: ReadonlyArray<QueueIR>;
|
|
880
1185
|
schema?: SchemaIR;
|
|
881
1186
|
storageRuleBuckets?: ReadonlyArray<string>;
|
|
882
1187
|
/** The project depends on the `lunora` umbrella — import base packages via its subpaths. */
|
|
@@ -885,20 +1190,24 @@ interface EmitServerOptions {
|
|
|
885
1190
|
}
|
|
886
1191
|
declare const emitServer: ({
|
|
887
1192
|
containers,
|
|
1193
|
+
hasAccessFacade,
|
|
888
1194
|
hasAi,
|
|
889
1195
|
hasAnalytics,
|
|
890
1196
|
hasBrowser,
|
|
1197
|
+
hasFlags,
|
|
891
1198
|
hasHyperdrive,
|
|
892
1199
|
hasImages,
|
|
893
1200
|
hasKv,
|
|
894
1201
|
hasPayments,
|
|
895
1202
|
hasPipelines,
|
|
1203
|
+
hasR2sql,
|
|
1204
|
+
queues,
|
|
896
1205
|
schema,
|
|
897
1206
|
storageRuleBuckets,
|
|
898
1207
|
useUmbrella,
|
|
899
1208
|
workflows
|
|
900
1209
|
}?: EmitServerOptions) => string;
|
|
901
|
-
declare const emitFunctions: (functions: ReadonlyArray<FunctionIR>, migrations?: ReadonlyArray<MigrationIR>) => string;
|
|
1210
|
+
declare const emitFunctions: (functions: ReadonlyArray<FunctionIR>, migrations?: ReadonlyArray<MigrationIR>, useUmbrella?: boolean, mutators?: ReadonlyArray<MutatorIR>, shapes?: ReadonlyArray<ShapeIR>) => string;
|
|
902
1211
|
/**
|
|
903
1212
|
* Storage-column map per table for the file browser: `{ table: [field, …] }` for
|
|
904
1213
|
* every field declared `v.storage(...)` (unwrapping `v.optional(...)`). The
|
|
@@ -916,7 +1225,7 @@ declare const emitFunctions: (functions: ReadonlyArray<FunctionIR>, migrations?:
|
|
|
916
1225
|
* `containers[].class_name` to be exported by the deployed worker. Returns ""
|
|
917
1226
|
* when the project declares no containers (the file is not written then).
|
|
918
1227
|
*/
|
|
919
|
-
declare const emitContainers: (containers: ReadonlyArray<ContainerIR
|
|
1228
|
+
declare const emitContainers: (containers: ReadonlyArray<ContainerIR>, jurisdiction?: JurisdictionIR) => string;
|
|
920
1229
|
/**
|
|
921
1230
|
* Emit `_generated/workflows.ts` — one `WorkflowEntrypoint` class per
|
|
922
1231
|
* `defineWorkflow` export, each a thin subclass of `LunoraWorkflow`
|
|
@@ -926,14 +1235,31 @@ declare const emitContainers: (containers: ReadonlyArray<ContainerIR>) => string
|
|
|
926
1235
|
* when the project declares no workflows (the file is not written then).
|
|
927
1236
|
*/
|
|
928
1237
|
declare const emitWorkflows: (workflows: ReadonlyArray<WorkflowIR>) => string;
|
|
1238
|
+
/**
|
|
1239
|
+
* Emit `_generated/queues.ts` — the push-consumer registry the worker `queue()`
|
|
1240
|
+
* handler dispatches through. Maps each push queue's stable wrangler name (which
|
|
1241
|
+
* `batch.queue` carries) to its `defineQueue` definition + export name. Pull
|
|
1242
|
+
* queues are consumed by an external worker, so they carry no handler and are
|
|
1243
|
+
* omitted here. Returns "" (and the file is not written) when no push queues are
|
|
1244
|
+
* declared — a pull-only or queue-free app keeps a clean `_generated/`.
|
|
1245
|
+
*/
|
|
929
1246
|
interface EmitShardOptions {
|
|
930
1247
|
advisories?: ReadonlyArray<Finding>;
|
|
931
1248
|
containers?: ReadonlyArray<ContainerIR>;
|
|
1249
|
+
/** Statically-discovered `ctx.flags.<type>("key")` reads — the studio Flags page + reactive evaluation iterate these. */
|
|
1250
|
+
flagKeys?: ReadonlyArray<{
|
|
1251
|
+
key: string;
|
|
1252
|
+
type: "boolean" | "number" | "object" | "string";
|
|
1253
|
+
}>;
|
|
1254
|
+
/** A `lunora/` source reads `ctx.access` — wires the verified Cloudflare Access facade onto every ctx. */
|
|
1255
|
+
hasAccessFacade?: boolean;
|
|
932
1256
|
hasAi?: boolean;
|
|
933
1257
|
/** A `lunora/` source reads `ctx.analytics` — wires the Analytics Engine write helper onto every ctx. */
|
|
934
1258
|
hasAnalytics?: boolean;
|
|
935
1259
|
/** A `lunora/` source reads `ctx.browser` — wires `ctx.browser` onto the ActionCtx only. */
|
|
936
1260
|
hasBrowser?: boolean;
|
|
1261
|
+
/** The project declares `lunora/flags.ts` — wires `ctx.flags` (OpenFeature) onto every ctx. */
|
|
1262
|
+
hasFlags?: boolean;
|
|
937
1263
|
/** A `lunora/` source reads `ctx.sql` (Hyperdrive) — wires `ctx.sql` onto the ActionCtx only. */
|
|
938
1264
|
hasHyperdrive?: boolean;
|
|
939
1265
|
/** A `lunora/` source reads `ctx.images` — wires `ctx.images` onto the ActionCtx only. */
|
|
@@ -941,9 +1267,19 @@ interface EmitShardOptions {
|
|
|
941
1267
|
/** A `lunora/` source reads `ctx.kv` — wires `ctx.kv` onto every ctx. */
|
|
942
1268
|
hasKv?: boolean;
|
|
943
1269
|
hasPayments?: boolean;
|
|
1270
|
+
/** A `lunora/` source reads `ctx.pipelines` — wires `ctx.pipelines` onto the ActionCtx only. */
|
|
1271
|
+
hasPipelines?: boolean;
|
|
1272
|
+
/** A `lunora/` source reads `ctx.r2sql` (R2 SQL) — wires `ctx.r2sql` onto the ActionCtx only. */
|
|
1273
|
+
hasR2sql?: boolean;
|
|
944
1274
|
maskMetadata?: MaskMetadataIR;
|
|
1275
|
+
/** Custom mutators declared via `defineMutator` in `lunora/mutators.ts` — wires the `isCustomMutator` push-protocol override. */
|
|
1276
|
+
mutators?: ReadonlyArray<MutatorIR>;
|
|
1277
|
+
/** Queues declared via `defineQueue` exports in `lunora/queues.ts` — wires the typed `ctx.queues` producers. */
|
|
1278
|
+
queues?: ReadonlyArray<QueueIR>;
|
|
945
1279
|
rlsMetadata?: RlsMetadataIR;
|
|
946
1280
|
schema: SchemaIR;
|
|
1281
|
+
/** Replication shapes declared via `defineShape` in `lunora/shapes.ts` — wires the `resolveShape` subscription override. */
|
|
1282
|
+
shapes?: ReadonlyArray<ShapeIR>;
|
|
947
1283
|
storageRules?: StorageRulesMetadataIR;
|
|
948
1284
|
studioFeatures?: StudioFeaturesResult;
|
|
949
1285
|
/** The project depends on the `lunora` umbrella — import base packages via its subpaths. */
|
|
@@ -953,16 +1289,24 @@ interface EmitShardOptions {
|
|
|
953
1289
|
declare const emitShard: ({
|
|
954
1290
|
advisories,
|
|
955
1291
|
containers,
|
|
1292
|
+
flagKeys,
|
|
1293
|
+
hasAccessFacade,
|
|
956
1294
|
hasAi,
|
|
957
1295
|
hasAnalytics,
|
|
958
1296
|
hasBrowser,
|
|
1297
|
+
hasFlags,
|
|
959
1298
|
hasHyperdrive,
|
|
960
1299
|
hasImages,
|
|
961
1300
|
hasKv,
|
|
962
1301
|
hasPayments,
|
|
1302
|
+
hasPipelines,
|
|
1303
|
+
hasR2sql,
|
|
963
1304
|
maskMetadata,
|
|
1305
|
+
mutators,
|
|
1306
|
+
queues,
|
|
964
1307
|
rlsMetadata,
|
|
965
1308
|
schema,
|
|
1309
|
+
shapes,
|
|
966
1310
|
storageRules,
|
|
967
1311
|
studioFeatures,
|
|
968
1312
|
useUmbrella,
|
|
@@ -1027,9 +1371,11 @@ declare const emitVectors: (vectorIndexes: ReadonlyArray<VectorIndexIR>) => stri
|
|
|
1027
1371
|
declare const emitWranglerCronTriggers: (crons: ReadonlyArray<CronJobIR>) => string[];
|
|
1028
1372
|
/** Which capability methods the generated `defineApp` builder exposes — one flag per package-backed feature the app actually uses. */
|
|
1029
1373
|
interface EmitAppOptions {
|
|
1374
|
+
/** App depends on `@lunora/cloudflare-access` → emit `.access()` (wire the Cloudflare Access `resolveIdentity`, composed ahead of `@lunora/auth` when both are present). */
|
|
1375
|
+
hasAccess: boolean;
|
|
1030
1376
|
/** App uses `@lunora/ai` / `ctx.ai` → emit `.ai()` (override the Workers AI binding backing `ctx.ai`). */
|
|
1031
1377
|
hasAi: boolean;
|
|
1032
|
-
/** App uses `@lunora/analytics` / `ctx.analytics` → emit `.analytics()` (override the dataset backing `ctx.analytics`). */
|
|
1378
|
+
/** App uses `@lunora/bindings/analytics` / `ctx.analytics` → emit `.analytics()` (override the dataset backing `ctx.analytics`). */
|
|
1033
1379
|
hasAnalytics: boolean;
|
|
1034
1380
|
/** App depends on `@lunora/auth` → emit `.auth()` + the lazy build/migrate dance. */
|
|
1035
1381
|
hasAuth: boolean;
|
|
@@ -1043,12 +1389,16 @@ interface EmitAppOptions {
|
|
|
1043
1389
|
hasHyperdrive: boolean;
|
|
1044
1390
|
/** Schema declares **Hyperdrive-backed** `.global({ backend: "hyperdrive" })` tables → emit `.hyperdriveGlobal()` (reactive Postgres/MySQL ctx-db over Hyperdrive). */
|
|
1045
1391
|
hasHyperdriveGlobal: boolean;
|
|
1046
|
-
/** App uses `@lunora/images` / `ctx.images` → emit `.images()`. */
|
|
1392
|
+
/** App uses `@lunora/bindings/images` / `ctx.images` → emit `.images()`. */
|
|
1047
1393
|
hasImages: boolean;
|
|
1048
|
-
/** App uses `@lunora/kv` / `ctx.kv` → emit `.kv()`. */
|
|
1394
|
+
/** App uses `@lunora/bindings/kv` / `ctx.kv` → emit `.kv()`. */
|
|
1049
1395
|
hasKv: boolean;
|
|
1050
1396
|
/** App uses `@lunora/payment` / `ctx.payments` → emit `.payment()`. */
|
|
1051
1397
|
hasPayments: boolean;
|
|
1398
|
+
/** App declares push queues (`defineQueue`) → wire `LUNORA_QUEUE_REGISTRY` into the worker's `queue()` consumer entry. */
|
|
1399
|
+
hasQueue: boolean;
|
|
1400
|
+
/** App uses `@lunora/bindings/r2sql` / `ctx.r2sql` → emit `.r2sql()`. */
|
|
1401
|
+
hasR2sql: boolean;
|
|
1052
1402
|
/** App imports `@lunora/scheduler` / declares crons → emit `.scheduler()`. */
|
|
1053
1403
|
hasScheduler: boolean;
|
|
1054
1404
|
/** App uses `@lunora/storage` → emit `.storage()` (DO `ctx.storage` + studio file browser). */
|
|
@@ -1057,6 +1407,8 @@ interface EmitAppOptions {
|
|
|
1057
1407
|
hasVectors: boolean;
|
|
1058
1408
|
/** App declares Cloudflare Workflows (`defineWorkflow`) → wire `options.workflowsClient` so the studio's workflow-instance proxy can reach the CF REST API. */
|
|
1059
1409
|
hasWorkflow: boolean;
|
|
1410
|
+
/** Schema declares `.jurisdiction("…")` → pin every DO the worker reaches (shards, fan-out, scheduler, containers) to the Cloudflare data-residency jurisdiction. */
|
|
1411
|
+
jurisdiction?: JurisdictionIR;
|
|
1060
1412
|
/** Project depends on the unscoped `lunorash` umbrella → import the runtime via `lunorash/runtime` instead of `@lunora/runtime`. */
|
|
1061
1413
|
useUmbrella: boolean;
|
|
1062
1414
|
/** An OpenAPI spec is emitted (`openapi.ts`) → wire `openApiSpec` into the worker. */
|
|
@@ -1201,6 +1553,19 @@ interface TableSnapshot {
|
|
|
1201
1553
|
}
|
|
1202
1554
|
/** The committed baseline — a deterministic structural view of the whole schema. */
|
|
1203
1555
|
interface SchemaSnapshot {
|
|
1556
|
+
/**
|
|
1557
|
+
* Cloudflare DO data-residency jurisdiction declared via `.jurisdiction("…")`,
|
|
1558
|
+
* or absent. Tracked because changing it strands all existing Durable Object
|
|
1559
|
+
* data (a DO name maps to a different ID per jurisdiction). Optional, so old
|
|
1560
|
+
* baselines written before this field parse cleanly (absent ⇒ undefined).
|
|
1561
|
+
*
|
|
1562
|
+
* Typed as a plain `string` (not the authoring union) on purpose: this is
|
|
1563
|
+
* STORED data that a newer Lunora may have written with a jurisdiction this
|
|
1564
|
+
* version doesn't yet know. Preserving the raw value keeps the breaking
|
|
1565
|
+
* `changedJurisdiction` diff correct under a downgrade — coercing an unknown
|
|
1566
|
+
* value to `undefined` would fail OPEN and hide the most destructive change.
|
|
1567
|
+
*/
|
|
1568
|
+
jurisdiction?: string;
|
|
1204
1569
|
/** Sorted list of every declared `defineMigration` id at capture time. */
|
|
1205
1570
|
migrationIds: ReadonlyArray<string>;
|
|
1206
1571
|
/** Table name → {@link TableSnapshot}, keys sorted for stable serialization. */
|
|
@@ -1214,7 +1579,7 @@ interface DriftChange {
|
|
|
1214
1579
|
/** Human-readable, actionable description (used in the gate message). */
|
|
1215
1580
|
summary: string;
|
|
1216
1581
|
/** A machine-readable change discriminator. */
|
|
1217
|
-
type: "addedIndex" | "addedOptionalField" | "addedRelation" | "addedRequiredField" | "addedTable" | "changedFieldKind" | "changedIndex" | "changedShardMode" | "fieldOptionalToRequired" | "fieldRequiredToOptional" | "removedField" | "removedIndex" | "removedRelation" | "removedTable";
|
|
1582
|
+
type: "addedIndex" | "addedOptionalField" | "addedRelation" | "addedRequiredField" | "addedTable" | "changedJurisdiction" | "changedFieldKind" | "changedIndex" | "changedShardMode" | "fieldOptionalToRequired" | "fieldRequiredToOptional" | "removedField" | "removedIndex" | "removedRelation" | "removedTable";
|
|
1218
1583
|
}
|
|
1219
1584
|
/** The result of diffing two snapshots: every classified change. */
|
|
1220
1585
|
interface SchemaDrift {
|
|
@@ -1316,6 +1681,11 @@ declare const refreshCodegenProject: (project: Project, lunoraDirectory: string)
|
|
|
1316
1681
|
* Top-level codegen entry. Parses `<projectRoot>/lunora/schema.ts` and every
|
|
1317
1682
|
* function file under `<projectRoot>/lunora/`, then writes
|
|
1318
1683
|
* `_generated/{api,server,dataModel}.ts` next to them.
|
|
1684
|
+
*
|
|
1685
|
+
* When `LUNORA_CODEGEN_TIMING` is set (truthy), a single diagnostic summary
|
|
1686
|
+
* line is written to stderr with the total wall time and the discovery-vs-emit
|
|
1687
|
+
* split — opt-in instrumentation that is otherwise zero-cost and side-effect-free
|
|
1688
|
+
* on the returned {@link CodegenResult}.
|
|
1319
1689
|
*/
|
|
1320
1690
|
declare const runCodegen: (options: CodegenOptions) => CodegenResult;
|
|
1321
1691
|
interface CodegenOptions {
|
|
@@ -1392,6 +1762,8 @@ interface CodegenResult {
|
|
|
1392
1762
|
generated: {
|
|
1393
1763
|
api: string; /** Fluent worker-composition builder (`_generated/app.ts`) — `defineApp()`. Always written. */
|
|
1394
1764
|
app: string;
|
|
1765
|
+
/** Partial-replication collection factories (`_generated/collections.ts`); `""` (and not written) unless the project declares shapes and installs `@lunora/db`. */
|
|
1766
|
+
collections: string;
|
|
1395
1767
|
/** Container DO classes (`_generated/containers.ts`); `""` (and not written) when no containers are declared. */
|
|
1396
1768
|
containers: string;
|
|
1397
1769
|
crons: string;
|
|
@@ -1416,6 +1788,8 @@ interface CodegenResult {
|
|
|
1416
1788
|
* `apiSpec` includes `openrpc`.
|
|
1417
1789
|
*/
|
|
1418
1790
|
openRpcModule: string;
|
|
1791
|
+
/** Push-consumer queue registry (`_generated/queues.ts`); `""` (and not written) when no push queues are declared. */
|
|
1792
|
+
queues: string;
|
|
1419
1793
|
/** Project-bound seed client (`_generated/seed.ts`); `""` (and not written) when `@lunora/seed` is not a declared dependency. */
|
|
1420
1794
|
seed: string;
|
|
1421
1795
|
server: string;
|
|
@@ -1426,6 +1800,13 @@ interface CodegenResult {
|
|
|
1426
1800
|
};
|
|
1427
1801
|
outputDirectory: string;
|
|
1428
1802
|
/**
|
|
1803
|
+
* Queues discovered from `defineQueue` exports in `lunora/queues.ts` — the
|
|
1804
|
+
* list the config layer reconciles into wrangler's `queues.producers[]` /
|
|
1805
|
+
* `queues.consumers[]`. Queues are NOT Durable Objects, so this adds no
|
|
1806
|
+
* binding or migration. Empty when the project declares no queues.
|
|
1807
|
+
*/
|
|
1808
|
+
queues: ReadonlyArray<QueueIR>;
|
|
1809
|
+
/**
|
|
1429
1810
|
* The CURRENT structural schema snapshot computed this run (tables + field
|
|
1430
1811
|
* kinds/optionality + indexes/relations/shard mode + declared migration ids).
|
|
1431
1812
|
* The pre-deploy drift gate diffs this against the committed baseline read
|
|
@@ -1469,5 +1850,52 @@ declare const validatorIrToJsonSchema: (validator: ValidatorIR) => JsonSchema;
|
|
|
1469
1850
|
* the contract; clients switch on `error.code`. Kept sorted for stable output.
|
|
1470
1851
|
*/
|
|
1471
1852
|
declare const LUNORA_ERROR_CODES: ReadonlyArray<string>;
|
|
1853
|
+
/**
|
|
1854
|
+
* Lunora-specific error→solution hints. A small rule table mapping the exact
|
|
1855
|
+
* messages Lunora throws — codegen/schema diagnostics, worker-entry export gaps,
|
|
1856
|
+
* and the runtime data-layer conflicts — to an actionable fix.
|
|
1857
|
+
*
|
|
1858
|
+
* This table is the single source of truth shared by every consumer that wants
|
|
1859
|
+
* to turn a raw Lunora error into a fix hint: the Vite error overlay
|
|
1860
|
+
* (`@lunora/vite`) renders the Markdown in the browser, and the standalone
|
|
1861
|
+
* `lunora dev` CLI prints it to the terminal. It lives in `@lunora/codegen`
|
|
1862
|
+
* because codegen owns most of the throw sites, so the hints stay next to the
|
|
1863
|
+
* code that produces the messages.
|
|
1864
|
+
*
|
|
1865
|
+
* Matching is on the **message text**. By the time a diagnostic reaches a
|
|
1866
|
+
* consumer it has often been flattened to a plain `{ message }` (the overlay
|
|
1867
|
+
* pushes codegen errors through `server.hot.send` with `name === "Error"`), so
|
|
1868
|
+
* the class identity is gone and the message is the only stable signal.
|
|
1869
|
+
*
|
|
1870
|
+
* Bodies are Markdown — the overlay renders them; the CLI prints them (lightly
|
|
1871
|
+
* de-marked) as-is.
|
|
1872
|
+
*/
|
|
1873
|
+
/** A resolved hint for a recognized Lunora error. */
|
|
1874
|
+
interface LunoraSolution {
|
|
1875
|
+
/** Markdown body shown under the header. */
|
|
1876
|
+
body: string;
|
|
1877
|
+
/** Short header for the solution. */
|
|
1878
|
+
header: string;
|
|
1879
|
+
/** Stable id (used in DEBUG logs and tests). */
|
|
1880
|
+
id: string;
|
|
1881
|
+
}
|
|
1882
|
+
/** A single error→solution rule: a {@link LunoraSolution} plus its matcher. */
|
|
1883
|
+
interface LunoraSolutionRule extends LunoraSolution {
|
|
1884
|
+
/** True when this rule recognizes the error message. */
|
|
1885
|
+
test: (message: string) => boolean;
|
|
1886
|
+
}
|
|
1887
|
+
/**
|
|
1888
|
+
* The rules, ordered most- to least-specific: the dev-time codegen/schema rules
|
|
1889
|
+
* come first because they're the errors a developer hits while editing
|
|
1890
|
+
* `lunora/`, then the runtime data-layer conflicts that surface from the worker.
|
|
1891
|
+
* The first matching rule (in array order) wins.
|
|
1892
|
+
*/
|
|
1893
|
+
declare const LUNORA_SOLUTION_RULES: ReadonlyArray<LunoraSolutionRule>;
|
|
1894
|
+
/**
|
|
1895
|
+
* Find the first Lunora solution whose rule matches `message`, or `undefined`
|
|
1896
|
+
* if none recognize it. Consumers turn the returned Markdown into their own
|
|
1897
|
+
* presentation (overlay panel, terminal hint, …).
|
|
1898
|
+
*/
|
|
1899
|
+
declare const findLunoraSolution: (message: string) => LunoraSolution | undefined;
|
|
1472
1900
|
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 };
|
|
1901
|
+
export { type AuthApiCallIR, CONTAINERS_FILENAME, CodegenDiagnosticError, type CodegenOptions, type CodegenResult, type ContainerIR, type CronJobIR, type DriftChange, type EmitAppOptions, FLAGS_FILENAME, type FieldSnapshot, type FlagsIR, type FunctionIR, GENERATED_HEADER, type HttpRouteIR, type IndexIR, type IndexSnapshot, type InsertWriteIR, LUNORA_ERROR_CODES, LUNORA_SOLUTION_RULES, type LunoraSolution, type LunoraSolutionRule, MUTATORS_FILENAME, type MaskProcedureIR, type MigrationIR, type MutatorIR, 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, SHAPES_FILENAME, type SchemaDrift, type SchemaDriftDecision, type SchemaIR, type SchemaSnapshot, SchemaSnapshotParseError, type ShapeIR, 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, discoverFlags, discoverFunctions, discoverHttpRoutes, discoverInserts, discoverMaskProcedures, discoverMigrations, discoverMutators, discoverNondeterministicCalls, discoverQueries, discoverQueues, discoverR2sqlCalls, discoverRlsMetadata, discoverRlsProcedures, discoverSchema, discoverShapes, discoverStorageRulesMetadata, discoverWorkflows, emitApi, emitApp, emitCollections, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitOpenApi, emitOpenApiModule, emitOpenRpc, emitOpenRpcModule, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers, evaluateSchemaDrift, findLunoraSolution, formatAdvisories, lintSchema, parseSchemaSnapshot, refreshCodegenProject, runCodegen, schemaFromIr, serializeSchemaSnapshot, validatorIrToJsonSchema };
|