@lunora/codegen 1.0.0-alpha.317 → 1.0.0-alpha.319

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.
@@ -5,7 +5,7 @@ import{APP_METHOD_CAPABILITIES as k}from"./CAPABILITY_PROBES-brcmKenl.mjs";impor
5
5
 
6
6
  return namespace ? createScheduler({${e.jurisdiction?` jurisdiction: ${JSON.stringify(e.jurisdiction)},`:""} namespace }) : undefined;
7
7
  }
8
- `:"",x=e=>e?`
8
+ `:"",A=e=>e?`
9
9
  /**
10
10
  * One bucket's \`Storage\`, signing under the name it is registered as.
11
11
  *
@@ -19,12 +19,16 @@ import{APP_METHOD_CAPABILITIES as k}from"./CAPABILITY_PROBES-brcmKenl.mjs";impor
19
19
  * declared.
20
20
  */
21
21
  private makeStorage(env: Env, declaration: StorageDeclaration<Env>, bucket: R2BucketLike, bucketName: string, origin?: string): Storage {
22
+ const publicBaseUrl = declaration.publicBaseUrl?.(env) ?? origin;
23
+ const s3 = declaration.s3?.(env);
24
+ const signingSecret = declaration.signingSecret?.(env);
25
+
22
26
  return createStorage({
23
27
  bucket,
24
28
  bucketName,
25
- publicBaseUrl: declaration.publicBaseUrl?.(env) ?? origin,
26
- s3: declaration.s3?.(env),
27
- signingSecret: declaration.signingSecret?.(env),
29
+ ...(publicBaseUrl === undefined ? {} : { publicBaseUrl }),
30
+ ...(s3 === undefined ? {} : { s3 }),
31
+ ...(signingSecret === undefined ? {} : { signingSecret }),
28
32
  });
29
33
  }
30
34
 
@@ -103,14 +107,14 @@ import{APP_METHOD_CAPABILITIES as k}from"./CAPABILITY_PROBES-brcmKenl.mjs";impor
103
107
  storageDelete: (key: string, opts?: { bucket?: string }) => pick(opts?.bucket).delete(key),
104
108
  storageDownload: (key: string, opts?: { bucket?: string }) => pick(opts?.bucket).download(key),
105
109
  storageList: (prefix?: string, opts?: { bucket?: string; cursor?: string; limit?: number }) => pick(opts?.bucket).list(prefix, opts),
106
- storageSignedUrl: hasSigning
107
- ? (key: string, opts?: { bucket?: string; contentType?: string; expiresInSeconds?: number; method?: "GET" | "PUT"; origin?: string }) =>
108
- pick(opts?.bucket, opts?.origin).getSignedUrl(key, { contentType: opts?.contentType, expiresInSeconds: opts?.expiresInSeconds, method: opts?.method })
109
- : undefined,
110
+ ...(hasSigning ? {
111
+ storageSignedUrl: (key: string, opts?: { bucket?: string; contentType?: string; expiresInSeconds?: number; method?: "GET" | "PUT"; origin?: string }) =>
112
+ pick(opts?.bucket, opts?.origin).getSignedUrl(key, opts),
113
+ } : {}),
110
114
  storageUpload: (key: string, body: ArrayBuffer, opts?: { bucket?: string; contentType?: string; sha256?: string }) => pick(opts?.bucket).upload(key, body, opts),
111
115
  };
112
116
  }
