@lunora/codegen 1.0.0-alpha.10 → 1.0.0-alpha.12
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/dist/index.d.mts +78 -10
- package/dist/index.d.ts +78 -10
- package/dist/index.mjs +6 -5
- package/dist/packem_shared/{GENERATED_HEADER-BiFXNUvo.mjs → GENERATED_HEADER-BEA7oWGC.mjs} +183 -34
- package/dist/packem_shared/{OPENRPC_VERSION-B4i9Qp3v.mjs → OPENRPC_VERSION-CQ3f8YQ-.mjs} +1 -1
- package/dist/packem_shared/QUEUES_FILENAME-B5_eWCRe.mjs +119 -0
- package/dist/packem_shared/{SCHEMA_SNAPSHOT_FILENAME-Bvv7qa_u.mjs → SCHEMA_SNAPSHOT_FILENAME-BXtduJFE.mjs} +26 -11
- package/dist/packem_shared/{buildOpenApiDocument-Cu3mZl-8.mjs → buildOpenApiDocument-699G4RP4.mjs} +1 -1
- package/dist/packem_shared/{emitApp-KfMaKXWe.mjs → emitApp-DiK0QSBn.mjs} +17 -3
- package/package.json +8 -7
package/dist/index.d.mts
CHANGED
|
@@ -312,6 +312,37 @@ interface WorkflowIR {
|
|
|
312
312
|
name: string;
|
|
313
313
|
}
|
|
314
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
|
+
/**
|
|
315
346
|
* A `ctx.workflows.get("name")…` call discovered in a function body — the
|
|
316
347
|
* use-site analog of {@link WorkflowIR} (which is the declaration side). Feeds
|
|
317
348
|
* the `workflow_unused` lint (a declared workflow with zero call sites) and the
|
|
@@ -851,6 +882,15 @@ declare const discoverNondeterministicCalls: (project: Project, lunoraDirectory:
|
|
|
851
882
|
* dropping the rest keeps the lint input small.
|
|
852
883
|
*/
|
|
853
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[];
|
|
854
894
|
/**
|
|
855
895
|
* Discover `ctx.r2sql` accesses lexically inside the handler body of every
|
|
856
896
|
* exported `query(...)` / `mutation(...)` registration under the lunora source
|
|
@@ -925,21 +965,23 @@ declare const emitApi: (functions: ReadonlyArray<FunctionIR>, workflows?: Readon
|
|
|
925
965
|
interface EmitServerOptions {
|
|
926
966
|
containers?: ReadonlyArray<ContainerIR>;
|
|
927
967
|
hasAi?: boolean;
|
|
928
|
-
/** 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. */
|
|
929
969
|
hasAnalytics?: boolean;
|
|
930
970
|
/** A `lunora/` source uses `@lunora/browser` / `ctx.browser` — wires `ctx.browser` onto ActionCtx only. */
|
|
931
971
|
hasBrowser?: boolean;
|
|
932
972
|
/** A `lunora/` source uses `@lunora/hyperdrive` / `ctx.sql` — wires `ctx.sql` onto ActionCtx only. */
|
|
933
973
|
hasHyperdrive?: boolean;
|
|
934
|
-
/** 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. */
|
|
935
975
|
hasImages?: boolean;
|
|
936
|
-
/** 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. */
|
|
937
977
|
hasKv?: boolean;
|
|
938
978
|
hasPayments?: boolean;
|
|
939
|
-
/** 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. */
|
|
940
980
|
hasPipelines?: boolean;
|
|
941
|
-
/** A `lunora/` source uses `@lunora/r2sql` / `ctx.r2sql` — wires `ctx.r2sql` onto ActionCtx only. */
|
|
981
|
+
/** A `lunora/` source uses `@lunora/bindings/r2sql` / `ctx.r2sql` — wires `ctx.r2sql` onto ActionCtx only. */
|
|
942
982
|
hasR2sql?: boolean;
|
|
983
|
+
/** Queues declared via `defineQueue` exports — wires the typed `ctx.queues` producers onto Mutation/Action contexts. */
|
|
984
|
+
queues?: ReadonlyArray<QueueIR>;
|
|
943
985
|
schema?: SchemaIR;
|
|
944
986
|
storageRuleBuckets?: ReadonlyArray<string>;
|
|
945
987
|
/** The project depends on the `lunora` umbrella — import base packages via its subpaths. */
|
|
@@ -957,6 +999,7 @@ declare const emitServer: ({
|
|
|
957
999
|
hasPayments,
|
|
958
1000
|
hasPipelines,
|
|
959
1001
|
hasR2sql,
|
|
1002
|
+
queues,
|
|
960
1003
|
schema,
|
|
961
1004
|
storageRuleBuckets,
|
|
962
1005
|
useUmbrella,
|
|
@@ -990,6 +1033,14 @@ declare const emitContainers: (containers: ReadonlyArray<ContainerIR>, jurisdict
|
|
|
990
1033
|
* when the project declares no workflows (the file is not written then).
|
|
991
1034
|
*/
|
|
992
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
|
+
*/
|
|
993
1044
|
interface EmitShardOptions {
|
|
994
1045
|
advisories?: ReadonlyArray<Finding>;
|
|
995
1046
|
containers?: ReadonlyArray<ContainerIR>;
|
|
@@ -1005,9 +1056,13 @@ interface EmitShardOptions {
|
|
|
1005
1056
|
/** A `lunora/` source reads `ctx.kv` — wires `ctx.kv` onto every ctx. */
|
|
1006
1057
|
hasKv?: boolean;
|
|
1007
1058
|
hasPayments?: boolean;
|
|
1059
|
+
/** A `lunora/` source reads `ctx.pipelines` — wires `ctx.pipelines` onto the ActionCtx only. */
|
|
1060
|
+
hasPipelines?: boolean;
|
|
1008
1061
|
/** A `lunora/` source reads `ctx.r2sql` (R2 SQL) — wires `ctx.r2sql` onto the ActionCtx only. */
|
|
1009
1062
|
hasR2sql?: boolean;
|
|
1010
1063
|
maskMetadata?: MaskMetadataIR;
|
|
1064
|
+
/** Queues declared via `defineQueue` exports in `lunora/queues.ts` — wires the typed `ctx.queues` producers. */
|
|
1065
|
+
queues?: ReadonlyArray<QueueIR>;
|
|
1011
1066
|
rlsMetadata?: RlsMetadataIR;
|
|
1012
1067
|
schema: SchemaIR;
|
|
1013
1068
|
storageRules?: StorageRulesMetadataIR;
|
|
@@ -1026,8 +1081,10 @@ declare const emitShard: ({
|
|
|
1026
1081
|
hasImages,
|
|
1027
1082
|
hasKv,
|
|
1028
1083
|
hasPayments,
|
|
1084
|
+
hasPipelines,
|
|
1029
1085
|
hasR2sql,
|
|
1030
1086
|
maskMetadata,
|
|
1087
|
+
queues,
|
|
1031
1088
|
rlsMetadata,
|
|
1032
1089
|
schema,
|
|
1033
1090
|
storageRules,
|
|
@@ -1096,7 +1153,7 @@ declare const emitWranglerCronTriggers: (crons: ReadonlyArray<CronJobIR>) => str
|
|
|
1096
1153
|
interface EmitAppOptions {
|
|
1097
1154
|
/** App uses `@lunora/ai` / `ctx.ai` → emit `.ai()` (override the Workers AI binding backing `ctx.ai`). */
|
|
1098
1155
|
hasAi: boolean;
|
|
1099
|
-
/** 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`). */
|
|
1100
1157
|
hasAnalytics: boolean;
|
|
1101
1158
|
/** App depends on `@lunora/auth` → emit `.auth()` + the lazy build/migrate dance. */
|
|
1102
1159
|
hasAuth: boolean;
|
|
@@ -1110,13 +1167,15 @@ interface EmitAppOptions {
|
|
|
1110
1167
|
hasHyperdrive: boolean;
|
|
1111
1168
|
/** Schema declares **Hyperdrive-backed** `.global({ backend: "hyperdrive" })` tables → emit `.hyperdriveGlobal()` (reactive Postgres/MySQL ctx-db over Hyperdrive). */
|
|
1112
1169
|
hasHyperdriveGlobal: boolean;
|
|
1113
|
-
/** App uses `@lunora/images` / `ctx.images` → emit `.images()`. */
|
|
1170
|
+
/** App uses `@lunora/bindings/images` / `ctx.images` → emit `.images()`. */
|
|
1114
1171
|
hasImages: boolean;
|
|
1115
|
-
/** App uses `@lunora/kv` / `ctx.kv` → emit `.kv()`. */
|
|
1172
|
+
/** App uses `@lunora/bindings/kv` / `ctx.kv` → emit `.kv()`. */
|
|
1116
1173
|
hasKv: boolean;
|
|
1117
1174
|
/** App uses `@lunora/payment` / `ctx.payments` → emit `.payment()`. */
|
|
1118
1175
|
hasPayments: boolean;
|
|
1119
|
-
/** App
|
|
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()`. */
|
|
1120
1179
|
hasR2sql: boolean;
|
|
1121
1180
|
/** App imports `@lunora/scheduler` / declares crons → emit `.scheduler()`. */
|
|
1122
1181
|
hasScheduler: boolean;
|
|
@@ -1505,6 +1564,8 @@ interface CodegenResult {
|
|
|
1505
1564
|
* `apiSpec` includes `openrpc`.
|
|
1506
1565
|
*/
|
|
1507
1566
|
openRpcModule: string;
|
|
1567
|
+
/** Push-consumer queue registry (`_generated/queues.ts`); `""` (and not written) when no push queues are declared. */
|
|
1568
|
+
queues: string;
|
|
1508
1569
|
/** Project-bound seed client (`_generated/seed.ts`); `""` (and not written) when `@lunora/seed` is not a declared dependency. */
|
|
1509
1570
|
seed: string;
|
|
1510
1571
|
server: string;
|
|
@@ -1515,6 +1576,13 @@ interface CodegenResult {
|
|
|
1515
1576
|
};
|
|
1516
1577
|
outputDirectory: string;
|
|
1517
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
|
+
/**
|
|
1518
1586
|
* The CURRENT structural schema snapshot computed this run (tables + field
|
|
1519
1587
|
* kinds/optionality + indexes/relations/shard mode + declared migration ids).
|
|
1520
1588
|
* The pre-deploy drift gate diffs this against the committed baseline read
|
|
@@ -1559,4 +1627,4 @@ declare const validatorIrToJsonSchema: (validator: ValidatorIR) => JsonSchema;
|
|
|
1559
1627
|
*/
|
|
1560
1628
|
declare const LUNORA_ERROR_CODES: ReadonlyArray<string>;
|
|
1561
1629
|
declare const VERSION = "0.0.0";
|
|
1562
|
-
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 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, 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 };
|
|
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.d.ts
CHANGED
|
@@ -312,6 +312,37 @@ interface WorkflowIR {
|
|
|
312
312
|
name: string;
|
|
313
313
|
}
|
|
314
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
|
+
/**
|
|
315
346
|
* A `ctx.workflows.get("name")…` call discovered in a function body — the
|
|
316
347
|
* use-site analog of {@link WorkflowIR} (which is the declaration side). Feeds
|
|
317
348
|
* the `workflow_unused` lint (a declared workflow with zero call sites) and the
|
|
@@ -851,6 +882,15 @@ declare const discoverNondeterministicCalls: (project: Project, lunoraDirectory:
|
|
|
851
882
|
* dropping the rest keeps the lint input small.
|
|
852
883
|
*/
|
|
853
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[];
|
|
854
894
|
/**
|
|
855
895
|
* Discover `ctx.r2sql` accesses lexically inside the handler body of every
|
|
856
896
|
* exported `query(...)` / `mutation(...)` registration under the lunora source
|
|
@@ -925,21 +965,23 @@ declare const emitApi: (functions: ReadonlyArray<FunctionIR>, workflows?: Readon
|
|
|
925
965
|
interface EmitServerOptions {
|
|
926
966
|
containers?: ReadonlyArray<ContainerIR>;
|
|
927
967
|
hasAi?: boolean;
|
|
928
|
-
/** 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. */
|
|
929
969
|
hasAnalytics?: boolean;
|
|
930
970
|
/** A `lunora/` source uses `@lunora/browser` / `ctx.browser` — wires `ctx.browser` onto ActionCtx only. */
|
|
931
971
|
hasBrowser?: boolean;
|
|
932
972
|
/** A `lunora/` source uses `@lunora/hyperdrive` / `ctx.sql` — wires `ctx.sql` onto ActionCtx only. */
|
|
933
973
|
hasHyperdrive?: boolean;
|
|
934
|
-
/** 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. */
|
|
935
975
|
hasImages?: boolean;
|
|
936
|
-
/** 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. */
|
|
937
977
|
hasKv?: boolean;
|
|
938
978
|
hasPayments?: boolean;
|
|
939
|
-
/** 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. */
|
|
940
980
|
hasPipelines?: boolean;
|
|
941
|
-
/** A `lunora/` source uses `@lunora/r2sql` / `ctx.r2sql` — wires `ctx.r2sql` onto ActionCtx only. */
|
|
981
|
+
/** A `lunora/` source uses `@lunora/bindings/r2sql` / `ctx.r2sql` — wires `ctx.r2sql` onto ActionCtx only. */
|
|
942
982
|
hasR2sql?: boolean;
|
|
983
|
+
/** Queues declared via `defineQueue` exports — wires the typed `ctx.queues` producers onto Mutation/Action contexts. */
|
|
984
|
+
queues?: ReadonlyArray<QueueIR>;
|
|
943
985
|
schema?: SchemaIR;
|
|
944
986
|
storageRuleBuckets?: ReadonlyArray<string>;
|
|
945
987
|
/** The project depends on the `lunora` umbrella — import base packages via its subpaths. */
|
|
@@ -957,6 +999,7 @@ declare const emitServer: ({
|
|
|
957
999
|
hasPayments,
|
|
958
1000
|
hasPipelines,
|
|
959
1001
|
hasR2sql,
|
|
1002
|
+
queues,
|
|
960
1003
|
schema,
|
|
961
1004
|
storageRuleBuckets,
|
|
962
1005
|
useUmbrella,
|
|
@@ -990,6 +1033,14 @@ declare const emitContainers: (containers: ReadonlyArray<ContainerIR>, jurisdict
|
|
|
990
1033
|
* when the project declares no workflows (the file is not written then).
|
|
991
1034
|
*/
|
|
992
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
|
+
*/
|
|
993
1044
|
interface EmitShardOptions {
|
|
994
1045
|
advisories?: ReadonlyArray<Finding>;
|
|
995
1046
|
containers?: ReadonlyArray<ContainerIR>;
|
|
@@ -1005,9 +1056,13 @@ interface EmitShardOptions {
|
|
|
1005
1056
|
/** A `lunora/` source reads `ctx.kv` — wires `ctx.kv` onto every ctx. */
|
|
1006
1057
|
hasKv?: boolean;
|
|
1007
1058
|
hasPayments?: boolean;
|
|
1059
|
+
/** A `lunora/` source reads `ctx.pipelines` — wires `ctx.pipelines` onto the ActionCtx only. */
|
|
1060
|
+
hasPipelines?: boolean;
|
|
1008
1061
|
/** A `lunora/` source reads `ctx.r2sql` (R2 SQL) — wires `ctx.r2sql` onto the ActionCtx only. */
|
|
1009
1062
|
hasR2sql?: boolean;
|
|
1010
1063
|
maskMetadata?: MaskMetadataIR;
|
|
1064
|
+
/** Queues declared via `defineQueue` exports in `lunora/queues.ts` — wires the typed `ctx.queues` producers. */
|
|
1065
|
+
queues?: ReadonlyArray<QueueIR>;
|
|
1011
1066
|
rlsMetadata?: RlsMetadataIR;
|
|
1012
1067
|
schema: SchemaIR;
|
|
1013
1068
|
storageRules?: StorageRulesMetadataIR;
|
|
@@ -1026,8 +1081,10 @@ declare const emitShard: ({
|
|
|
1026
1081
|
hasImages,
|
|
1027
1082
|
hasKv,
|
|
1028
1083
|
hasPayments,
|
|
1084
|
+
hasPipelines,
|
|
1029
1085
|
hasR2sql,
|
|
1030
1086
|
maskMetadata,
|
|
1087
|
+
queues,
|
|
1031
1088
|
rlsMetadata,
|
|
1032
1089
|
schema,
|
|
1033
1090
|
storageRules,
|
|
@@ -1096,7 +1153,7 @@ declare const emitWranglerCronTriggers: (crons: ReadonlyArray<CronJobIR>) => str
|
|
|
1096
1153
|
interface EmitAppOptions {
|
|
1097
1154
|
/** App uses `@lunora/ai` / `ctx.ai` → emit `.ai()` (override the Workers AI binding backing `ctx.ai`). */
|
|
1098
1155
|
hasAi: boolean;
|
|
1099
|
-
/** 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`). */
|
|
1100
1157
|
hasAnalytics: boolean;
|
|
1101
1158
|
/** App depends on `@lunora/auth` → emit `.auth()` + the lazy build/migrate dance. */
|
|
1102
1159
|
hasAuth: boolean;
|
|
@@ -1110,13 +1167,15 @@ interface EmitAppOptions {
|
|
|
1110
1167
|
hasHyperdrive: boolean;
|
|
1111
1168
|
/** Schema declares **Hyperdrive-backed** `.global({ backend: "hyperdrive" })` tables → emit `.hyperdriveGlobal()` (reactive Postgres/MySQL ctx-db over Hyperdrive). */
|
|
1112
1169
|
hasHyperdriveGlobal: boolean;
|
|
1113
|
-
/** App uses `@lunora/images` / `ctx.images` → emit `.images()`. */
|
|
1170
|
+
/** App uses `@lunora/bindings/images` / `ctx.images` → emit `.images()`. */
|
|
1114
1171
|
hasImages: boolean;
|
|
1115
|
-
/** App uses `@lunora/kv` / `ctx.kv` → emit `.kv()`. */
|
|
1172
|
+
/** App uses `@lunora/bindings/kv` / `ctx.kv` → emit `.kv()`. */
|
|
1116
1173
|
hasKv: boolean;
|
|
1117
1174
|
/** App uses `@lunora/payment` / `ctx.payments` → emit `.payment()`. */
|
|
1118
1175
|
hasPayments: boolean;
|
|
1119
|
-
/** App
|
|
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()`. */
|
|
1120
1179
|
hasR2sql: boolean;
|
|
1121
1180
|
/** App imports `@lunora/scheduler` / declares crons → emit `.scheduler()`. */
|
|
1122
1181
|
hasScheduler: boolean;
|
|
@@ -1505,6 +1564,8 @@ interface CodegenResult {
|
|
|
1505
1564
|
* `apiSpec` includes `openrpc`.
|
|
1506
1565
|
*/
|
|
1507
1566
|
openRpcModule: string;
|
|
1567
|
+
/** Push-consumer queue registry (`_generated/queues.ts`); `""` (and not written) when no push queues are declared. */
|
|
1568
|
+
queues: string;
|
|
1508
1569
|
/** Project-bound seed client (`_generated/seed.ts`); `""` (and not written) when `@lunora/seed` is not a declared dependency. */
|
|
1509
1570
|
seed: string;
|
|
1510
1571
|
server: string;
|
|
@@ -1515,6 +1576,13 @@ interface CodegenResult {
|
|
|
1515
1576
|
};
|
|
1516
1577
|
outputDirectory: string;
|
|
1517
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
|
+
/**
|
|
1518
1586
|
* The CURRENT structural schema snapshot computed this run (tables + field
|
|
1519
1587
|
* kinds/optionality + indexes/relations/shard mode + declared migration ids).
|
|
1520
1588
|
* The pre-deploy drift gate diffs this against the committed baseline read
|
|
@@ -1559,4 +1627,4 @@ declare const validatorIrToJsonSchema: (validator: ValidatorIR) => JsonSchema;
|
|
|
1559
1627
|
*/
|
|
1560
1628
|
declare const LUNORA_ERROR_CODES: ReadonlyArray<string>;
|
|
1561
1629
|
declare const VERSION = "0.0.0";
|
|
1562
|
-
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 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, 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 };
|
|
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
|
@@ -10,16 +10,17 @@ export { default as discoverMaskProcedures } from './packem_shared/discoverMaskP
|
|
|
10
10
|
export { default as discoverMigrations } from './packem_shared/discoverMigrations-Bi5nJ0mJ.mjs';
|
|
11
11
|
export { default as discoverNondeterministicCalls } from './packem_shared/discoverNondeterministicCalls-C4M8AXmQ.mjs';
|
|
12
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';
|
|
13
14
|
export { default as discoverR2sqlCalls } from './packem_shared/discoverR2sqlCalls-BVNMd428.mjs';
|
|
14
15
|
export { discoverRlsMetadata, default as discoverRlsProcedures } from './packem_shared/discoverRlsMetadata-BS9GOGC5.mjs';
|
|
15
16
|
export { default as discoverSchema } from './packem_shared/discoverSchema-BnWHHJ4T.mjs';
|
|
16
17
|
export { default as discoverStorageRulesMetadata } from './packem_shared/discoverStorageRulesMetadata-Da8BKXcI.mjs';
|
|
17
18
|
export { WORKFLOWS_FILENAME, discoverWorkflows } from './packem_shared/WORKFLOWS_FILENAME-D62dcBGg.mjs';
|
|
18
|
-
export { GENERATED_HEADER, emitApi, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers } from './packem_shared/GENERATED_HEADER-
|
|
19
|
-
export { emitApp } from './packem_shared/emitApp-
|
|
20
|
-
export { buildOpenApiDocument, emitOpenApi, emitOpenApiModule } from './packem_shared/buildOpenApiDocument-
|
|
21
|
-
export { OPENRPC_VERSION, buildOpenRpcDocument, emitOpenRpc, emitOpenRpcModule } from './packem_shared/OPENRPC_VERSION-
|
|
22
|
-
export { SCHEMA_SNAPSHOT_FILENAME, createCodegenProject, refreshCodegenProject, runCodegen } from './packem_shared/SCHEMA_SNAPSHOT_FILENAME-
|
|
19
|
+
export { GENERATED_HEADER, emitApi, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers } from './packem_shared/GENERATED_HEADER-BEA7oWGC.mjs';
|
|
20
|
+
export { emitApp } from './packem_shared/emitApp-DiK0QSBn.mjs';
|
|
21
|
+
export { buildOpenApiDocument, emitOpenApi, emitOpenApiModule } from './packem_shared/buildOpenApiDocument-699G4RP4.mjs';
|
|
22
|
+
export { OPENRPC_VERSION, buildOpenRpcDocument, emitOpenRpc, emitOpenRpcModule } from './packem_shared/OPENRPC_VERSION-CQ3f8YQ-.mjs';
|
|
23
|
+
export { SCHEMA_SNAPSHOT_FILENAME, createCodegenProject, refreshCodegenProject, runCodegen } from './packem_shared/SCHEMA_SNAPSHOT_FILENAME-BXtduJFE.mjs';
|
|
23
24
|
export { SCHEMA_SNAPSHOT_VERSION, SchemaSnapshotParseError, buildSchemaSnapshot, diffSchemaSnapshots, evaluateSchemaDrift, parseSchemaSnapshot, serializeSchemaSnapshot } from './packem_shared/SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs';
|
|
24
25
|
export { schemaFromIr } from './packem_shared/schemaFromIr-DTYsLBaA.mjs';
|
|
25
26
|
export { LUNORA_ERROR_CODES, validatorIrToJsonSchema } from './packem_shared/LUNORA_ERROR_CODES-CySpQPD3.mjs';
|
|
@@ -722,6 +722,7 @@ const emitServer = ({
|
|
|
722
722
|
hasPayments = false,
|
|
723
723
|
hasPipelines = false,
|
|
724
724
|
hasR2sql = false,
|
|
725
|
+
queues = [],
|
|
725
726
|
schema,
|
|
726
727
|
storageRuleBuckets = [],
|
|
727
728
|
useUmbrella = false,
|
|
@@ -755,6 +756,11 @@ const emitServer = ({
|
|
|
755
756
|
assertIdentifier(workflow.bindingName, `workflow binding "${workflow.bindingName}"`);
|
|
756
757
|
return ` /** Workflow binding for the \`${workflow.exportName}\` workflow. */
|
|
757
758
|
readonly ${workflow.bindingName}?: unknown;`;
|
|
759
|
+
}),
|
|
760
|
+
...queues.map((queue) => {
|
|
761
|
+
assertIdentifier(queue.bindingName, `queue binding "${queue.bindingName}"`);
|
|
762
|
+
return ` /** Queue producer binding for the \`${queue.exportName}\` queue. */
|
|
763
|
+
readonly ${queue.bindingName}?: unknown;`;
|
|
758
764
|
})
|
|
759
765
|
].join("\n");
|
|
760
766
|
const envBlock = `
|
|
@@ -777,7 +783,7 @@ ${envBindingFields}` : ""}
|
|
|
777
783
|
/** Alias for {@link CloudflareBindings} — the typed shape of \`env\`. */
|
|
778
784
|
export type Env = CloudflareBindings;`;
|
|
779
785
|
const kvContextField = hasKv ? `
|
|
780
|
-
readonly kv: import("@lunora/kv").Kv;` : "";
|
|
786
|
+
readonly kv: import("@lunora/bindings/kv").Kv;` : "";
|
|
781
787
|
const hyperdriveActionField = hasHyperdrive ? `
|
|
782
788
|
/**
|
|
783
789
|
* External database access via Hyperdrive. Non-deterministic — available only in actions. Writes here are NOT tracked by Lunora live queries; subscriptions will not re-run on external DB changes.
|
|
@@ -788,18 +794,18 @@ export type Env = CloudflareBindings;`;
|
|
|
788
794
|
readonly browser: import("@lunora/browser").Browser;` : "";
|
|
789
795
|
const imagesActionField = hasImages ? `
|
|
790
796
|
/** Cloudflare Images transforms (resize/format/optimize). Non-deterministic — available only in actions. */
|
|
791
|
-
readonly images: import("@lunora/images").Images;` : "";
|
|
797
|
+
readonly images: import("@lunora/bindings/images").Images;` : "";
|
|
792
798
|
const analyticsContextField = hasAnalytics ? `
|
|
793
799
|
/** Analytics Engine telemetry sink. Fire-and-forget and sampled; do not read it back in-handler. */
|
|
794
|
-
readonly analytics: import("@lunora/analytics").AnalyticsClient;` : "";
|
|
800
|
+
readonly analytics: import("@lunora/bindings/analytics").AnalyticsClient;` : "";
|
|
795
801
|
const pipelinesActionField = hasPipelines ? `
|
|
796
802
|
/** Pipelines ingestion sink (durable, R2-backed). Fire-and-forget and batched; do not read it back in-handler. */
|
|
797
|
-
readonly pipelines: import("@lunora/pipelines").PipelineClient;` : "";
|
|
803
|
+
readonly pipelines: import("@lunora/bindings/pipelines").PipelineClient;` : "";
|
|
798
804
|
const r2sqlActionField = hasR2sql ? `
|
|
799
805
|
/**
|
|
800
806
|
* R2 SQL over Apache Iceberg tables (window functions, DISTINCT, set operations). Non-deterministic — available only in actions. Reads here are NOT tracked by Lunora live queries.
|
|
801
807
|
*/
|
|
802
|
-
readonly r2sql: import("@lunora/r2sql").R2SqlClient;` : "";
|
|
808
|
+
readonly r2sql: import("@lunora/bindings/r2sql").R2SqlClient;` : "";
|
|
803
809
|
const hasWorkflows = workflows.length > 0;
|
|
804
810
|
const workflowsTypeImport = hasWorkflows ? `import type { WorkflowHandle } from "@lunora/workflow";
|
|
805
811
|
import type * as lunoraWorkflowDefinitions from "../workflows.js";
|
|
@@ -820,6 +826,21 @@ ${workflows.map((workflow) => ` get(name: ${JSON.stringify(workflow.exportNam
|
|
|
820
826
|
const workflowsOmit = hasWorkflows ? ` | "workflows"` : "";
|
|
821
827
|
const workflowsContextField = hasWorkflows ? `
|
|
822
828
|
readonly workflows: LunoraWorkflows;` : "";
|
|
829
|
+
const hasQueues = queues.length > 0;
|
|
830
|
+
const queuesTypeImport = hasQueues ? `import type { QueueProducer } from "@lunora/queue";
|
|
831
|
+
import type * as lunoraQueueDefinitions from "../queues.js";
|
|
832
|
+
` : "";
|
|
833
|
+
const queuesTypeBlock = hasQueues ? `
|
|
834
|
+
|
|
835
|
+
/** Message body type carried by a \`defineQueue\` definition (its phantom \`__lunoraBody\`). */
|
|
836
|
+
type QueueBodyOf<Definition> = Definition extends { __lunoraBody?: infer Body } ? (unknown extends Body ? unknown : NonNullable<Body>) : unknown;
|
|
837
|
+
|
|
838
|
+
/** This project's declared queues, addressable from \`ctx.queues\` by their \`lunora/queues.ts\` export name. */
|
|
839
|
+
export interface LunoraQueues {
|
|
840
|
+
${queues.map((queue) => ` readonly ${queue.exportName}: QueueProducer<QueueBodyOf<typeof lunoraQueueDefinitions.${queue.exportName}>>;`).join("\n")}
|
|
841
|
+
}` : "";
|
|
842
|
+
const queuesContextField = hasQueues ? `
|
|
843
|
+
readonly queues: LunoraQueues;` : "";
|
|
823
844
|
const server = `${GENERATED_HEADER}import { createPolicyDsl, initLunora, v as vBase } from "${base.server}";
|
|
824
845
|
import type {
|
|
825
846
|
ActionBuilder,
|
|
@@ -841,11 +862,11 @@ import type {
|
|
|
841
862
|
} from "${base.server}";
|
|
842
863
|
|
|
843
864
|
import type { DataModel, DatabaseReaderFacade, DatabaseWriterFacade, Doc, Id as IdOfTable, OrmReader, OrmWriter, Relations, TableName } from "./dataModel.js";
|
|
844
|
-
${aiTypeImport}${paymentsTypeImport}${containersTypeImport}${workflowsTypeImport}
|
|
865
|
+
${aiTypeImport}${paymentsTypeImport}${containersTypeImport}${workflowsTypeImport}${queuesTypeImport}
|
|
845
866
|
export type { DataModel, Doc, Id, TableName } from "./dataModel.js";
|
|
846
867
|
|
|
847
868
|
/** Storage buckets this schema declares (\`v.storage("name")\`), narrowing \`ctx.storage.bucket(name)\`. */
|
|
848
|
-
export type StorageBucketName = ${storageBucketUnion};${envBlock}${workflowsTypeBlock}
|
|
869
|
+
export type StorageBucketName = ${storageBucketUnion};${envBlock}${workflowsTypeBlock}${queuesTypeBlock}
|
|
849
870
|
|
|
850
871
|
/**
|
|
851
872
|
* Project-typed contexts. The base contexts from \`@lunora/server\` are
|
|
@@ -883,13 +904,13 @@ export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"> {
|
|
|
883
904
|
export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${workflowsOmit}> {
|
|
884
905
|
readonly db: Omit<DatabaseWriter, "query" | "get"> & DatabaseWriterFacade & { query: TypedTableQuery; get: TypedTableGet };
|
|
885
906
|
readonly orm: OrmWriter;
|
|
886
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${kvContextField}${analyticsContextField}${workflowsContextField}
|
|
907
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${kvContextField}${analyticsContextField}${workflowsContextField}${queuesContextField}
|
|
887
908
|
}
|
|
888
909
|
|
|
889
910
|
export interface ActionCtx extends Omit<ActionCtxBase, "db" | "storage"${workflowsOmit}> {
|
|
890
911
|
readonly db: Omit<DatabaseWriter, "query" | "get"> & DatabaseWriterFacade & { query: TypedTableQuery; get: TypedTableGet };
|
|
891
912
|
readonly orm: OrmWriter;
|
|
892
|
-
readonly storage: StorageBase<StorageBucketName>;${aiActionField}${paymentsActionField}${containersActionField}${kvContextField}${hyperdriveActionField}${browserActionField}${imagesActionField}${analyticsContextField}${pipelinesActionField}${r2sqlActionField}${workflowsContextField}
|
|
913
|
+
readonly storage: StorageBase<StorageBucketName>;${aiActionField}${paymentsActionField}${containersActionField}${kvContextField}${hyperdriveActionField}${browserActionField}${imagesActionField}${analyticsContextField}${pipelinesActionField}${r2sqlActionField}${workflowsContextField}${queuesContextField}
|
|
893
914
|
}
|
|
894
915
|
|
|
895
916
|
/**
|
|
@@ -1235,7 +1256,7 @@ const emitKvFragments = (hasKv) => {
|
|
|
1235
1256
|
kv?: (env: Record<string, unknown>) => KVNamespaceLike;`,
|
|
1236
1257
|
contextField: `
|
|
1237
1258
|
kv,`,
|
|
1238
|
-
importLines: [`import type { Kv, KVNamespaceLike } from "@lunora/kv";`, `import { createKv } from "@lunora/kv";`],
|
|
1259
|
+
importLines: [`import type { Kv, KVNamespaceLike } from "@lunora/bindings/kv";`, `import { createKv } from "@lunora/bindings/kv";`],
|
|
1239
1260
|
stub: `
|
|
1240
1261
|
const kvStub: Kv = {
|
|
1241
1262
|
delete: async () => {
|
|
@@ -1275,8 +1296,8 @@ const emitAnalyticsFragments = (hasAnalytics) => {
|
|
|
1275
1296
|
contextField: `
|
|
1276
1297
|
analytics,`,
|
|
1277
1298
|
importLines: [
|
|
1278
|
-
`import type { AnalyticsClient, AnalyticsEngineDatasetLike } from "@lunora/analytics";`,
|
|
1279
|
-
`import { createAnalytics } from "@lunora/analytics";`
|
|
1299
|
+
`import type { AnalyticsClient, AnalyticsEngineDatasetLike } from "@lunora/bindings/analytics";`,
|
|
1300
|
+
`import { createAnalytics } from "@lunora/bindings/analytics";`
|
|
1280
1301
|
],
|
|
1281
1302
|
stub: `
|
|
1282
1303
|
const analyticsStub: AnalyticsClient = {
|
|
@@ -1305,7 +1326,7 @@ const emitImagesFragments = (hasImages) => {
|
|
|
1305
1326
|
// ActionCtx-only: woven onto the action ctx object, never query/mutation.
|
|
1306
1327
|
contextField: `
|
|
1307
1328
|
images,`,
|
|
1308
|
-
importLines: [`import type { Images, ImagesBindingLike } from "@lunora/images";`, `import { createImages } from "@lunora/images";`],
|
|
1329
|
+
importLines: [`import type { Images, ImagesBindingLike } from "@lunora/bindings/images";`, `import { createImages } from "@lunora/bindings/images";`],
|
|
1309
1330
|
stub: `
|
|
1310
1331
|
const imagesStub: Images = {
|
|
1311
1332
|
info: async () => {
|
|
@@ -1404,10 +1425,10 @@ const emitR2sqlFragments = (hasR2sql) => {
|
|
|
1404
1425
|
// ActionCtx-only: attached via the \`ctx.r2sql = r2sql\` assignment in the
|
|
1405
1426
|
// \`isAction\` block, never the every-ctx object literal.
|
|
1406
1427
|
contextField: "",
|
|
1407
|
-
importLines: [`import type { R2SqlClient } from "@lunora/r2sql";`, `import { createR2Sql } from "@lunora/r2sql";`],
|
|
1428
|
+
importLines: [`import type { R2SqlClient } from "@lunora/bindings/r2sql";`, `import { createR2Sql } from "@lunora/bindings/r2sql";`],
|
|
1408
1429
|
// The stub is typed `R2SqlClient`, so TS flags a missing method at build
|
|
1409
1430
|
// time — but it must stay structurally in sync with that interface
|
|
1410
|
-
// (`@lunora/r2sql` client.ts) when a method is added there.
|
|
1431
|
+
// (`@lunora/bindings/r2sql` client.ts) when a method is added there.
|
|
1411
1432
|
stub: `
|
|
1412
1433
|
const r2sqlStub: R2SqlClient = {
|
|
1413
1434
|
describe: async () => {
|
|
@@ -1432,6 +1453,34 @@ const r2sqlStub: R2SqlClient = {
|
|
|
1432
1453
|
`
|
|
1433
1454
|
};
|
|
1434
1455
|
};
|
|
1456
|
+
const emitPipelinesFragments = (hasPipelines) => {
|
|
1457
|
+
if (!hasPipelines) {
|
|
1458
|
+
return EMPTY_HELPER_FRAGMENTS;
|
|
1459
|
+
}
|
|
1460
|
+
const pipelinesMissing = `throw new Error("ctx.pipelines: no Pipelines binding found. Add a \\\`pipelines\\\` binding (env.PIPELINES) to wrangler.jsonc, or pass \\\`pipelines\\\` to createShardDO().");`;
|
|
1461
|
+
return {
|
|
1462
|
+
build: `
|
|
1463
|
+
const pipelinesBinding = config.pipelines?.(env) ?? (env as Record<string, unknown>).PIPELINES;
|
|
1464
|
+
const pipelines: PipelineClient = pipelinesBinding ? createPipelines({ binding: pipelinesBinding as PipelineBindingLike }) : pipelinesStub;
|
|
1465
|
+
`,
|
|
1466
|
+
configField: `
|
|
1467
|
+
pipelines?: (env: Record<string, unknown>) => PipelineBindingLike;`,
|
|
1468
|
+
// ActionCtx-only: attached via the \`ctx.pipelines = pipelines\` assignment
|
|
1469
|
+
// in the \`isAction\` block, never the every-ctx object literal.
|
|
1470
|
+
contextField: "",
|
|
1471
|
+
importLines: [
|
|
1472
|
+
`import type { PipelineBindingLike, PipelineClient } from "@lunora/bindings/pipelines";`,
|
|
1473
|
+
`import { createPipelines } from "@lunora/bindings/pipelines";`
|
|
1474
|
+
],
|
|
1475
|
+
stub: `
|
|
1476
|
+
const pipelinesStub: PipelineClient = {
|
|
1477
|
+
send: async () => {
|
|
1478
|
+
${pipelinesMissing}
|
|
1479
|
+
},
|
|
1480
|
+
};
|
|
1481
|
+
`
|
|
1482
|
+
};
|
|
1483
|
+
};
|
|
1435
1484
|
const emitContainers = (containers, jurisdiction) => {
|
|
1436
1485
|
if (containers.length === 0) {
|
|
1437
1486
|
return "";
|
|
@@ -1455,11 +1504,18 @@ export class ${container.className} extends LunoraContainer {
|
|
|
1455
1504
|
* requires each \`containers[].class_name\` to be exported by the worker:
|
|
1456
1505
|
*
|
|
1457
1506
|
* \`export * from "./lunora/_generated/containers.js";\`
|
|
1507
|
+
*
|
|
1508
|
+
* \`ContainerProxy\` is re-exported alongside them: the egress-interception path
|
|
1509
|
+
* (\`allowedHosts\`/\`deniedHosts\`/\`interceptHttps\` and the runtime
|
|
1510
|
+
* \`handle.egress\` controls) routes container outbound traffic through this
|
|
1511
|
+
* WorkerEntrypoint, so it too must be exported by the deployed worker.
|
|
1458
1512
|
*/
|
|
1459
|
-
import LunoraContainer from "@lunora/container/do";
|
|
1513
|
+
import { LunoraContainer } from "@lunora/container/do";
|
|
1460
1514
|
|
|
1461
1515
|
import { ${imports} } from "../containers.js";
|
|
1462
1516
|
|
|
1517
|
+
export { ContainerProxy } from "@lunora/container/do";
|
|
1518
|
+
|
|
1463
1519
|
${classes}`;
|
|
1464
1520
|
};
|
|
1465
1521
|
const emitContainerFragments = (containers, jurisdiction) => {
|
|
@@ -1532,6 +1588,32 @@ type WorkflowOutputOf<Definition> = Definition extends { __output?: infer Output
|
|
|
1532
1588
|
|
|
1533
1589
|
${classes}`;
|
|
1534
1590
|
};
|
|
1591
|
+
const emitQueues = (queues) => {
|
|
1592
|
+
const pushQueues = queues.filter((queue) => queue.mode === "push");
|
|
1593
|
+
if (pushQueues.length === 0) {
|
|
1594
|
+
return "";
|
|
1595
|
+
}
|
|
1596
|
+
for (const queue of pushQueues) {
|
|
1597
|
+
assertIdentifier(queue.exportName, `queue export "${queue.exportName}"`);
|
|
1598
|
+
}
|
|
1599
|
+
const imports = pushQueues.map((queue) => queue.exportName).join(", ");
|
|
1600
|
+
const entries = pushQueues.map((queue) => ` ${JSON.stringify(queue.name)}: { definition: ${queue.exportName}, exportName: ${JSON.stringify(queue.exportName)} },`).join("\n");
|
|
1601
|
+
return `${GENERATED_HEADER}/**
|
|
1602
|
+
* Push-consumer registry for the queues declared in \`lunora/queues.ts\`. The
|
|
1603
|
+
* composed worker's \`queue(batch, env, ctx)\` entry routes each delivered batch
|
|
1604
|
+
* by \`batch.queue\` to the matching \`defineQueue\` handler. Wired automatically
|
|
1605
|
+
* by \`defineApp\` — you don't import this directly.
|
|
1606
|
+
*/
|
|
1607
|
+
import type { QueueRegistry } from "@lunora/queue";
|
|
1608
|
+
|
|
1609
|
+
import { ${imports} } from "../queues.js";
|
|
1610
|
+
|
|
1611
|
+
/** Stable wrangler queue name → { definition, exportName } for batch routing. */
|
|
1612
|
+
export const LUNORA_QUEUE_REGISTRY: QueueRegistry = {
|
|
1613
|
+
${entries}
|
|
1614
|
+
};
|
|
1615
|
+
`;
|
|
1616
|
+
};
|
|
1535
1617
|
const emitWorkflowFragments = (workflows) => {
|
|
1536
1618
|
if (workflows.length === 0) {
|
|
1537
1619
|
return { build: "", contextField: "", importLines: [], specs: "" };
|
|
@@ -1557,6 +1639,31 @@ ${specEntries}
|
|
|
1557
1639
|
`
|
|
1558
1640
|
};
|
|
1559
1641
|
};
|
|
1642
|
+
const emitQueueFragments = (queues) => {
|
|
1643
|
+
if (queues.length === 0) {
|
|
1644
|
+
return { build: "", contextField: "", importLines: [], specs: "" };
|
|
1645
|
+
}
|
|
1646
|
+
for (const queue of queues) {
|
|
1647
|
+
assertIdentifier(queue.exportName, `queue export "${queue.exportName}"`);
|
|
1648
|
+
assertIdentifier(queue.bindingName, `queue binding "${queue.bindingName}"`);
|
|
1649
|
+
}
|
|
1650
|
+
const specEntries = queues.map((queue) => ` { binding: "${queue.bindingName}", exportName: "${queue.exportName}", name: ${JSON.stringify(queue.name)} },`).join("\n");
|
|
1651
|
+
return {
|
|
1652
|
+
build: `
|
|
1653
|
+
const queues = createQueueContext(env, LUNORA_QUEUES);
|
|
1654
|
+
`,
|
|
1655
|
+
contextField: `
|
|
1656
|
+
queues,`,
|
|
1657
|
+
importLines: [`import type { QueueBindingSpec } from "@lunora/queue";`, `import { createQueueContext } from "@lunora/queue";`],
|
|
1658
|
+
// eslint-disable-next-line no-secrets/no-secrets -- the emitted readonly-array type annotation is dense generated TS, not a credential
|
|
1659
|
+
specs: `
|
|
1660
|
+
/** Wiring specs for \`ctx.queues\` (codegen-derived from \`lunora/queues.ts\`). */
|
|
1661
|
+
const LUNORA_QUEUES: ReadonlyArray<QueueBindingSpec> = [
|
|
1662
|
+
${specEntries}
|
|
1663
|
+
];
|
|
1664
|
+
`
|
|
1665
|
+
};
|
|
1666
|
+
};
|
|
1560
1667
|
const emitWorkflowsMetadataFragments = (workflows) => {
|
|
1561
1668
|
if (workflows.length === 0) {
|
|
1562
1669
|
return { constant: "", override: "" };
|
|
@@ -1583,6 +1690,33 @@ const LUNORA_WORKFLOWS_INFO: WorkflowsResult = ${JSON.stringify(metadata, void 0
|
|
|
1583
1690
|
`
|
|
1584
1691
|
};
|
|
1585
1692
|
};
|
|
1693
|
+
const emitQueuesMetadataFragments = (queues) => {
|
|
1694
|
+
if (queues.length === 0) {
|
|
1695
|
+
return { constant: "", override: "" };
|
|
1696
|
+
}
|
|
1697
|
+
const metadata = {
|
|
1698
|
+
queues: queues.map((queue) => {
|
|
1699
|
+
return {
|
|
1700
|
+
binding: queue.bindingName,
|
|
1701
|
+
...queue.tuning.deadLetterQueue === void 0 ? {} : { deadLetterQueue: queue.tuning.deadLetterQueue },
|
|
1702
|
+
exportName: queue.exportName,
|
|
1703
|
+
mode: queue.mode,
|
|
1704
|
+
name: queue.name
|
|
1705
|
+
};
|
|
1706
|
+
})
|
|
1707
|
+
};
|
|
1708
|
+
return {
|
|
1709
|
+
constant: `
|
|
1710
|
+
/** Read-only declared-queue metadata (discovered from \`lunora/queues.ts\`) served via \`__lunora_admin__:listQueues\` for the studio's queues view. */
|
|
1711
|
+
const LUNORA_QUEUES_INFO: QueuesResult = ${JSON.stringify(metadata, void 0, 4)};
|
|
1712
|
+
`,
|
|
1713
|
+
override: `
|
|
1714
|
+
protected override queuesMetadata(): QueuesResult {
|
|
1715
|
+
return LUNORA_QUEUES_INFO;
|
|
1716
|
+
}
|
|
1717
|
+
`
|
|
1718
|
+
};
|
|
1719
|
+
};
|
|
1586
1720
|
const emitPaymentFragments = (hasPayments) => {
|
|
1587
1721
|
if (!hasPayments) {
|
|
1588
1722
|
return { build: "", configField: "", contextField: "", imports: [], stub: "" };
|
|
@@ -1638,13 +1772,14 @@ const paymentStub: LunoraPayment = {
|
|
|
1638
1772
|
`
|
|
1639
1773
|
};
|
|
1640
1774
|
};
|
|
1641
|
-
const buildDoTypeImports = (hasVectors, hasWorkflows) => [
|
|
1775
|
+
const buildDoTypeImports = (hasVectors, hasWorkflows, hasQueues) => [
|
|
1642
1776
|
"AdvisoryFinding",
|
|
1643
1777
|
"DatabaseWriterLike",
|
|
1644
1778
|
"DataMigrationLike",
|
|
1645
1779
|
"LogSink",
|
|
1646
1780
|
"MaskPoliciesResult",
|
|
1647
1781
|
"MigrationRunResult",
|
|
1782
|
+
...hasQueues ? ["QueuesResult"] : [],
|
|
1648
1783
|
"RunShardApplyCdcArgs",
|
|
1649
1784
|
"RunShardMigrationArgs",
|
|
1650
1785
|
"RlsPoliciesResult",
|
|
@@ -1673,8 +1808,10 @@ const emitShard = ({
|
|
|
1673
1808
|
hasImages = false,
|
|
1674
1809
|
hasKv = false,
|
|
1675
1810
|
hasPayments = false,
|
|
1811
|
+
hasPipelines = false,
|
|
1676
1812
|
hasR2sql = false,
|
|
1677
1813
|
maskMetadata,
|
|
1814
|
+
queues = [],
|
|
1678
1815
|
rlsMetadata,
|
|
1679
1816
|
schema,
|
|
1680
1817
|
storageRules,
|
|
@@ -1690,6 +1827,8 @@ const emitShard = ({
|
|
|
1690
1827
|
const hyperdriveFragments = emitHyperdriveFragments(hasHyperdrive);
|
|
1691
1828
|
const browserFragments = emitBrowserFragments(hasBrowser);
|
|
1692
1829
|
const r2sqlFragments = emitR2sqlFragments(hasR2sql);
|
|
1830
|
+
const pipelinesFragments = emitPipelinesFragments(hasPipelines);
|
|
1831
|
+
const { build: queuesBuild, contextField: queuesContextField, importLines: queueImportLines, specs: queueSpecs } = emitQueueFragments(queues);
|
|
1693
1832
|
const {
|
|
1694
1833
|
build: containersBuild,
|
|
1695
1834
|
contextField: containersContextField,
|
|
@@ -1716,12 +1855,14 @@ const emitShard = ({
|
|
|
1716
1855
|
const studioFeaturesData = studioFeatures ?? {
|
|
1717
1856
|
mail: false,
|
|
1718
1857
|
payments: false,
|
|
1858
|
+
queues: false,
|
|
1719
1859
|
scheduler: false,
|
|
1720
1860
|
storage: false,
|
|
1721
1861
|
vectors: false,
|
|
1722
1862
|
workflows: false
|
|
1723
1863
|
};
|
|
1724
1864
|
const { constant: workflowsMetadataConst, override: workflowsMetadataOverride } = emitWorkflowsMetadataFragments(workflows);
|
|
1865
|
+
const { constant: queuesMetadataConst, override: queuesMetadataOverride } = emitQueuesMetadataFragments(queues);
|
|
1725
1866
|
const hasVectors = schema.vectorIndexes.length > 0;
|
|
1726
1867
|
const hasGlobalTables = schema.tables.some((table) => table.shardMode === "global");
|
|
1727
1868
|
const hasHyperdriveGlobal = schema.tables.some((table) => table.shardMode === "global" && table.globalBackend === "hyperdrive");
|
|
@@ -1736,23 +1877,24 @@ const emitShard = ({
|
|
|
1736
1877
|
const tableIndexes = buildTableIndexes(schema);
|
|
1737
1878
|
const tableColumns = buildTableColumns(schema);
|
|
1738
1879
|
const storageColumns = buildStorageColumns(schema);
|
|
1739
|
-
const doTypeImports = buildDoTypeImports(hasVectors, workflows.length > 0);
|
|
1880
|
+
const doTypeImports = buildDoTypeImports(hasVectors, workflows.length > 0, queues.length > 0);
|
|
1740
1881
|
const relationFanout = emitRelationFanout(hasGlobalTables);
|
|
1741
1882
|
const importLines = [
|
|
1742
1883
|
`import type { ${doTypeImports.join(", ")} } from "${base.do}";`,
|
|
1743
1884
|
`import { applyCdcChanges, createShardCtxDb, runDataMigration, runShardMigrations, ${relationFanout.importFragment}ShardDO as ShardDOBase } from "${base.do}";`,
|
|
1744
|
-
// `asBucketStorage` (the bucket-aware `ctx.storage` wrapper)
|
|
1885
|
+
// `asBucketStorage` (the bucket-aware `ctx.storage` wrapper) and
|
|
1886
|
+
// `createSecrets` (the `ctx.secrets` core built-in) live in
|
|
1745
1887
|
// `@lunora/server`, the single source — imported here rather than stamped
|
|
1746
1888
|
// inline into every generated shard.
|
|
1747
|
-
`import { asBucketStorage } from "${base.server}";`
|
|
1889
|
+
`import { asBucketStorage, createSecrets } from "${base.server}";`
|
|
1748
1890
|
];
|
|
1749
1891
|
if (hasTables) {
|
|
1750
1892
|
importLines.push(`import { bindOrm, bindTableFacade } from "${base.server}";`);
|
|
1751
1893
|
}
|
|
1752
1894
|
if (hasVectors) {
|
|
1753
1895
|
importLines.push(
|
|
1754
|
-
`import type { SchemaLike as VectorSchemaLike, VectorizeIndexLike, VectorSearchLike } from "@lunora/vectors";`,
|
|
1755
|
-
`import { createContextVectors, createVectors, createVectorSyncHook } from "@lunora/vectors";`
|
|
1896
|
+
`import type { SchemaLike as VectorSchemaLike, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";`,
|
|
1897
|
+
`import { createContextVectors, createVectors, createVectorSyncHook } from "@lunora/bindings/vectors";`
|
|
1756
1898
|
);
|
|
1757
1899
|
}
|
|
1758
1900
|
if (hasAi) {
|
|
@@ -1765,8 +1907,10 @@ const emitShard = ({
|
|
|
1765
1907
|
...hyperdriveFragments.importLines,
|
|
1766
1908
|
...browserFragments.importLines,
|
|
1767
1909
|
...r2sqlFragments.importLines,
|
|
1910
|
+
...pipelinesFragments.importLines,
|
|
1768
1911
|
...containerImportLines,
|
|
1769
1912
|
...workflowImportLines,
|
|
1913
|
+
...queueImportLines,
|
|
1770
1914
|
...paymentsImports,
|
|
1771
1915
|
``,
|
|
1772
1916
|
`import schema from "../schema.js";`,
|
|
@@ -1908,18 +2052,23 @@ ${schema.tables.map(
|
|
|
1908
2052
|
(table) => ` facade[${JSON.stringify(table.name)}] = bindTableFacade(db, ${JSON.stringify(table.name)});`
|
|
1909
2053
|
).join("\n")}
|
|
1910
2054
|
` : "";
|
|
1911
|
-
const
|
|
1912
|
-
|
|
1913
|
-
|
|
2055
|
+
const secretsBuild = `
|
|
2056
|
+
const secrets = createSecrets(env);
|
|
2057
|
+
`;
|
|
2058
|
+
const everyContextBuild = `${kvFragments.build}${analyticsFragments.build}${secretsBuild}`;
|
|
2059
|
+
const everyContextField = `${kvFragments.contextField}${analyticsFragments.contextField}
|
|
2060
|
+
secrets,`;
|
|
2061
|
+
const actionOnlyHasAny = hasImages || hasHyperdrive || hasBrowser || hasR2sql || hasPipelines;
|
|
1914
2062
|
const actionOnlyBlock = actionOnlyHasAny ? `
|
|
1915
2063
|
// ActionCtx-only helpers (external, non-deterministic I/O): constructed
|
|
1916
2064
|
// and attached only for an \`action\` so query/mutation ctx never carry them.
|
|
1917
2065
|
if (isAction) {
|
|
1918
|
-
${imagesFragments.build}${hyperdriveFragments.build}${browserFragments.build}${r2sqlFragments.build}${[
|
|
2066
|
+
${imagesFragments.build}${hyperdriveFragments.build}${browserFragments.build}${r2sqlFragments.build}${pipelinesFragments.build}${[
|
|
1919
2067
|
...hasImages ? [" ctx.images = images;"] : [],
|
|
1920
2068
|
...hasHyperdrive ? [" ctx.sql = sql;"] : [],
|
|
1921
2069
|
...hasBrowser ? [" ctx.browser = browser;"] : [],
|
|
1922
|
-
...hasR2sql ? [" ctx.r2sql = r2sql;"] : []
|
|
2070
|
+
...hasR2sql ? [" ctx.r2sql = r2sql;"] : [],
|
|
2071
|
+
...hasPipelines ? [" ctx.pipelines = pipelines;"] : []
|
|
1923
2072
|
].join("\n")}
|
|
1924
2073
|
}
|
|
1925
2074
|
` : "";
|
|
@@ -1959,14 +2108,14 @@ const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(storageRulesDa
|
|
|
1959
2108
|
|
|
1960
2109
|
/** Which optional package-backed features this app wires up (discovered from imports / \`ctx.*\` reads / schema signals) served via \`__lunora_admin__:studioFeatures\` so the studio hides nav pages whose package isn't enabled. */
|
|
1961
2110
|
const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(studioFeaturesData, void 0, 4)};
|
|
1962
|
-
${workflowsMetadataConst}${containerSpecs}${workflowSpecs}
|
|
2111
|
+
${workflowsMetadataConst}${queuesMetadataConst}${containerSpecs}${workflowSpecs}${queueSpecs}
|
|
1963
2112
|
export interface ShardDOConfig {
|
|
1964
2113
|
/** Opt into change-data-capture: records a post-image to \`__cdc_log\` on every write (backs streaming export + replay-PITR). */
|
|
1965
2114
|
cdc?: boolean;
|
|
1966
2115
|
/** Optional telemetry sink. When supplied, each \`ctx.log.*\` call is forwarded to \`sink.onLog\`. Pass the SAME sink you give \`createWorker({ observability })\` (which drives \`onRpc\`) to route both RPC and log events. */
|
|
1967
2116
|
observability?: (env: Record<string, unknown>) => LogSink | undefined;
|
|
1968
2117
|
scheduler?: (env: Record<string, unknown>) => unknown;
|
|
1969
|
-
storage?: (env: Record<string, unknown>) => unknown;${vectorsConfigField}${aiConfigField}${kvFragments.configField}${analyticsFragments.configField}${imagesFragments.configField}${hyperdriveFragments.configField}${browserFragments.configField}${r2sqlFragments.configField}${paymentsConfigField}${d1ConfigField}${hyperdriveGlobalConfigField}
|
|
2118
|
+
storage?: (env: Record<string, unknown>) => unknown;${vectorsConfigField}${aiConfigField}${kvFragments.configField}${analyticsFragments.configField}${imagesFragments.configField}${hyperdriveFragments.configField}${browserFragments.configField}${r2sqlFragments.configField}${pipelinesFragments.configField}${paymentsConfigField}${d1ConfigField}${hyperdriveGlobalConfigField}
|
|
1970
2119
|
}
|
|
1971
2120
|
|
|
1972
2121
|
const schedulerStub = {
|
|
@@ -2004,7 +2153,7 @@ const storageStub = {
|
|
|
2004
2153
|
throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
|
|
2005
2154
|
},
|
|
2006
2155
|
};
|
|
2007
|
-
${globalDatabaseStub}${vectorsStub}${aiStub}${kvFragments.stub}${analyticsFragments.stub}${imagesFragments.stub}${hyperdriveFragments.stub}${browserFragments.stub}${r2sqlFragments.stub}${paymentStub}${bindTableHelper}
|
|
2156
|
+
${globalDatabaseStub}${vectorsStub}${aiStub}${kvFragments.stub}${analyticsFragments.stub}${imagesFragments.stub}${hyperdriveFragments.stub}${browserFragments.stub}${r2sqlFragments.stub}${pipelinesFragments.stub}${paymentStub}${bindTableHelper}
|
|
2008
2157
|
// Bound in-process \`ctx.run*\` composition depth so a self- or cyclically-
|
|
2009
2158
|
// referencing call fails loudly with a clear error instead of overflowing the
|
|
2010
2159
|
// stack. Tracked across the awaited handler chain (one DO invocation is
|
|
@@ -2149,7 +2298,7 @@ ${relationFanout.override}
|
|
|
2149
2298
|
protected override studioFeatures(): StudioFeaturesResult {
|
|
2150
2299
|
return LUNORA_STUDIO_FEATURES;
|
|
2151
2300
|
}
|
|
2152
|
-
${workflowsMetadataOverride}
|
|
2301
|
+
${workflowsMetadataOverride}${queuesMetadataOverride}
|
|
2153
2302
|
protected override advisories(): AdvisoryFinding[] {
|
|
2154
2303
|
return LUNORA_ADVISORIES;
|
|
2155
2304
|
}
|
|
@@ -2383,7 +2532,7 @@ ${workflowsMetadataOverride}
|
|
|
2383
2532
|
// dispatch path) fall back to the per-request fields as before.
|
|
2384
2533
|
const userId = options.identity ? options.identity.userId : this.getCurrentUserId();
|
|
2385
2534
|
const identity = options.identity ? options.identity.identity : this.getCurrentIdentity();
|
|
2386
|
-
${vectorsBuild}${aiBuild}${everyContextBuild}${containersBuild}${workflowsBuild}
|
|
2535
|
+
${vectorsBuild}${aiBuild}${everyContextBuild}${containersBuild}${workflowsBuild}${queuesBuild}
|
|
2387
2536
|
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
2388
2537
|
// Build the storage adapter once and share it between \`ctx.storage\`
|
|
2389
2538
|
// and \`ctx.db.system._storage\` so both read the same R2 binding. The
|
|
@@ -2425,7 +2574,7 @@ ${facadeBlock}${paymentsBuild}
|
|
|
2425
2574
|
log,
|
|
2426
2575
|
now,${ormContextField}
|
|
2427
2576
|
scheduler,
|
|
2428
|
-
storage,${vectorsContextField}${aiContextField}${everyContextField}${paymentsContextField}${containersContextField}${workflowsContextField}
|
|
2577
|
+
storage,${vectorsContextField}${aiContextField}${everyContextField}${paymentsContextField}${containersContextField}${workflowsContextField}${queuesContextField}
|
|
2429
2578
|
};
|
|
2430
2579
|
${isActionLine}${actionOnlyBlock}
|
|
2431
2580
|
ctx.runAction = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("action", reference.__lunoraRef, fnArgs, ctx);
|
|
@@ -2689,4 +2838,4 @@ const emitWranglerCronTriggers = (crons) => {
|
|
|
2689
2838
|
return triggers;
|
|
2690
2839
|
};
|
|
2691
2840
|
|
|
2692
|
-
export { GENERATED_HEADER, buildStorageColumns, emitApi, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitSeed, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers };
|
|
2841
|
+
export { GENERATED_HEADER, buildStorageColumns, emitApi, emitContainers, emitCrons, emitDataModel, emitDrizzleSchema, emitFunctions, emitQueues, emitSeed, emitServer, emitShard, emitVectors, emitWorkflows, emitWranglerCronTriggers };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GENERATED_HEADER } from './GENERATED_HEADER-
|
|
1
|
+
import { GENERATED_HEADER } from './GENERATED_HEADER-BEA7oWGC.mjs';
|
|
2
2
|
import { s as sanitizeNamespace } from './paths-BRd6JHuF.mjs';
|
|
3
3
|
import { argsObjectSchema, LUNORA_ERROR_CODES } from './LUNORA_ERROR_CODES-CySpQPD3.mjs';
|
|
4
4
|
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { queueDefaultName, queueBindingName } from '@lunora/queue';
|
|
4
|
+
import { SyntaxKind, Node } from 'ts-morph';
|
|
5
|
+
import { diagnosticAt } from './CodegenDiagnosticError-DeblMkzO.mjs';
|
|
6
|
+
|
|
7
|
+
const QUEUES_FILENAME = "queues.ts";
|
|
8
|
+
const isDefineQueue = (identifier) => {
|
|
9
|
+
const symbol = identifier.getSymbol();
|
|
10
|
+
if (!symbol) {
|
|
11
|
+
return identifier.getText() === "defineQueue";
|
|
12
|
+
}
|
|
13
|
+
for (const declaration of symbol.getDeclarations()) {
|
|
14
|
+
if (!Node.isImportSpecifier(declaration)) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (declaration.getImportDeclaration().getModuleSpecifierValue() !== "@lunora/queue") {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
return declaration.getNameNode().getText() === "defineQueue";
|
|
21
|
+
}
|
|
22
|
+
return false;
|
|
23
|
+
};
|
|
24
|
+
const stringProperty = (expression, exportName, property) => {
|
|
25
|
+
if (Node.isStringLiteral(expression) || Node.isNoSubstitutionTemplateLiteral(expression)) {
|
|
26
|
+
return expression.getLiteralValue();
|
|
27
|
+
}
|
|
28
|
+
throw diagnosticAt(
|
|
29
|
+
expression,
|
|
30
|
+
`queue "${exportName}": \`${property}\` must be a static string literal — it is deploy configuration codegen writes into wrangler.jsonc`
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
const numberProperty = (expression, exportName, property) => {
|
|
34
|
+
if (Node.isNumericLiteral(expression)) {
|
|
35
|
+
return expression.getLiteralValue();
|
|
36
|
+
}
|
|
37
|
+
throw diagnosticAt(
|
|
38
|
+
expression,
|
|
39
|
+
`queue "${exportName}": \`${property}\` must be a static numeric literal — it is deploy configuration codegen writes into wrangler.jsonc`
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
const queueNameOverride = (argument, exportName) => {
|
|
43
|
+
const nameProperty = argument.getProperty("name");
|
|
44
|
+
if (!nameProperty || !Node.isPropertyAssignment(nameProperty)) {
|
|
45
|
+
return void 0;
|
|
46
|
+
}
|
|
47
|
+
const name = stringProperty(nameProperty.getInitializerOrThrow(), exportName, "name");
|
|
48
|
+
if (name.length === 0) {
|
|
49
|
+
throw diagnosticAt(nameProperty, `queue "${exportName}": \`name\` must be a non-empty string when provided`);
|
|
50
|
+
}
|
|
51
|
+
return name;
|
|
52
|
+
};
|
|
53
|
+
const queueFromCall = (call, exportName) => {
|
|
54
|
+
const argument = call.getArguments()[0];
|
|
55
|
+
if (!argument || !Node.isObjectLiteralExpression(argument)) {
|
|
56
|
+
throw diagnosticAt(call, `queue "${exportName}": defineQueue must be passed an inline object literal`);
|
|
57
|
+
}
|
|
58
|
+
const ir = {
|
|
59
|
+
bindingName: queueBindingName(exportName),
|
|
60
|
+
exportName,
|
|
61
|
+
mode: "push",
|
|
62
|
+
name: queueNameOverride(argument, exportName) ?? queueDefaultName(exportName),
|
|
63
|
+
tuning: {}
|
|
64
|
+
};
|
|
65
|
+
const modeProperty = argument.getProperty("mode");
|
|
66
|
+
if (modeProperty && Node.isPropertyAssignment(modeProperty)) {
|
|
67
|
+
const mode = stringProperty(modeProperty.getInitializerOrThrow(), exportName, "mode");
|
|
68
|
+
if (mode !== "push" && mode !== "pull") {
|
|
69
|
+
throw diagnosticAt(modeProperty, `queue "${exportName}": \`mode\` must be "push" or "pull" (got ${JSON.stringify(mode)})`);
|
|
70
|
+
}
|
|
71
|
+
ir.mode = mode;
|
|
72
|
+
}
|
|
73
|
+
const dlqProperty = argument.getProperty("deadLetterQueue");
|
|
74
|
+
if (dlqProperty && Node.isPropertyAssignment(dlqProperty)) {
|
|
75
|
+
ir.tuning.deadLetterQueue = stringProperty(dlqProperty.getInitializerOrThrow(), exportName, "deadLetterQueue");
|
|
76
|
+
}
|
|
77
|
+
for (const property of ["maxBatchSize", "maxBatchTimeout", "maxRetries", "retryDelay"]) {
|
|
78
|
+
const node = argument.getProperty(property);
|
|
79
|
+
if (node && Node.isPropertyAssignment(node)) {
|
|
80
|
+
ir.tuning[property] = numberProperty(node.getInitializerOrThrow(), exportName, property);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return ir;
|
|
84
|
+
};
|
|
85
|
+
const queuesFromSource = (source) => {
|
|
86
|
+
const queues = [];
|
|
87
|
+
for (const declaration of source.getVariableDeclarations()) {
|
|
88
|
+
if (!declaration.isExported()) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const initializer = declaration.getInitializer();
|
|
92
|
+
if (initializer?.getKind() !== SyntaxKind.CallExpression) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const call = initializer;
|
|
96
|
+
const callee = call.getExpression();
|
|
97
|
+
if (!Node.isIdentifier(callee) || !isDefineQueue(callee)) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const nameNode = declaration.getNameNode();
|
|
101
|
+
if (!Node.isIdentifier(nameNode)) {
|
|
102
|
+
throw diagnosticAt(nameNode, "defineQueue exports must be plain named exports (no destructuring)");
|
|
103
|
+
}
|
|
104
|
+
queues.push(queueFromCall(call, nameNode.getText()));
|
|
105
|
+
}
|
|
106
|
+
return queues;
|
|
107
|
+
};
|
|
108
|
+
const discoverQueues = (project, lunoraDirectory) => {
|
|
109
|
+
const queuesPath = join(lunoraDirectory, QUEUES_FILENAME);
|
|
110
|
+
if (!existsSync(queuesPath)) {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
const source = project.getSourceFile(queuesPath) ?? project.addSourceFileAtPath(queuesPath);
|
|
114
|
+
const queues = queuesFromSource(source);
|
|
115
|
+
queues.sort((a, b) => a.exportName.localeCompare(b.exportName));
|
|
116
|
+
return queues;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export { QUEUES_FILENAME, discoverQueues };
|
|
@@ -13,16 +13,17 @@ import discoverMaskProcedures, { discoverMaskMetadata } from './discoverMaskProc
|
|
|
13
13
|
import discoverMigrations from './discoverMigrations-Bi5nJ0mJ.mjs';
|
|
14
14
|
import discoverNondeterministicCalls from './discoverNondeterministicCalls-C4M8AXmQ.mjs';
|
|
15
15
|
import discoverQueries from './discoverQueries-B0wGT-xe.mjs';
|
|
16
|
+
import { discoverQueues } from './QUEUES_FILENAME-B5_eWCRe.mjs';
|
|
16
17
|
import discoverR2sqlCalls from './discoverR2sqlCalls-BVNMd428.mjs';
|
|
17
18
|
import discoverRlsProcedures, { discoverRlsMetadata } from './discoverRlsMetadata-BS9GOGC5.mjs';
|
|
18
19
|
import discoverSchema from './discoverSchema-BnWHHJ4T.mjs';
|
|
19
20
|
import discoverStorageRulesMetadata from './discoverStorageRulesMetadata-Da8BKXcI.mjs';
|
|
20
21
|
import { e as enclosingExportName$1 } from './discover-ast-CT6BgBr4.mjs';
|
|
21
22
|
import { discoverWorkflows } from './WORKFLOWS_FILENAME-D62dcBGg.mjs';
|
|
22
|
-
import { buildStorageColumns, emitDataModel, emitApi, emitServer, emitFunctions, emitShard, emitContainers, emitWorkflows, emitCrons, emitVectors, emitDrizzleSchema, emitSeed, emitWranglerCronTriggers } from './GENERATED_HEADER-
|
|
23
|
-
import { emitApp } from './emitApp-
|
|
24
|
-
import { buildOpenApiDocument, emitOpenApiModule } from './buildOpenApiDocument-
|
|
25
|
-
import { buildOpenRpcDocument, emitOpenRpcModule } from './OPENRPC_VERSION-
|
|
23
|
+
import { buildStorageColumns, emitDataModel, emitApi, emitServer, emitFunctions, emitShard, emitContainers, emitWorkflows, emitQueues, emitCrons, emitVectors, emitDrizzleSchema, emitSeed, emitWranglerCronTriggers } from './GENERATED_HEADER-BEA7oWGC.mjs';
|
|
24
|
+
import { emitApp } from './emitApp-DiK0QSBn.mjs';
|
|
25
|
+
import { buildOpenApiDocument, emitOpenApiModule } from './buildOpenApiDocument-699G4RP4.mjs';
|
|
26
|
+
import { buildOpenRpcDocument, emitOpenRpcModule } from './OPENRPC_VERSION-CQ3f8YQ-.mjs';
|
|
26
27
|
import { buildSchemaSnapshot, serializeSchemaSnapshot } from './SCHEMA_SNAPSHOT_VERSION-wWGP2_5E.mjs';
|
|
27
28
|
|
|
28
29
|
const HTTP_VERBS = /* @__PURE__ */ new Set(["delete", "get", "head", "options", "patch", "post", "put"]);
|
|
@@ -240,18 +241,21 @@ const discoverArgumentValidators = (project, lunoraDirectory) => {
|
|
|
240
241
|
|
|
241
242
|
const PROBES = {
|
|
242
243
|
ai: { contextProperty: "ai", moduleSpecifier: "@lunora/ai" },
|
|
243
|
-
analytics: { contextProperty: "analytics", moduleSpecifier: "@lunora/analytics" },
|
|
244
|
+
analytics: { contextProperty: "analytics", moduleSpecifier: "@lunora/bindings/analytics" },
|
|
244
245
|
browser: { contextProperty: "browser", moduleSpecifier: "@lunora/browser" },
|
|
245
246
|
hyperdrive: { contextProperty: "sql", moduleSpecifier: "@lunora/hyperdrive" },
|
|
246
|
-
images: { contextProperty: "images", moduleSpecifier: "@lunora/images" },
|
|
247
|
-
kv: { contextProperty: "kv", moduleSpecifier: "@lunora/kv" },
|
|
247
|
+
images: { contextProperty: "images", moduleSpecifier: "@lunora/bindings/images" },
|
|
248
|
+
kv: { contextProperty: "kv", moduleSpecifier: "@lunora/bindings/kv" },
|
|
248
249
|
mail: { moduleSpecifier: "@lunora/mail" },
|
|
249
250
|
payments: { contextProperty: "payments", moduleSpecifier: "@lunora/payment" },
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
// Pipelines is its own `@lunora/bindings/pipelines` subpath (distinct from
|
|
252
|
+
// `/analytics`), so a real import is a clean signal that won't be flipped by a
|
|
253
|
+
// plain analytics import; `ctx.pipelines` reads flip it too.
|
|
254
|
+
pipelines: { contextProperty: "pipelines", moduleSpecifier: "@lunora/bindings/pipelines" },
|
|
255
|
+
r2sql: { contextProperty: "r2sql", moduleSpecifier: "@lunora/bindings/r2sql" },
|
|
252
256
|
scheduler: { contextProperty: "scheduler", moduleSpecifier: "@lunora/scheduler" },
|
|
253
257
|
storage: { contextProperty: "storage", moduleSpecifier: "@lunora/storage" },
|
|
254
|
-
vectors: { contextProperty: "vectors", moduleSpecifier: "@lunora/vectors" },
|
|
258
|
+
vectors: { contextProperty: "vectors", moduleSpecifier: "@lunora/bindings/vectors" },
|
|
255
259
|
workflows: { contextProperty: "workflows", moduleSpecifier: "@lunora/workflow" }
|
|
256
260
|
};
|
|
257
261
|
const readsContextProperty = (sourceFile, property) => {
|
|
@@ -313,9 +317,10 @@ const buildStudioFeatures = (usage, signals) => {
|
|
|
313
317
|
return {
|
|
314
318
|
mail: usage.mail || signals.dependencies.has("@lunora/mail"),
|
|
315
319
|
payments: usage.payments || signals.dependencies.has("@lunora/payment"),
|
|
320
|
+
queues: signals.queueCount > 0 || signals.dependencies.has("@lunora/queue"),
|
|
316
321
|
scheduler: usage.scheduler || signals.cronCount > 0 || signals.dependencies.has("@lunora/scheduler"),
|
|
317
322
|
storage: usage.storage || signals.storageRuleCount > 0 || signals.storageColumnCount > 0 || signals.dependencies.has("@lunora/storage"),
|
|
318
|
-
vectors: usage.vectors || signals.vectorIndexCount > 0 || signals.dependencies.has("@lunora/vectors"),
|
|
323
|
+
vectors: usage.vectors || signals.vectorIndexCount > 0 || signals.dependencies.has("@lunora/bindings/vectors"),
|
|
319
324
|
workflows: usage.workflows || signals.workflowCount > 0 || signals.dependencies.has("@lunora/workflow")
|
|
320
325
|
};
|
|
321
326
|
};
|
|
@@ -735,6 +740,7 @@ const runCodegen = (options) => {
|
|
|
735
740
|
const httpRoutes = discoverHttpRoutes(project, lunoraDirectory);
|
|
736
741
|
const migrations = discoverMigrations(project, lunoraDirectory);
|
|
737
742
|
const workflows = discoverWorkflows(project, lunoraDirectory);
|
|
743
|
+
const queues = discoverQueues(project, lunoraDirectory);
|
|
738
744
|
const crons = discoverCrons(project, lunoraDirectory, workflows);
|
|
739
745
|
const containers = discoverContainers(project, lunoraDirectory);
|
|
740
746
|
const advisories = options.lint === false ? [] : lintSchema(
|
|
@@ -772,6 +778,7 @@ const runCodegen = (options) => {
|
|
|
772
778
|
const studioFeatures = buildStudioFeatures(featureUsage, {
|
|
773
779
|
cronCount: crons.length,
|
|
774
780
|
dependencies,
|
|
781
|
+
queueCount: queues.length,
|
|
775
782
|
storageColumnCount: Object.keys(buildStorageColumns(schema)).length,
|
|
776
783
|
storageRuleCount: storageRulesMetadata.rules.length,
|
|
777
784
|
vectorIndexCount: schema.vectorIndexes.length,
|
|
@@ -792,6 +799,7 @@ const runCodegen = (options) => {
|
|
|
792
799
|
hasPayments,
|
|
793
800
|
hasPipelines,
|
|
794
801
|
hasR2sql,
|
|
802
|
+
queues,
|
|
795
803
|
schema,
|
|
796
804
|
storageRuleBuckets: storageRulesMetadata.rules.map((rule) => rule.bucket),
|
|
797
805
|
useUmbrella,
|
|
@@ -808,8 +816,10 @@ const runCodegen = (options) => {
|
|
|
808
816
|
hasImages,
|
|
809
817
|
hasKv,
|
|
810
818
|
hasPayments,
|
|
819
|
+
hasPipelines,
|
|
811
820
|
hasR2sql,
|
|
812
821
|
maskMetadata,
|
|
822
|
+
queues,
|
|
813
823
|
rlsMetadata,
|
|
814
824
|
schema,
|
|
815
825
|
storageRules: storageRulesMetadata,
|
|
@@ -819,6 +829,7 @@ const runCodegen = (options) => {
|
|
|
819
829
|
});
|
|
820
830
|
const containersContent = emitContainers(containers, schema.jurisdiction);
|
|
821
831
|
const workflowsContent = emitWorkflows(workflows);
|
|
832
|
+
const queuesContent = emitQueues(queues);
|
|
822
833
|
const cronsContent = emitCrons(crons);
|
|
823
834
|
const vectorsContent = emitVectors(schema.vectorIndexes);
|
|
824
835
|
const drizzleFiles = emitDrizzleSchema(schema, useUmbrella);
|
|
@@ -844,6 +855,7 @@ const runCodegen = (options) => {
|
|
|
844
855
|
hasKv,
|
|
845
856
|
hasPayments,
|
|
846
857
|
hasR2sql,
|
|
858
|
+
hasQueue: queues.some((queue) => queue.mode === "push"),
|
|
847
859
|
hasScheduler: studioFeatures.scheduler,
|
|
848
860
|
hasStorage: studioFeatures.storage,
|
|
849
861
|
hasVectors: schema.vectorIndexes.length > 0,
|
|
@@ -886,6 +898,7 @@ const runCodegen = (options) => {
|
|
|
886
898
|
writeIfChanged(join(outputDirectory, "drizzle.shard.ts"), drizzleFiles.shard);
|
|
887
899
|
writeIfPresent(join(outputDirectory, "containers.ts"), containersContent);
|
|
888
900
|
writeIfPresent(join(outputDirectory, "workflows.ts"), workflowsContent);
|
|
901
|
+
writeIfPresent(join(outputDirectory, "queues.ts"), queuesContent);
|
|
889
902
|
writeIfPresent(join(outputDirectory, "seed.ts"), seedContent);
|
|
890
903
|
if (wantsOpenApi) {
|
|
891
904
|
writeIfChanged(join(outputDirectory, "openapi.json"), openApiContent);
|
|
@@ -923,6 +936,7 @@ const runCodegen = (options) => {
|
|
|
923
936
|
openApiModule: openApiModuleContent,
|
|
924
937
|
openRpc: openRpcContent,
|
|
925
938
|
openRpcModule: openRpcModuleContent,
|
|
939
|
+
queues: queuesContent,
|
|
926
940
|
seed: seedContent,
|
|
927
941
|
server: serverContent,
|
|
928
942
|
shard: shardContent,
|
|
@@ -930,6 +944,7 @@ const runCodegen = (options) => {
|
|
|
930
944
|
workflows: workflowsContent
|
|
931
945
|
},
|
|
932
946
|
outputDirectory,
|
|
947
|
+
queues,
|
|
933
948
|
schemaSnapshot,
|
|
934
949
|
schemaSnapshotPath,
|
|
935
950
|
workflows
|
package/dist/packem_shared/{buildOpenApiDocument-Cu3mZl-8.mjs → buildOpenApiDocument-699G4RP4.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GENERATED_HEADER } from './GENERATED_HEADER-
|
|
1
|
+
import { GENERATED_HEADER } from './GENERATED_HEADER-BEA7oWGC.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-
|
|
1
|
+
import { GENERATED_HEADER } from './GENERATED_HEADER-BEA7oWGC.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`)."],
|
|
@@ -23,7 +23,7 @@ const LONG_TAIL = [
|
|
|
23
23
|
];
|
|
24
24
|
const hasAnyLongTail = (options) => LONG_TAIL.some(([flag]) => options[flag]);
|
|
25
25
|
const buildImportLines = (options) => {
|
|
26
|
-
const { hasAuth, hasFramework, hasGlobal, hasHyperdriveGlobal, hasScheduler, hasStorage, hasWorkflow, useUmbrella, wantsOpenApi, wantsOpenRpc } = options;
|
|
26
|
+
const { hasAuth, hasFramework, hasGlobal, hasHyperdriveGlobal, hasQueue, hasScheduler, hasStorage, hasWorkflow, useUmbrella, wantsOpenApi, wantsOpenRpc } = options;
|
|
27
27
|
const runtimeModule = useUmbrella ? "lunorash/runtime" : "@lunora/runtime";
|
|
28
28
|
const runtimeTypeImports = ["ExecutionContextLike", "LunoraWorker", "Route", "ScheduledControllerLike", "ShardNamespaceLike", "WorkerOptions"];
|
|
29
29
|
if (hasGlobal) {
|
|
@@ -60,6 +60,7 @@ const buildImportLines = (options) => {
|
|
|
60
60
|
...hasGlobal || hasHyperdriveGlobal ? [`import schema from "../schema.js";`] : [],
|
|
61
61
|
`import { LUNORA_CRONS } from "./crons.js";`,
|
|
62
62
|
`import { LUNORA_FUNCTIONS } from "./functions.js";`,
|
|
63
|
+
...hasQueue ? [`import { dispatchQueueBatch } from "@lunora/queue";`, `import { LUNORA_QUEUE_REGISTRY } from "./queues.js";`] : [],
|
|
63
64
|
...wantsOpenApi ? [`import { openApiSpec } from "./openapi.js";`] : [],
|
|
64
65
|
...wantsOpenRpc ? [`import { openRpcSpec } from "./openrpc.js";`] : [],
|
|
65
66
|
`import { createShardDO } from "./shard.js";`
|
|
@@ -354,6 +355,14 @@ const buildBaseWorkerOptions = (options) => [
|
|
|
354
355
|
...options.jurisdiction ? [` jurisdiction: ${JSON.stringify(options.jurisdiction)},`] : [],
|
|
355
356
|
...options.wantsOpenApi ? [` openApiSpec,`] : [],
|
|
356
357
|
...options.wantsOpenRpc ? [` openRpcSpec,`] : [],
|
|
358
|
+
// The push-consumer handler backing the worker's `queue(batch, …)` entry:
|
|
359
|
+
// routes each delivered batch to its `defineQueue` handler. Built from
|
|
360
|
+
// `@lunora/queue` here (keeping the runtime decoupled) and wired only when the
|
|
361
|
+
// app declares push queues in `lunora/queues.ts`.
|
|
362
|
+
...options.hasQueue ? [
|
|
363
|
+
` queue: (batch: unknown, queueEnv: unknown, _context: ExecutionContextLike): Promise<void> =>`,
|
|
364
|
+
` dispatchQueueBatch(batch as Parameters<typeof dispatchQueueBatch>[0], LUNORA_QUEUE_REGISTRY, { env: queueEnv as Record<string, unknown> }),`
|
|
365
|
+
] : [],
|
|
357
366
|
` routes: this.routeMap,`,
|
|
358
367
|
` shardDO: this.shardSelector?.(env) ?? (undefined as unknown as ShardNamespaceLike),`
|
|
359
368
|
];
|
|
@@ -562,7 +571,12 @@ ${buildWorkerLine}
|
|
|
562
571
|
worker ??= buildWorker(rawEnv as Env);
|
|
563
572
|
|
|
564
573
|
return worker.serverQuery(request, rawEnv, reference, args, options);
|
|
565
|
-
}
|
|
574
|
+
},${options.hasQueue ? `
|
|
575
|
+
queue: async (batch: unknown, rawEnv: unknown, context: ExecutionContextLike): Promise<void> => {
|
|
576
|
+
worker ??= buildWorker(rawEnv as Env);
|
|
577
|
+
|
|
578
|
+
return worker.queue?.(batch, rawEnv, context);
|
|
579
|
+
},` : ""}
|
|
566
580
|
};
|
|
567
581
|
|
|
568
582
|
if (this.emailHandler) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/codegen",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.12",
|
|
4
4
|
"description": "Code generator for Lunora: emits _generated/{api,server,dataModel}.ts from your schema",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"directory": "packages/codegen"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
|
-
"dist",
|
|
28
|
+
"./dist",
|
|
29
29
|
"__assets__",
|
|
30
30
|
"README.md",
|
|
31
31
|
"LICENSE.md"
|
|
@@ -46,11 +46,12 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@lunora/advisor": "1.0.0-alpha.
|
|
50
|
-
"@lunora/container": "1.0.0-alpha.
|
|
51
|
-
"@lunora/
|
|
52
|
-
"@lunora/
|
|
53
|
-
"@lunora/
|
|
49
|
+
"@lunora/advisor": "1.0.0-alpha.6",
|
|
50
|
+
"@lunora/container": "1.0.0-alpha.4",
|
|
51
|
+
"@lunora/queue": "1.0.0-alpha.1",
|
|
52
|
+
"@lunora/scheduler": "1.0.0-alpha.3",
|
|
53
|
+
"@lunora/values": "1.0.0-alpha.3",
|
|
54
|
+
"@lunora/workflow": "1.0.0-alpha.3",
|
|
54
55
|
"ts-morph": "^28.0.0"
|
|
55
56
|
},
|
|
56
57
|
"engines": {
|