113
- `:"",A=e=>e?`
117
+ `:"",x=e=>e?`
114
118
  /**
115
119
  * Adapt the raw D1 binding to \`@lunora/d1\`'s \`D1Exec\` (reads via \`all\`, writes via \`run\`, and — when the binding exposes it — several writes in one round trip via \`batch\`).
116
120
  *
@@ -186,29 +190,29 @@ const buildExec = (database: D1DatabaseLike, bookmark?: string, onBookmark?: (bo
186
190
  // \`target\`, so the real workerd \`D1Database\`/session doesn't throw
187
191
  // \`TypeError: Illegal invocation\` the way a detached
188
192
  // \`const fn = target.batch; fn(...)\` capture would.
189
- batch: batchFn
190
- ? async (statements) => {
191
- const results = await batchFn.call(
192
- target,
193
- statements.map(({ params, sql }) => target.prepare(sql).bind(...params)),
194
- );
195
-
196
- // Meter each leg. D1 returns one result per statement, in
197
- // order, each with its own \`meta\` — and a batch is where the
198
- // expensive writes live (\`@lunora/sql-store\` runs its
199
- // backfills through here), so discarding it left exactly the
200
- // statements worth costing unaccounted. Guarded on the array
201
- // because \`batch\` is optional in the structural type and a
202
- // test double may resolve to anything.
203
- if (Array.isArray(results)) {
204
- for (const [index, statement] of statements.entries()) {
205
- meter(statement.sql, (results[index] as { meta?: Record<string, unknown> } | undefined)?.meta);
206
- }
207
- }
193
+ ...(batchFn ? {
194
+ batch: async (statements) => {
195
+ const results = await batchFn.call(
196
+ target,
197
+ statements.map(({ params, sql }) => target.prepare(sql).bind(...params)),
198
+ );
199
+
200
+ // Meter each leg. D1 returns one result per statement, in
201
+ // order, each with its own \`meta\` — and a batch is where the
202
+ // expensive writes live (\`@lunora/sql-store\` runs its
203
+ // backfills through here), so discarding it left exactly the
204
+ // statements worth costing unaccounted. Guarded on the array
205
+ // because \`batch\` is optional in the structural type and a
206
+ // test double may resolve to anything.
207
+ if (Array.isArray(results)) {
208
+ for (const [index, statement] of statements.entries()) {
209
+ meter(statement.sql, (results[index] as { meta?: Record<string, unknown> } | undefined)?.meta);
210
+ }
211
+ }
208
212
 
209
- onBookmark?.(session?.getBookmark() ?? undefined);
210
- }
211
- : undefined,
213
+ onBookmark?.(session?.getBookmark() ?? undefined);
214
+ },
215
+ } : {}),
212
216
  run: async (sql, parameters) => {
213
217
  const result = await target
214
218
  .prepare(sql)
@@ -258,7 +262,7 @@ const buildGlobalImporter =
258
262
  return importGlobalRows(writer, schema as unknown as D1CtxDbOptions["schema"], {
259
263
  exec,
260
264
  rows: request.rows.map((row) => ({ doc: row.doc, line: row.line, table: row.table })),
261
- startLine: request.startLine,
265
+ ...(request.startLine === undefined ? {} : { startLine: request.startLine }),
262
266
  });
263
267
  };
264
268
 
@@ -299,7 +303,7 @@ const buildGlobalCdcSync =
299
303
  return { changes: [], cursor: request.sinceSeq };
300
304
  }
301
305
 
302
- const page = await readD1CdcChanges(exec, { limit: request.limit, sinceSeq: request.sinceSeq });
306
+ const page = await readD1CdcChanges(exec, request);
303
307
 
304
308
  // \`as unknown as\`, because \`CdcChange\` is an interface and interfaces carry
305
309
  // no implicit index signature — the shapes are otherwise identical.
@@ -332,7 +336,7 @@ const buildGlobalCdcApplier =
332
336
 
333
337
  return request.changes.length;
334
338
  };
335
- `:"",C=e=>[...e.hasStorage?["/** `.storage(...)` declaration — one bucket (required) plus optional extra named buckets and signed-URL config. Backs `ctx.storage` AND the studio file browser. */\ninterface StorageDeclaration<Env> {\n /** The default R2 bucket binding (the bare `ctx.storage`). */\n bucket: Selector<Env, R2BucketLike>;\n /** Extra named buckets, reached via `ctx.storage.bucket(\"name\")` and the studio's bucket picker. */\n buckets?: Record<string, Selector<Env, R2BucketLike>>;\n /** Public base URL signed/public object URLs resolve against. Omit it and `ctx.storage` in a mutation, action or HTTP handler (and the studio's copy-URL) signs against the origin the request reached the worker on — no per-environment value to ship. Queries get no such fallback (a live query re-runs with no request behind it), so a query that signs URLs needs this set. */\n publicBaseUrl?: Selector<Env, string>;\n /** R2 S3-API credentials (`{ accountId, accessKeyId, secretAccessKey, bucket, jurisdiction? }`) enabling `ctx.storage.getPresignedUrl` — native S3 presigned URLs that hit R2 directly, bypassing the worker. Omit to use only the worker-signed `getSignedUrl` path. */\n s3?: Selector<Env, R2S3Credentials>;\n /** HMAC secret for signed URLs. */\n signingSecret?: Selector<Env, string>;\n}"]:[],...e.hasScheduler?["/** `.scheduler(...)` declaration — the `SchedulerDO` namespace. Backs `ctx.scheduler` AND the studio's scheduled-jobs view. The origin its callbacks dispatch back to is not declared here: the DO reads `env.LUNORA_ORIGIN_URL` at fire time, because a caller-supplied dispatch target would be an SSRF vector. */\ninterface SchedulerDeclaration<Env> {\n /** The `SchedulerDO` namespace binding (typically `env.SCHEDULER`). */\n namespace: Selector<Env, DurableObjectNamespaceLike & ShardNamespaceLike>;\n}"]:[],...e.hasGlobal?["/** `.global(...)` declaration — the D1 binding backing `.global()` tables. Backs cross-tenant `ctx.db` reads/writes AND the studio's global data browser. */\ninterface GlobalDeclaration<Env> {\n /** The D1 binding (typically `env.DB`). */\n d1: Selector<Env, D1DatabaseLike>;\n /** The worker origin used to fan reverse cross-backend relations across shards. Without it, such a relation throws a clear error. */\n origin?: Selector<Env, string>;\n}"]:[],...e.hasHyperdriveGlobal?['/** `.hyperdriveGlobal(...)` declaration — backs `.global({ backend: "hyperdrive" })` tables on a Postgres/MySQL database via Hyperdrive. Stays reactive: the writer is injected as `globalDb` and the broadcast hook drives live queries. */\ninterface HyperdriveGlobalDeclaration<Env> {\n /** The Hyperdrive engine — selects the Postgres or MySQL dialect. */\n engine: HyperdriveEngine;\n /** Build the `SqlExec` from `env` — e.g. `buildPgExec(fromPostgresJs(postgres(env.HYPERDRIVE.connectionString)))`. Cache the driver on the DO instance; rebuild lazily after hibernation. */\n exec: (env: Env) => SqlExec;\n /** The worker origin used to fan reverse cross-backend relations across shards. Without it, such a relation throws a clear error. */\n origin?: Selector<Env, string>;\n}']:[],...e.hasAuth?['/** `.auth(...)` declaration — better-auth options plus the storage the adapter reads. Give it `d1` (the default) or `namespace` (a Durable Object that hosts the auth tables), never both. The builder owns the lazy build + `ensureMigrated` dance and wires `authHandler` / `resolveIdentity` / `authAdmin`. */\ninterface AuthDeclaration<Env> {\n /** The D1 binding the auth SQL adapter is wired over (via `lunoraD1Adapter`). Omit only when using `namespace`. */\n d1?: Selector<Env, unknown>;\n /** Shared secret the worker presents on the object\'s internal session route. REQUIRED with `namespace`: the binding is reachable from any worker bound to it, so the secret — not the binding — is the authorization boundary. Without it identity resolution fails closed. */\n internalSecret?: Selector<Env, string>;\n /** Name of the Durable Object instance holding the auth tables. Defaults to `"auth"`. Set it to run separate auth objects (per deployment, per tenant) off one namespace. */\n objectName?: Selector<Env, string>;\n /** The auth Durable Object namespace — the DO-backed mode. Needed for `@better-auth/scim`, which requires native transactions that D1 has none of. The object owns the auth tables, so `/api/auth/*` and identity resolution both go through it. Typed as `AuthNamespaceLike` because `createDoAuthWiring` resolves through `idFromName` + `get` and has no `getByName` fallback — both members are load-bearing here, and `ShardNamespaceLike` leaves both optional. */\n namespace?: Selector<Env, AuthNamespaceLike>;\n /** Build the better-auth options from `env` (secret, plugins, email/password, …). */\n options: (env: Env) => LunoraAuthOptions;\n}']:[]],O=e=>[...e.hasAccess?[" private accessSelector?: Selector<Env, CreateAccessResolverOptions | undefined>;"]:[]," private adminToken?: Selector<Env, string>;",...e.hasAuth?[" private authDeclaration?: AuthDeclaration<Env>;"]:[]," private cdcEnabled = false;"," private reactiveCacheConfig: boolean | { maxBytes?: number; maxEntries?: number } = false;",' private maxRelationKeysLimit?: ShardConfig["maxRelationKeys"];',' private observabilitySink?: ShardConfig["observability"];',' private relationExistsPushDownMode?: ShardConfig["relationExistsPushDown"];'," private readonly extendFns: ((env: Env, derived: Readonly<WorkerOptions>) => Partial<WorkerOptions>)[] = [];",...e.hasGlobal?[" private globalDeclaration?: GlobalDeclaration<Env>;"]:[],...e.hasHyperdriveGlobal?[" private hyperdriveGlobalDeclaration?: HyperdriveGlobalDeclaration<Env>;"]:[]," private httpRouterApp?: HttpRouterLike;"," private readonly routeMap: Record<string, Route> = {};",...e.hasScheduler?[" private schedulerDeclaration?: SchedulerDeclaration<Env>;"]:[],...g(e)?[" private readonly shardExtras: Partial<ShardConfig> = {};"]:[],...d(e)?[" private shardRegistrySelector?: Selector<Env, ShardNamespaceLike>;"]:[]," private shardSelector?: Selector<Env, ShardNamespaceLike>;",...e.hasSourcedTables?[' private sourceClientFactory?: NonNullable<ShardConfig["sourceClient"]>;']:[],...e.hasStorage?[" private storageDeclaration?: StorageDeclaration<Env>;"]:[]],T=e=>m(e).map(({configKey:r,doc:t,method:a})=>` /** ${t} */
339
+ `:"",C=e=>[...e.hasStorage?["/** `.storage(...)` declaration — one bucket (required) plus optional extra named buckets and signed-URL config. Backs `ctx.storage` AND the studio file browser. */\ninterface StorageDeclaration<Env> {\n /** The default R2 bucket binding (the bare `ctx.storage`). */\n bucket: Selector<Env, R2BucketLike>;\n /** Extra named buckets, reached via `ctx.storage.bucket(\"name\")` and the studio's bucket picker. */\n buckets?: Record<string, Selector<Env, R2BucketLike>>;\n /** Public base URL signed/public object URLs resolve against. Omit it and `ctx.storage` in a mutation, action or HTTP handler (and the studio's copy-URL) signs against the origin the request reached the worker on — no per-environment value to ship. Queries get no such fallback (a live query re-runs with no request behind it), so a query that signs URLs needs this set. */\n publicBaseUrl?: Selector<Env, string>;\n /** R2 S3-API credentials (`{ accountId, accessKeyId, secretAccessKey, bucket, jurisdiction? }`) enabling `ctx.storage.getPresignedUrl` — native S3 presigned URLs that hit R2 directly, bypassing the worker. Omit to use only the worker-signed `getSignedUrl` path. */\n s3?: Selector<Env, R2S3Credentials>;\n /** HMAC secret for signed URLs. */\n signingSecret?: Selector<Env, string>;\n}"]:[],...e.hasScheduler?["/** `.scheduler(...)` declaration — the `SchedulerDO` namespace. Backs `ctx.scheduler` AND the studio's scheduled-jobs view. The origin its callbacks dispatch back to is not declared here: the DO reads `env.LUNORA_ORIGIN_URL` at fire time, because a caller-supplied dispatch target would be an SSRF vector. */\ninterface SchedulerDeclaration<Env> {\n /** The `SchedulerDO` namespace binding (typically `env.SCHEDULER`). */\n namespace: Selector<Env, DurableObjectNamespaceLike & ShardNamespaceLike>;\n}"]:[],...e.hasGlobal?["/** `.global(...)` declaration — the D1 binding backing `.global()` tables. Backs cross-tenant `ctx.db` reads/writes AND the studio's global data browser. */\ninterface GlobalDeclaration<Env> {\n /** The D1 binding (typically `env.DB`). */\n d1: Selector<Env, D1DatabaseLike>;\n /** The worker origin used to fan reverse cross-backend relations across shards. Without it, such a relation throws a clear error. */\n origin?: Selector<Env, string>;\n}"]:[],...e.hasHyperdriveGlobal?['/** `.hyperdriveGlobal(...)` declaration — backs `.global({ backend: "hyperdrive" })` tables on a Postgres/MySQL database via Hyperdrive. Stays reactive: the writer is injected as `globalDb` and the broadcast hook drives live queries. */\ninterface HyperdriveGlobalDeclaration<Env> {\n /** The Hyperdrive engine — selects the Postgres or MySQL dialect. */\n engine: HyperdriveEngine;\n /** Build the `SqlExec` from `env` — e.g. `buildPgExec(fromPostgresJs(postgres(env.HYPERDRIVE.connectionString)))`. Cache the driver on the DO instance; rebuild lazily after hibernation. */\n exec: (env: Env) => SqlExec;\n /** The worker origin used to fan reverse cross-backend relations across shards. Without it, such a relation throws a clear error. */\n origin?: Selector<Env, string>;\n}']:[],...e.hasAuth?['/** `.auth(...)` declaration — better-auth options plus the storage the adapter reads. Give it `d1` (the default) or `namespace` (a Durable Object that hosts the auth tables), never both. The builder owns the lazy build + `ensureMigrated` dance and wires `authHandler` / `resolveIdentity` / `authAdmin`. */\ninterface AuthDeclaration<Env> {\n /** The D1 binding the auth SQL adapter is wired over (via `lunoraD1Adapter`). Omit only when using `namespace`. */\n d1?: Selector<Env, unknown>;\n /** Shared secret the worker presents on the object\'s internal session route. REQUIRED with `namespace`: the binding is reachable from any worker bound to it, so the secret — not the binding — is the authorization boundary. Without it identity resolution fails closed. */\n internalSecret?: Selector<Env, string>;\n /** Name of the Durable Object instance holding the auth tables. Defaults to `"auth"`. Set it to run separate auth objects (per deployment, per tenant) off one namespace. */\n objectName?: Selector<Env, string>;\n /** The auth Durable Object namespace — the DO-backed mode. Needed for `@better-auth/scim`, which requires native transactions that D1 has none of. The object owns the auth tables, so `/api/auth/*` and identity resolution both go through it. Typed as `AuthNamespaceLike` because `createDoAuthWiring` resolves through `idFromName` + `get` and has no `getByName` fallback — both members are load-bearing here, and `ShardNamespaceLike` leaves both optional. */\n namespace?: Selector<Env, AuthNamespaceLike>;\n /** Build the better-auth options from `env` (secret, plugins, email/password, …). */\n options: (env: Env) => LunoraAuthOptions;\n}']:[]],O=e=>[...e.hasAccess?[" private accessSelector?: Selector<Env, CreateAccessResolverOptions | undefined>;"]:[]," private adminToken?: Selector<Env, string>;",...e.hasAuth?[" private authDeclaration?: AuthDeclaration<Env>;"]:[]," private cdcEnabled = false;",' private deliveryAuthorizationSelector?: ShardConfig["deliveryAuthorization"];'," private reactiveCacheConfig: boolean | { maxBytes?: number; maxEntries?: number } = false;",' private maxRelationKeysLimit?: ShardConfig["maxRelationKeys"];',' private observabilitySink?: ShardConfig["observability"];',' private relationExistsPushDownMode?: ShardConfig["relationExistsPushDown"];'," private readonly extendFns: ((env: Env, derived: Readonly<WorkerOptions>) => Partial<WorkerOptions>)[] = [];",...e.hasGlobal?[" private globalDeclaration?: GlobalDeclaration<Env>;"]:[],...e.hasHyperdriveGlobal?[" private hyperdriveGlobalDeclaration?: HyperdriveGlobalDeclaration<Env>;"]:[]," private httpRouterApp?: HttpRouterLike;"," private readonly routeMap: Record<string, Route> = {};",...e.hasScheduler?[" private schedulerDeclaration?: SchedulerDeclaration<Env>;"]:[],...g(e)?[" private readonly shardExtras: Partial<ShardConfig> = {};"]:[],...d(e)?[" private shardRegistrySelector?: Selector<Env, ShardNamespaceLike>;"]:[]," private shardSelector?: Selector<Env, ShardNamespaceLike>;",...e.hasSourcedTables?[' private sourceClientFactory?: NonNullable<ShardConfig["sourceClient"]>;']:[],...e.hasStorage?[" private storageDeclaration?: StorageDeclaration<Env>;"]:[]],T=e=>m(e).map(({configKey:r,doc:t,method:a})=>` /** ${t} */
336
340
  public ${a}(factory: (env: Env) => ReturnType<NonNullable<ShardConfig["${r}"]>>): this {
337
341
  this.shardExtras.${r} = factory as NonNullable<ShardConfig["${r}"]>;
338
342
 
@@ -356,7 +360,11 @@ const buildGlobalCdcApplier =
356
360
  this.maxRelationKeysLimit = limit;
357
361
 
358
362
  return this;
359
- }`," /**\n * Route the shard's `ctx.log` lines, `ctx.trace` spans and `ctx.metrics` measurements to a telemetry sink.\n *\n * The DO half of observability: without it every in-handler signal stays in the shard's local ring buffer (the studio Logs panel) and reaches no collector. The worker half — one `onRpc` event per dispatched RPC — is a `createWorker` option; pass the SAME sink to both via `.extend((env) => ({ observability: sink(env) }))` to correlate them.\n */\n public observability(selector: NonNullable<ShardConfig[\"observability\"]>): this {\n this.observabilitySink = selector;\n\n return this;\n }",' /** Resolution policy for a relation-crossing `where` whose child is co-located in this shard: `"auto"` (cost-based, the engine default), `"always"` (inline correlated EXISTS) or `"never"` (universal semijoin). All three return identical rows. */\n public relationExistsPushDown(mode: NonNullable<ShardConfig["relationExistsPushDown"]>): this {\n this.relationExistsPushDownMode = mode;\n\n return this;\n }',...e.hasAuth?[' /** Wire better-auth — the builder lazily builds the instance, runs `ensureMigrated`, and dispatches `/api/auth/*` inside the worker (instrumented for the auth-failure SLO). Pass `d1` for the D1-backed default, or `namespace` + `internalSecret` to host the auth tables in a Durable Object (what `@better-auth/scim` needs). */\n public auth(declaration: AuthDeclaration<Env>): this {\n // Reject the ambiguous and the empty shapes here rather than at the first\n // request: with neither storage set, auth would silently never answer, and\n // with both it is unclear which one owns the tables.\n if (declaration.d1 && declaration.namespace) {\n throw new Error(".auth(): pass either `d1` or `namespace`, not both — they are two different homes for the same tables.");\n }\n\n if (!declaration.d1 && !declaration.namespace) {\n throw new Error(".auth(): needs `d1` (D1-backed) or `namespace` (Durable-Object-backed) to know where the auth tables live.");\n }\n\n if (declaration.namespace && !declaration.internalSecret) {\n throw new Error(\n ".auth(): `namespace` requires `internalSecret` — the auth DO binding is reachable from any worker bound to it, so identity resolution is gated on a shared secret and would otherwise fail closed on every request.",\n );\n }\n\n this.authDeclaration = declaration;\n\n return this;\n }']:[]," /** Escape hatch — merge raw `WorkerOptions` (anything not yet sugared) over the derived options at build time. The second `derived` argument is a snapshot of the options assembled so far (after `.auth(...)` etc.), so you can compose rather than clobber — e.g. wrap `derived.resolveIdentity` instead of replacing it. */\n public extend(fn: (env: Env, derived: Readonly<WorkerOptions>) => Partial<WorkerOptions>): this {\n this.extendFns.push(fn);\n\n return this;\n }",...e.hasGlobal?[` /** Back \`.global()\` (cross-tenant) tables with D1 — wires \`ctx.db\` routing, the studio global browser, and reverse cross-shard relations. */
363
+ }`," /**\n * Route the shard's `ctx.log` lines, `ctx.trace` spans and `ctx.metrics` measurements to a telemetry sink.\n *\n * The DO half of observability: without it every in-handler signal stays in the shard's local ring buffer (the studio Logs panel) and reaches no collector. The worker half — one `onRpc` event per dispatched RPC — is a `createWorker` option; pass the SAME sink to both via `.extend((env) => ({ observability: sink(env) }))` to correlate them.\n */\n public observability(selector: NonNullable<ShardConfig[\"observability\"]>): this {\n this.observabilitySink = selector;\n\n return this;\n }",' /** Resolution policy for a relation-crossing `where` whose child is co-located in this shard: `"auto"` (cost-based, the engine default), `"always"` (inline correlated EXISTS) or `"never"` (universal semijoin). All three return identical rows. */\n public relationExistsPushDown(mode: NonNullable<ShardConfig["relationExistsPushDown"]>): this {\n this.relationExistsPushDownMode = mode;\n\n return this;\n }',` /** Authorize each RPC/subscription read and fence its eventual delivery against durable authority epochs. */
364
+ public deliveryAuthorization(selector: NonNullable<ShardConfig["deliveryAuthorization"]>): this {
365
+ this.deliveryAuthorizationSelector = selector;
366
+ return this;
367
+ }`,...e.hasAuth?[' /** Wire better-auth — the builder lazily builds the instance, runs `ensureMigrated`, and dispatches `/api/auth/*` inside the worker (instrumented for the auth-failure SLO). Pass `d1` for the D1-backed default, or `namespace` + `internalSecret` to host the auth tables in a Durable Object (what `@better-auth/scim` needs). */\n public auth(declaration: AuthDeclaration<Env>): this {\n // Reject the ambiguous and the empty shapes here rather than at the first\n // request: with neither storage set, auth would silently never answer, and\n // with both it is unclear which one owns the tables.\n if (declaration.d1 && declaration.namespace) {\n throw new Error(".auth(): pass either `d1` or `namespace`, not both — they are two different homes for the same tables.");\n }\n\n if (!declaration.d1 && !declaration.namespace) {\n throw new Error(".auth(): needs `d1` (D1-backed) or `namespace` (Durable-Object-backed) to know where the auth tables live.");\n }\n\n if (declaration.namespace && !declaration.internalSecret) {\n throw new Error(\n ".auth(): `namespace` requires `internalSecret` — the auth DO binding is reachable from any worker bound to it, so identity resolution is gated on a shared secret and would otherwise fail closed on every request.",\n );\n }\n\n this.authDeclaration = declaration;\n\n return this;\n }']:[]," /** Escape hatch — merge raw `WorkerOptions` (anything not yet sugared) over the derived options at build time. The second `derived` argument is a snapshot of the options assembled so far (after `.auth(...)` etc.), so you can compose rather than clobber — e.g. wrap `derived.resolveIdentity` instead of replacing it. */\n public extend(fn: (env: Env, derived: Readonly<WorkerOptions>) => Partial<WorkerOptions>): this {\n this.extendFns.push(fn);\n\n return this;\n }",...e.hasGlobal?[` /** Back \`.global()\` (cross-tenant) tables with D1 — wires \`ctx.db\` routing, the studio global browser, and reverse cross-shard relations. */
360
368
  public global(declaration: GlobalDeclaration<Env>): this {
361
369
  this.globalDeclaration = declaration;
362
370
 
@@ -397,7 +405,7 @@ const buildGlobalCdcApplier =
397
405
 
398
406
  return this;
399
407
  }`]:[],...T(e)],I=e=>{const r=a=>e.hasScheduler?`
400
- ...(this.schedulerDeclaration ? { scheduler: this.resolveScheduler(env) as unknown as ${a}["scheduler"] } : {}),`:"",t=[" cdc: this.cdcEnabled,"," reactiveCache: this.reactiveCacheConfig,"," ...(this.maxRelationKeysLimit === undefined ? {} : { maxRelationKeys: this.maxRelationKeysLimit }),"," ...(this.observabilitySink === undefined ? {} : { observability: this.observabilitySink }),"," ...(this.relationExistsPushDownMode === undefined ? {} : { relationExistsPushDown: this.relationExistsPushDownMode }),",...e.hasGlobal?[` ...(this.globalDeclaration
408
+ ...(this.schedulerDeclaration ? { scheduler: this.resolveScheduler(env) as unknown as ${a}["scheduler"] } : {}),`:"",t=[" cdc: this.cdcEnabled,"," reactiveCache: this.reactiveCacheConfig,"," ...(this.maxRelationKeysLimit === undefined ? {} : { maxRelationKeys: this.maxRelationKeysLimit }),"," ...(this.observabilitySink === undefined ? {} : { observability: this.observabilitySink }),"," ...(this.deliveryAuthorizationSelector === undefined ? {} : { deliveryAuthorization: this.deliveryAuthorizationSelector }),"," ...(this.relationExistsPushDownMode === undefined ? {} : { relationExistsPushDown: this.relationExistsPushDownMode }),",...e.hasGlobal?[` ...(this.globalDeclaration
401
409
  ? {
402
410
  d1: (rawEnv: Record<string, unknown>, request?: { bookmark?: string; cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; onBookmark?: (bookmark: string | undefined) => void; userId?: string | null }) => {
403
411
  const env = rawEnv as Env;
@@ -409,7 +417,11 @@ const buildGlobalCdcApplier =
409
417
 
410
418
  const origin = this.globalDeclaration?.origin?.(env);
411
419
  const crossShard = origin
412
- ? createCrossShardRelationCapabilities({ identity: request?.identity, origin, userId: request?.userId ?? undefined })
420
+ ? createCrossShardRelationCapabilities({
421
+ ...(request?.identity === undefined ? {} : { identity: request.identity }),
422
+ origin,
423
+ ...(request?.userId == null ? {} : { userId: request.userId }),
424
+ })
413
425
  : undefined;
414
426
 
415
427
  return createD1CtxDb({
@@ -443,7 +455,11 @@ const buildGlobalCdcApplier =
443
455
 
444
456
  const origin = declaration.origin?.(env);
445
457
  const crossShard = origin
446
- ? createCrossShardRelationCapabilities({ identity: request?.identity, origin, userId: request?.userId ?? undefined })
458
+ ? createCrossShardRelationCapabilities({
459
+ ...(request?.identity === undefined ? {} : { identity: request.identity }),
460
+ origin,
461
+ ...(request?.userId == null ? {} : { userId: request.userId }),
462
+ })
447
463
  : undefined;
448
464
 
449
465
  return createHyperdriveGlobalCtxDb({
@@ -471,7 +487,7 @@ const buildGlobalCdcApplier =
471
487
  : {}),`]:[],...d(e)?[" ...(this.shardRegistrySelector ? { shardRegistry: (rawEnv: Record<string, unknown>) => this.shardRegistrySelector?.(rawEnv as Env) } : {}),"]:[],...e.hasSourcedTables?[" ...(this.sourceClientFactory === undefined ? {} : { sourceClient: this.sourceClientFactory }),"]:[],...e.hasStorage?[" ...(this.storageDeclaration ? { storage: (rawEnv: Record<string, unknown>, origin?: string) => this.resolveStorage(rawEnv as Env, origin) } : {}),"]:[],...g(e)?[" ...this.shardExtras,"]:[]];return t.length>0?`
472
488
  ${t.join(`
473
489
  `)}
474
- `:""},q=e=>e?['import * as lunoraIdentityContract from "../identity.js";']:[],L=(e,r)=>e?['import type { CreateAccessResolverOptions } from "@lunora/cloudflare-access";',`import { createAccessResolver${r?", composeResolvers":""} } from "@lunora/cloudflare-access";`]:[],j=e=>e?['import { createKvIntrospectorFromEnv } from "@lunora/bindings/kv";']:[],B=e=>e?['import { createVectorAdminIntrospector } from "@lunora/bindings/vectors";']:[],G=e=>e?['import type { D1CtxDbOptions, D1DatabaseLike, D1Exec } from "@lunora/d1";','import { applyCdcChanges, createD1CtxDb, emitD1QueryCost, exportGlobalRows, facetGlobalColumn, importGlobalRows, listGlobalTables, readD1CdcChanges, readGlobalTablePage, retryingExec } from "@lunora/d1";']:[],P=e=>e?['import notifyConfig from "../notify.js";']:[],_=e=>v(e)?['import { dispatchAgentEmail } from "@lunora/agent/inbound";']:[],W=e=>v(e)?['import * as lunoraAgentDefinitions from "../agents.js";']:[],M=e=>{const{hasFramework:r,hasGlobal:t,hasHyperdriveGlobal:a,hasQueue:s,useUmbrella:o}=e,i=o?"lunorash/runtime":"@lunora/runtime",c=["ExecutionContextLike","HttpRouterLike","LunoraWorker","Route","ScheduledControllerLike","ShardNamespaceLike","WorkerOptions",...s?["TriggerTrace"]:[],...t?["GlobalIntrospector"]:[],...e.tables.length>0?["ShardingInfo"]:[],...r?["FrameworkHostHandler"]:[]],l=[...t||a?["createCrossShardRelationCapabilities"]:[],...d(e)?["createDynamicShardRegistry","createQueryCoordinator"]:[],"createWorker",...e.jurisdiction?["declareAppJurisdiction"]:[],"resolveLogArchiveFromEnv",...e.hasAuth?["memoizeIdentity"]:[],...r?["withFrameworkWorker"]:[]].join(", ");return[`import type { ${[...c].toSorted((n,h)=>n.localeCompare(h)).join(", ")} } from "${i}";`,`import { ${l} } from "${i}";`]},H=e=>{const{hasAccess:r,hasAuth:t,hasGlobal:a,hasHyperdriveGlobal:s,hasKvIntrospector:o,hasQueue:i,hasScheduler:c,hasStorage:l,hasWorkflow:n,wantsOpenApi:h,wantsOpenRpc:u}=e;return[...t?['import type { AuthNamespaceLike, LunoraAuth, LunoraAuthOptions } from "@lunora/auth";','import { authDiscoveryPathsFor, createAuth, createAuthAdmin, createAuthAuditReader, createDoAuthWiring, d1Executor, handleAuthDiscoveryRequest, handleAuthRequest, lunoraD1Adapter } from "@lunora/auth";']:[],...L(r,t),...G(a),...s?['import type { HyperdriveEngine } from "@lunora/hyperdrive/global";','import { createHyperdriveGlobalCtxDb } from "@lunora/hyperdrive/global";','import type { SqlCtxDbOptions, SqlExec } from "@lunora/sql-store";']:[],...j(o),...B(e.hasVectors),...c?['import type { DurableObjectNamespaceLike } from "@lunora/scheduler";','import { createScheduler } from "@lunora/scheduler";']:[],...l?['import type { R2BucketLike, R2S3Credentials, Storage } from "@lunora/storage";','import { createBucketStorage, createStorage } from "@lunora/storage";']:[],...n?['import { createWorkflowsRestClient } from "@lunora/workflow";']:[],..._(e),...M(e),"",...q(e.identity),...W(e),...a||s?['import schema from "../schema.js";']:[],...P(e.hasNotify),'import { LUNORA_CRONS } from "./crons.js";','import { LUNORA_FUNCTIONS } from "./functions.js";',...i?['import { createQueueCaptureSink, dispatchQueueBatch, shouldCaptureQueue } from "@lunora/queue";','import { LUNORA_QUEUE_REGISTRY } from "./queues.js";']:[],...e.wantsArchitecture?['import { architecture } from "./architecture.js";']:[],...h?['import { openApiSpec } from "./openapi.js";']:[],...u?['import { openRpcSpec } from "./openrpc.js";']:[],'import { createShardDO } from "./shard.js";',...e.hasVectors?['import { LUNORA_VECTOR_INDEXES } from "./vectors.js";']:[]]},$=e=>e.jurisdiction&&e.jurisdictionPinsAuth===!0?`
490
+ `:""},q=e=>e?['import * as lunoraIdentityContract from "../identity.js";']:[],L=(e,r)=>e?['import type { CreateAccessResolverOptions } from "@lunora/cloudflare-access";',`import { createAccessResolver${r?", composeResolvers":""} } from "@lunora/cloudflare-access";`]:[],j=e=>e?['import { createKvIntrospectorFromEnv } from "@lunora/bindings/kv";']:[],B=e=>e?['import { createVectorAdminIntrospector } from "@lunora/bindings/vectors";']:[],P=e=>e?['import type { D1CtxDbOptions, D1DatabaseLike, D1Exec } from "@lunora/d1";','import { applyCdcChanges, createD1CtxDb, emitD1QueryCost, exportGlobalRows, facetGlobalColumn, importGlobalRows, listGlobalTables, readD1CdcChanges, readGlobalTablePage, retryingExec } from "@lunora/d1";']:[],G=e=>e?['import notifyConfig from "../notify.js";']:[],_=e=>v(e)?['import { dispatchAgentEmail } from "@lunora/agent/inbound";']:[],W=e=>v(e)?['import * as lunoraAgentDefinitions from "../agents.js";']:[],M=e=>{const{hasFramework:r,hasGlobal:t,hasHyperdriveGlobal:a,hasQueue:n,useUmbrella:o}=e,i=o?"lunorash/runtime":"@lunora/runtime",c=["ExecutionContextLike","HttpRouterLike","LunoraWorker","Route","ScheduledControllerLike","ShardNamespaceLike","WorkerOptions",...n?["TriggerTrace"]:[],...t?["GlobalIntrospector"]:[],...e.tables.length>0?["ShardingInfo"]:[],...r?["FrameworkHostHandler"]:[]],l=[...t||a?["createCrossShardRelationCapabilities"]:[],...d(e)?["createDynamicShardRegistry","createQueryCoordinator"]:[],"createWorker",...e.jurisdiction?["declareAppJurisdiction"]:[],"resolveLogArchiveFromEnv",...e.hasAuth?["memoizeIdentity"]:[],...r?["withFrameworkWorker"]:[]].join(", ");return[`import type { ${[...c].toSorted((s,h)=>s.localeCompare(h)).join(", ")} } from "${i}";`,`import { ${l} } from "${i}";`]},H=e=>{const{hasAccess:r,hasAuth:t,hasGlobal:a,hasHyperdriveGlobal:n,hasKvIntrospector:o,hasQueue:i,hasScheduler:c,hasStorage:l,hasWorkflow:s,wantsOpenApi:h,wantsOpenRpc:u}=e;return[...t?['import type { AuthNamespaceLike, LunoraAuth, LunoraAuthOptions } from "@lunora/auth";','import { authDiscoveryPathsFor, createAuth, createAuthAdmin, createAuthAuditReader, createDoAuthWiring, d1Executor, handleAuthDiscoveryRequest, handleAuthRequest, lunoraD1Adapter } from "@lunora/auth";']:[],...L(r,t),...P(a),...n?['import type { HyperdriveEngine } from "@lunora/hyperdrive/global";','import { createHyperdriveGlobalCtxDb } from "@lunora/hyperdrive/global";','import type { SqlCtxDbOptions, SqlExec } from "@lunora/sql-store";']:[],...j(o),...B(e.hasVectors),...c?['import type { DurableObjectNamespaceLike } from "@lunora/scheduler";','import { createScheduler } from "@lunora/scheduler";']:[],...l?['import type { R2BucketLike, R2S3Credentials, Storage } from "@lunora/storage";','import { createBucketStorage, createStorage } from "@lunora/storage";']:[],...s?['import { createWorkflowsRestClient } from "@lunora/workflow";']:[],..._(e),...M(e),"",...q(e.identity),...W(e),...a||n?['import schema from "../schema.js";']:[],...G(e.hasNotify),'import { LUNORA_CRONS } from "./crons.js";','import { LUNORA_FUNCTIONS } from "./functions.js";',...i?['import { createQueueCaptureSink, dispatchQueueBatch, shouldCaptureQueue } from "@lunora/queue";','import { LUNORA_QUEUE_REGISTRY } from "./queues.js";']:[],...e.wantsArchitecture?['import { architecture } from "./architecture.js";']:[],...h?['import { openApiSpec } from "./openapi.js";']:[],...u?['import { openRpcSpec } from "./openrpc.js";']:[],'import { createShardDO } from "./shard.js";',...e.hasVectors?['import { LUNORA_VECTOR_INDEXES } from "./vectors.js";']:[]]},$=e=>e.jurisdiction&&e.jurisdictionPinsAuth===!0?`
475
491
  // The schema's jurisdiction pins the auth object like every other DO.
476
492
  jurisdiction: ${JSON.stringify(e.jurisdiction)},`:"",U=e=>typeof e=="string"?`{ mode: { kind: ${JSON.stringify(e)} } }`:`{ mode: { field: ${JSON.stringify(e.field)}, kind: "shardBy" } }`,F=e=>[...e.tables.length>0?[` const tableSharding = new Map<string, ShardingInfo>([
477
493
  ${e.tables.map(r=>` [${JSON.stringify(r.name)}, ${U(r.shardMode)}],`).join(`
@@ -532,7 +548,13 @@ ${e.tables.map(r=>` [${JSON.stringify(r.name)}, ${U(r.shardMode)}],`)
532
548
  throw new Error(
533
549
  ".vectors(): the schema declares vector index(es) but no binding map was chained. Pass \`.vectors((env) => ({ <indexName>: env.<BINDING> }))\` so \`ctx.vectors\` resolves and the studio's Vectors tab can list them.",
534
550
  );
535
- }`]:[],...e.hasNotify?[" options.notifySubscriptionStore = notifyConfig.store ? notifyConfig.store(env as Record<string, unknown>) : undefined;"]:[]," options.logArchive = resolveLogArchiveFromEnv(env);",...e.hasAuth?[` // Captured before the branch so the narrowing survives — reading
551
+ }`]:[],...e.hasNotify?[` if (notifyConfig.store) {
552
+ options.notifySubscriptionStore = notifyConfig.store(env as Record<string, unknown>);
553
+ }`]:[],` const logArchive = resolveLogArchiveFromEnv(env);
554
+
555
+ if (logArchive !== undefined) {
556
+ options.logArchive = logArchive;
557
+ }`,...e.hasAuth?[` // Captured before the branch so the narrowing survives — reading
536
558
  // \`this.authDeclaration.namespace\` again below would be optional all over again.
537
559
  const authDeclaration = this.authDeclaration;
538
560
  const authNamespace = authDeclaration?.namespace;
@@ -544,16 +566,20 @@ ${e.tables.map(r=>` [${JSON.stringify(r.name)}, ${U(r.shardMode)}],`)
544
566
  // to it. \`createDoAuthWiring\` is a tested function in \`@lunora/auth\` rather
545
567
  // than more emitted code: request-path logic in generated output can only be
546
568
  // typechecked, never unit-tested.
569
+ const discoveryPaths = authDiscoveryPathsFor(authDeclaration, env);
570
+ const internalSecret = authDeclaration.internalSecret?.(env);
571
+ const namespace = authNamespace(env);
572
+ const objectName = authDeclaration.objectName?.(env);
547
573
  const authWiring = createDoAuthWiring({
548
574
  // The OAuth discovery documents (an \`mcp()\` resource's metadata, the
549
575
  // issuer's) are derived here from the declared options, so the worker
550
576
  // forwards only those exact paths and no other probe reaches the object.
551
577
  // Memoised on the declaration: a framework-hosted worker rebuilds these
552
578
  // options per request, and \`options(env)\` rebuilds every plugin.
553
- discoveryPaths: authDiscoveryPathsFor(authDeclaration, env),
554
- internalSecret: authDeclaration.internalSecret?.(env),${$(e)}
555
- namespace: authNamespace(env),
556
- objectName: authDeclaration.objectName?.(env),
579
+ discoveryPaths,
580
+ internalSecret,${$(e)}
581
+ namespace,
582
+ ...(objectName === undefined ? {} : { objectName }),
557
583
  });
558
584
 
559
585
  options.authHandler = authWiring.authHandler;
@@ -625,7 +651,9 @@ ${e.tables.map(r=>` [${JSON.stringify(r.name)}, ${U(r.shardMode)}],`)
625
651
  };
626
652
  const authInstance = getAuth();
627
653
 
628
- options.authAdmin = authInstance ? createAuthAdmin(authInstance) : undefined;
654
+ if (authInstance) {
655
+ options.authAdmin = createAuthAdmin(authInstance);
656
+ }
629
657
  options.authAuditReader = createAuthAuditReader(d1Executor(authD1(env) as never));
630
658
  }
631
659
 
@@ -719,10 +747,10 @@ ${e.tables.map(r=>` [${JSON.stringify(r.name)}, ${U(r.shardMode)}],`)
719
747
  }`]:[],...e.voiceAgents&&e.voiceAgents.length>0?[` options.voiceAgents = {
720
748
  ${e.voiceAgents.map(r=>` ${JSON.stringify(r.exportName)}: (env as Record<string, unknown>)[${JSON.stringify(r.bindingName)}] as ShardNamespaceLike,`).join(`
721
749
  `)}
722
- };`]:[]],J=e=>[" cronJobs: LUNORA_CRONS,"," functions: LUNORA_FUNCTIONS,",...e.identity?[` identity: lunoraIdentityContract.${e.identity.exportName},`]:[],...e.jurisdiction?[` jurisdiction: ${JSON.stringify(e.jurisdiction)},`]:[],...e.wantsArchitecture?[" architecture,"]:[],...e.wantsOpenApi?[" openApiSpec,"]:[],...e.wantsOpenRpc?[" openRpcSpec,"]:[],...e.hasQueue?[" queue: (batch: unknown, queueEnv: unknown, _context: ExecutionContextLike, trigger: TriggerTrace): Promise<void> =>"," dispatchQueueBatch(batch as Parameters<typeof dispatchQueueBatch>[0], LUNORA_QUEUE_REGISTRY, {"," capture: shouldCaptureQueue(queueEnv as Record<string, unknown>)",` ? createQueueCaptureSink(queueEnv as Record<string, unknown>${e.jurisdiction?`, { jurisdiction: ${JSON.stringify(e.jurisdiction)} }`:""})`," : undefined,"," env: queueEnv as Record<string, unknown>,"," traceparent: trigger.traceparent,"," }),"]:[]," ...(this.httpRouterApp ? { httpRouter: this.httpRouterApp } : {}),"," routes: this.routeMap,"," shardDO: this.shardSelector?.(env) ?? (undefined as unknown as ShardNamespaceLike),"],K=e=>e?`
750
+ };`]:[]],z=e=>[" cronJobs: LUNORA_CRONS,"," functions: LUNORA_FUNCTIONS,",...e.identity?[` identity: lunoraIdentityContract.${e.identity.exportName},`]:[],...e.jurisdiction?[` jurisdiction: ${JSON.stringify(e.jurisdiction)},`]:[],...e.wantsArchitecture?[" architecture,"]:[],...e.wantsOpenApi?[" openApiSpec,"]:[],...e.wantsOpenRpc?[" openRpcSpec,"]:[],...e.hasQueue?[" queue: (batch: unknown, queueEnv: unknown, _context: ExecutionContextLike, trigger: TriggerTrace): Promise<void> =>"," dispatchQueueBatch(batch as Parameters<typeof dispatchQueueBatch>[0], LUNORA_QUEUE_REGISTRY, {"," capture: shouldCaptureQueue(queueEnv as Record<string, unknown>)",` ? createQueueCaptureSink(queueEnv as Record<string, unknown>${e.jurisdiction?`, { jurisdiction: ${JSON.stringify(e.jurisdiction)} }`:""})`," : undefined,"," env: queueEnv as Record<string, unknown>,"," traceparent: trigger.traceparent,"," }),"]:[]," ...(this.httpRouterApp ? { httpRouter: this.httpRouterApp } : {}),"," routes: this.routeMap,"," shardDO: this.shardSelector?.(env) ?? (undefined as unknown as ShardNamespaceLike),"],J=e=>e?`
723
751
  /** The identity memo per \`env\` object, owned by one assembled worker. */
724
752
  type IdentityMemoStore = WeakMap<object, ReturnType<typeof memoizeIdentity>>;
725
- `:"",V=e=>[...e.hasAuth?["AuthDeclaration"]:[],"ComposedApp",...e.hasGlobal?["GlobalDeclaration"]:[],"LunoraConfig",...e.hasScheduler?["SchedulerDeclaration"]:[],"Selector",...e.hasStorage?["StorageDeclaration"]:[]].toSorted((r,t)=>r.localeCompare(t)).join(", "),Z=e=>{const r=(e.hasVectors??!0)&&(e.vectorIndexCount??0)>0,t={...e,hasVectors:r},{hasAuth:a}=t,s=C(t),o=Q(t),i=a?` let auth: LunoraAuth | null = null;
753
+ `:"",K=e=>[...e.hasAuth?["AuthDeclaration"]:[],"ComposedApp",...e.hasGlobal?["GlobalDeclaration"]:[],"LunoraConfig",...e.hasScheduler?["SchedulerDeclaration"]:[],"Selector",...e.hasStorage?["StorageDeclaration"]:[]].toSorted((r,t)=>r.localeCompare(t)).join(", "),Z=e=>{const r=(e.hasVectors??!0)&&(e.vectorIndexCount??0)>0,t={...e,hasVectors:r},{hasAuth:a}=t,n=C(t),o=Q(t),i=a?` let auth: LunoraAuth | null = null;
726
754
  let authInit: Promise<void> | null = null;
727
755
  // One memo per env for THIS assembled worker: a framework-hosted worker rebuilds its options per
728
756
  // request and must reuse it, but a second \`assemble()\` has its own auth closure and must not share.
@@ -780,8 +808,8 @@ type IdentityMemoStore = WeakMap<object, ReturnType<typeof memoizeIdentity>>;
780
808
  throw error;
781
809
  }));
782
810
  `:"",l=a?`
783
- await ensureAuth(env);`:"",n=a?"() => auth, identityMemos":"() => null",h=a?"getAuth: () => LunoraAuth | null, identityMemos: IdentityMemoStore":"_getAuth: () => null",u=t.hasFramework?` const buildWorker = (env: Env): LunoraWorker =>
784
- host ? withFrameworkWorker(host, (hostEnv) => this.buildWorkerOptions(hostEnv as Env, ${n})) : createWorker(this.buildWorkerOptions(env, ${n}));`:` const buildWorker = (env: Env): LunoraWorker => createWorker(this.buildWorkerOptions(env, ${n}));`,y=t.hasFramework?"host?: FrameworkHostHandler":"",p=t.emailAgents??[],f=p.length>0?` composed.email = dispatchAgentEmail([
811
+ await ensureAuth(env);`:"",s=a?"() => auth, identityMemos":"() => null",h=a?"getAuth: () => LunoraAuth | null, identityMemos: IdentityMemoStore":"_getAuth: () => null",u=t.hasFramework?` const buildWorker = (env: Env): LunoraWorker =>
812
+ host ? withFrameworkWorker(host, (hostEnv) => this.buildWorkerOptions(hostEnv as Env, ${s})) : createWorker(this.buildWorkerOptions(env, ${s}));`:` const buildWorker = (env: Env): LunoraWorker => createWorker(this.buildWorkerOptions(env, ${s}));`,y=t.hasFramework?"host?: FrameworkHostHandler":"",p=t.emailAgents??[],f=p.length>0?` composed.email = dispatchAgentEmail([
785
813
  ${p.map(b=>` { agent: lunoraAgentDefinitions.${b.exportName}, className: ${JSON.stringify(b.className)} },`).join(`
786
814
  `)}
787
815
  ]);
@@ -797,15 +825,15 @@ type Selector<Env, T> = (env: Env) => T | undefined;
797
825
 
798
826
  /** The generated \`createShardDO\` config — \`.observability()\`, \`.maxRelationKeys()\` and the long-tail \`.ai()\` / \`.kv()\` / … methods pass straight through to it. */
799
827
  type ShardConfig = NonNullable<Parameters<typeof createShardDO>[0]>;
800
- ${K(a)}${t.jurisdiction?`
828
+ ${J(a)}${t.jurisdiction?`
801
829
  // Module scope, so every isolate loading this script (the worker and each Durable
802
830
  // Object class it exports) knows the schema's jurisdiction before a request runs.
803
831
  // \`@lunora/mail\` reads it to pin its shard RPC like every other DO path.
804
832
  declareAppJurisdiction(${JSON.stringify(t.jurisdiction)});
805
833
  `:""}
806
- ${s.join(`
834
+ ${n.join(`
807
835
 
808
- `)}${s.length>0?`
836
+ `)}${n.length>0?`
809
837
 
810
838
  `:""}/** The composed app: a Cloudflare module worker (\`fetch\` / \`scheduled\` / optional \`email\`) plus the \`ShardDO\` class binding. */
811
839
  interface ComposedApp extends LunoraWorker {
@@ -889,16 +917,18 @@ ${t.hasFramework?`
889
917
  `:""}
890
918
  return composed;
891
919
  }
892
- ${R(t)}${x(t.hasStorage)}
920
+ ${R(t)}${A(t.hasStorage)}
893
921
  /** Fan the recorded declarations into the worker-side \`createWorker\` options. */
894
922
  private buildWorkerOptions(env: Env, ${h}): WorkerOptions {
895
923
  const options: WorkerOptions = {
896
- ${J(t).join(`
924
+ ${z(t).join(`
897
925
  `)}
898
926
  };
899
927
 
900
- if (this.adminToken) {
901
- options.adminToken = this.adminToken(env);
928
+ const adminToken = this.adminToken?.(env);
929
+
930
+ if (adminToken !== undefined) {
931
+ options.adminToken = adminToken;
902
932
  }
903
933
 
904
934
  ${o.join(`
@@ -912,7 +942,7 @@ ${o.join(`
912
942
  return options;
913
943
  }
914
944
  }
915
- ${A(t.hasGlobal)}
945
+ ${x(t.hasGlobal)}
916
946
  /**
917
947
  * Shape of the project's root \`lunora.config.*\`.
918
948
  *
@@ -951,5 +981,5 @@ interface LunoraConfig<Env extends object = object> {
951
981
  const defineApp = <Env extends object>(): AppBuilder<Env> => new AppBuilder<Env>();
952
982
 
953
983
  export { AppBuilder, defineApp };
954
- export type { ${V(t)} };
984
+ export type { ${K(t)} };
955
985
  `};export{Z as emitApp};
@@ -1 +1 @@
1
- import"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import"./isD1GlobalTable-udvHAAzD.mjs";import"./json-data-Chfs2Cz5.mjs";import{e as d}from"./shard-26v1MJxM.mjs";import"./shard-runtime-CkTgY8tL.mjs";import"./shared-DnCokNcE.mjs";import"./platform-8oj7iXQy.mjs";import"./schema-BgM8A3XV.mjs";export{d as default};
1
+ import"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import"./isD1GlobalTable-udvHAAzD.mjs";import"./json-data-Chfs2Cz5.mjs";import{e as d}from"./shard-DYYhXxEG.mjs";import"./shard-runtime-BQ6ZNigW.mjs";import"./shared-DnCokNcE.mjs";import"./platform-8oj7iXQy.mjs";import"./schema-BgM8A3XV.mjs";export{d as default};