@lunora/codegen 1.0.0-alpha.246 → 1.0.0-alpha.248

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.
@@ -1,17 +1,17 @@
1
- import{relative as qe,isAbsolute as _e,sep as Ve}from"node:path";import{LunoraError as D}from"@lunora/errors";import{S as Ge}from"./capabilities-DJJWVEtk.mjs";import{p as He}from"./ir-DBSvhNa-.mjs";import{a as h,G as ze,u as Ue,d as Xe}from"./shared-DjUziztz.mjs";const Je=/\.([cm]?)tsx?$/u,Ke=(u,s=[])=>{const t=new Set;for(const a of u.tables)for(const o of Object.values(a.shape)){const i=Ue(o);i.kind==="storage"&&typeof i.bucket=="string"&&i.bucket!==""&&t.add(i.bucket)}for(const a of s)a!==""&&a!=="default"&&t.add(a);return["default",...[...t].toSorted((a,o)=>a.localeCompare(o))]},ot=({agents:u=[],containers:s=[],env:t,hasAccessFacade:a=!1,hasAi:o=!1,hasAnalytics:i=!1,hasBrowser:X=!1,hasVectors:J=!0,hasFlags:K=!1,hasHyperdrive:Y=!1,hasImages:Z=!1,hasKv:ee=!1,hasNotify:te=!1,hasPayments:M=!1,hasPipelines:ae=!1,hasR2sql:re=!1,hasX402:S=!1,identity:d,queues:F=[],schema:W,generatedDirectory:Q="",services:b=[],storageRuleBuckets:oe=[],topics:E=[],useUmbrella:ne=!1,workflows:P=[]}={})=>{const r=Xe(ne),se=Ke(W??{tables:[]},oe).map(e=>JSON.stringify(e)).join(" | "),ie=o?`import type { LunoraAi } from "@lunora/ai";
2
- `:"",de=o?`
3
- readonly ai: LunoraAi;`:"",le=M?`import type { LunoraPayment } from "@lunora/payment";
4
- `:"",ce=M?`
5
- readonly payments: LunoraPayment;`:"",ue=S?`import type { X402Pay } from "@lunora/x402/pay";
6
- `:"",pe=S?`
7
- readonly x402: X402Pay;`:"",ye=s.length>0?`import type { ContainerAccessor } from "@lunora/container";
8
- `:"",me=s.length>0?`
9
- readonly containers: {${s.map(e=>`
10
- readonly ${e.exportName}: ContainerAccessor;`).join("")}
11
- };`:"",j=[...o?[" /** Workers AI binding (the conventional `env.AI`), narrowing `ctx.ai`. */\n readonly AI?: unknown;"]:[],...s.map(e=>(h(e.bindingName,`container binding "${e.bindingName}"`),` /** Durable Object namespace for the \`${e.exportName}\` container. */
1
+ import{relative as Ve,isAbsolute as Ge,sep as He}from"node:path";import{LunoraError as D}from"@lunora/errors";import{S as ze}from"./capabilities-DJJWVEtk.mjs";import{p as Ue}from"./ir-DBSvhNa-.mjs";import{a as h,G as Xe,u as Je,d as Ke}from"./shared-DjUziztz.mjs";const Ye=/\.([cm]?)tsx?$/u,Ze=(u,n=[])=>{const t=new Set;for(const a of u.tables)for(const s of Object.values(a.shape)){const d=Je(s);d.kind==="storage"&&typeof d.bucket=="string"&&d.bucket!==""&&t.add(d.bucket)}for(const a of n)a!==""&&a!=="default"&&t.add(a);return["default",...[...t].toSorted((a,s)=>a.localeCompare(s))]},st=({agents:u=[],containers:n=[],env:t,hasAccessFacade:a=!1,hasAi:s=!1,hasAnalytics:d=!1,hasBrowser:J=!1,hasVectors:K=!0,hasFlags:Y=!1,hasHyperdrive:Z=!1,hasImages:ee=!1,hasKv:te=!1,hasNotify:ae=!1,hasPayments:M=!1,hasPipelines:re=!1,hasR2sql:oe=!1,hasX402:S=!1,identity:l,queues:F=[],schema:W,generatedDirectory:Q="",services:b=[],storageRuleBuckets:ne=[],topics:j=[],useUmbrella:se=!1,workflows:E=[]}={})=>{const r=Ke(se),ie=Ze(W??{tables:[]},ne).map(e=>JSON.stringify(e)).join(" | "),de=s?`import type { LunoraAi } from "@lunora/ai";
2
+ `:"",le=s?`
3
+ readonly ai: LunoraAi;`:"",ce=M?`import type { LunoraPayment } from "@lunora/payment";
4
+ `:"",ue=M?`
5
+ readonly payments: LunoraPayment;`:"",pe=S?`import type { X402Pay } from "@lunora/x402/pay";
6
+ `:"",ye=S?`
7
+ readonly x402: X402Pay;`:"",P=e=>e.sandbox===!0?"SandboxContainerAccessor":"ContainerAccessor",me=[...new Set(n.map(e=>P(e)))].toSorted((e,o)=>e.localeCompare(o)),he=n.length>0?`import type { ${me.join(", ")} } from "@lunora/container";
8
+ `:"",be=n.length>0?`
9
+ readonly containers: {${n.map(e=>`
10
+ readonly ${e.exportName}: ${P(e)};`).join("")}
11
+ };`:"",L=[...s?[" /** Workers AI binding (the conventional `env.AI`), narrowing `ctx.ai`. */\n readonly AI?: unknown;"]:[],...n.map(e=>(h(e.bindingName,`container binding "${e.bindingName}"`),` /** Durable Object namespace for the \`${e.exportName}\` container. */
12
12
  readonly ${e.bindingName}?: unknown;`)),...F.map(e=>(h(e.bindingName,`queue binding "${e.bindingName}"`),` /** Queue producer binding for the \`${e.exportName}\` queue. */
13
13
  readonly ${e.bindingName}?: unknown;`))].join(`
14
- `),he=`
14
+ `),fe=`
15
15
 
16
16
  /**
17
17
  * This project's Cloudflare bindings, as far as codegen can discover them from
@@ -24,26 +24,26 @@ import{relative as qe,isAbsolute as _e,sep as Ve}from"node:path";import{LunoraEr
24
24
  * surface, so treat them as \`Fetcher\`/\`Service<unknown>\` and cast.
25
25
  */
26
26
  export interface CloudflareBindings {
27
- readonly [binding: string]: unknown;${j?`
28
- ${j}`:""}
27
+ readonly [binding: string]: unknown;${L?`
28
+ ${L}`:""}
29
29
  }
30
30
 
31
31
  /** Alias for {@link CloudflareBindings} — the typed shape of \`env\`. */
32
- export type Env = CloudflareBindings;`,n=(e,l,c)=>{const m=Ge.get(e);if(m!==void 0&&m.tier!==c)throw new D("INTERNAL",`@lunora/codegen: capability "${e}" declares tier "${m.tier}" in SERVER_CTX_FIELDS but is emitted onto the "${c}" context — update whichever is wrong.`);return l?m?.field??"":""},f=n("kv",ee,"every"),x=n("analytics",i,"every"),be=n("hyperdrive",Y,"action"),fe=n("browser",X,"action"),xe=n("images",Z,"action"),ge=n("pipelines",ae,"action"),Te=n("r2sql",re,"action"),p=J&&(W?.vectorIndexes.length??0)>0,g=p?' | "vectors"':"",L=p?`
33
- readonly vectors: VectorSearch<VectorIndexName>;`:"",ve=p?`
32
+ export type Env = CloudflareBindings;`,i=(e,o,c)=>{const m=ze.get(e);if(m!==void 0&&m.tier!==c)throw new D("INTERNAL",`@lunora/codegen: capability "${e}" declares tier "${m.tier}" in SERVER_CTX_FIELDS but is emitted onto the "${c}" context — update whichever is wrong.`);return o?m?.field??"":""},f=i("kv",te,"every"),x=i("analytics",d,"every"),xe=i("hyperdrive",Z,"action"),ge=i("browser",J,"action"),Te=i("images",ee,"action"),ve=i("pipelines",re,"action"),we=i("r2sql",oe,"action"),p=K&&(W?.vectorIndexes.length??0)>0,g=p?' | "vectors"':"",q=p?`
33
+ readonly vectors: VectorSearch<VectorIndexName>;`:"",$e=p?`
34
34
  readonly vectors: VectorSearchReader<VectorIndexName>;`:"",ke=p?`import type { VectorSearch, VectorSearchReader } from "${r.server}";
35
35
  import type { VectorIndexName } from "./dataModel.js";
36
36
  `:"",T=a?`
37
37
  /** Verified Cloudflare Access identity — a synchronous facade over the resolved claims (email / groups / hasGroup / claims). Anonymous when no Access token is present. */
38
- readonly access: import("@lunora/cloudflare-access/context").AccessFacade;`:"",v=K?`
38
+ readonly access: import("@lunora/cloudflare-access/context").AccessFacade;`:"",v=Y?`
39
39
  /** Feature-flag evaluation (OpenFeature). Reads are memoized per request; evaluations never throw — a provider error resolves to the supplied default. */
40
- readonly flags: import("${r.flags}").LunoraFlags;`:"",k=te?`
40
+ readonly flags: import("${r.flags}").LunoraFlags;`:"",w=ae?`
41
41
  /** Multi-channel notifications (@lunora/notify): send / chat / inApp / webhook plus the push device sub-facade. Sends are external I/O — confine them to action handlers. */
42
42
  readonly notify: import("@lunora/notify").LunoraNotify;
43
43
  /** Device push sub-facade — the same object as ctx.notify.push (register / send / broadcast). Sends belong in action handlers. */
44
- readonly push: import("@lunora/notify").LunoraPush;`:"",y=P.length>0,we=y?`import type { WorkflowHandle } from "@lunora/workflow";
44
+ readonly push: import("@lunora/notify").LunoraPush;`:"",y=E.length>0,Ie=y?`import type { WorkflowHandle } from "@lunora/workflow";
45
45
  import type * as lunoraWorkflowDefinitions from "../workflows.js";
46
- `:"",$e=y?`
46
+ `:"",Re=y?`
47
47
 
48
48
  /** Params type carried by a \`defineWorkflow\` definition (its phantom \`__params\`). */
49
49
  type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params }
@@ -54,56 +54,56 @@ type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params
54
54
 
55
55
  /** This project's declared workflows, addressable from \`ctx.workflows\` by their \`lunora/workflows.ts\` export name. */
56
56
  export interface LunoraWorkflows {
57
- ${P.map(e=>` get(name: ${JSON.stringify(e.exportName)}): WorkflowHandle<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${e.exportName}>>;`).join(`
57
+ ${E.map(e=>` get(name: ${JSON.stringify(e.exportName)}): WorkflowHandle<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${e.exportName}>>;`).join(`
58
58
  `)}
59
- }`:"",q=y?' | "workflows"':"",_=y?`
60
- readonly workflows: LunoraWorkflows;`:"",V=He(F),w=V.length>0,$=E.length>0,I=[...w?["QueueProducer"]:[],...$?["TopicPublisher"]:[]],Ie=I.length>0?`import type { ${I.join(", ")} } from "@lunora/queue";
59
+ }`:"",_=y?' | "workflows"':"",V=y?`
60
+ readonly workflows: LunoraWorkflows;`:"",G=Ue(F),$=G.length>0,k=j.length>0,I=[...$?["QueueProducer"]:[],...k?["TopicPublisher"]:[]],Be=I.length>0?`import type { ${I.join(", ")} } from "@lunora/queue";
61
61
  import type * as lunoraQueueDefinitions from "../queues.js";
62
- `:"",Re=I.length>0?"\n\n/** Message body type carried by a `defineQueue` / `defineTopic` definition (its phantom `__lunoraBody`). */\ntype QueueBodyOf<Definition> = Definition extends { __lunoraBody?: infer Body } ? (unknown extends Body ? unknown : NonNullable<Body>) : unknown;":"",Be=w?`
62
+ `:"",Oe=I.length>0?"\n\n/** Message body type carried by a `defineQueue` / `defineTopic` definition (its phantom `__lunoraBody`). */\ntype QueueBodyOf<Definition> = Definition extends { __lunoraBody?: infer Body } ? (unknown extends Body ? unknown : NonNullable<Body>) : unknown;":"",Ae=$?`
63
63
 
64
64
  /** This project's declared queues, addressable from \`ctx.queues\` by their \`lunora/queues.ts\` export name. */
65
65
  export interface LunoraQueues {
66
- ${V.map(e=>` readonly ${e.exportName}: QueueProducer<QueueBodyOf<typeof lunoraQueueDefinitions.${e.exportName}>>;`).join(`
66
+ ${G.map(e=>` readonly ${e.exportName}: QueueProducer<QueueBodyOf<typeof lunoraQueueDefinitions.${e.exportName}>>;`).join(`
67
67
  `)}
68
- }`:"",Oe=$?`
68
+ }`:"",Ne=k?`
69
69
 
70
70
  /** This project's declared topics, addressable from \`ctx.topics\` by their \`lunora/queues.ts\` export name. */
71
71
  export interface LunoraTopics {
72
- ${E.map(e=>` readonly ${e.exportName}: TopicPublisher<QueueBodyOf<typeof lunoraQueueDefinitions.${e.exportName}>>;`).join(`
72
+ ${j.map(e=>` readonly ${e.exportName}: TopicPublisher<QueueBodyOf<typeof lunoraQueueDefinitions.${e.exportName}>>;`).join(`
73
73
  `)}
74
- }`:"",Ae=`${Re}${Be}${Oe}`,G=w?`
75
- readonly queues: LunoraQueues;`:"",H=$?`
76
- readonly topics: LunoraTopics;`:"",R=b.length>0,Ne=e=>{if(Q==="")throw new D("INTERNAL","@lunora/codegen: emitServer needs `generatedDirectory` to import an RPC service's types");const l=qe(Q,e);if(_e(l))throw new D("INTERNAL",`@lunora/codegen: an RPC service's entry (${e}) must be on the same drive as the app`);const c=l.split(Ve).join("/").replace(Je,".$1js");return c.startsWith(".")?c:`./${c}`},z=b.filter(e=>e.entrypoint!==void 0),Ce=z.length>0?"ServiceFetcher, ServiceRpc":"ServiceFetcher",De=R?`import type { ${Ce} } from "${r.server}";
77
- ${z.map(e=>`import type * as lunoraService_${e.name} from ${JSON.stringify(Ne(e.main))};
78
- `).join("")}`:"",Me=R?`
74
+ }`:"",Ce=`${Oe}${Ae}${Ne}`,H=$?`
75
+ readonly queues: LunoraQueues;`:"",z=k?`
76
+ readonly topics: LunoraTopics;`:"",R=b.length>0,De=e=>{if(Q==="")throw new D("INTERNAL","@lunora/codegen: emitServer needs `generatedDirectory` to import an RPC service's types");const o=Ve(Q,e);if(Ge(o))throw new D("INTERNAL",`@lunora/codegen: an RPC service's entry (${e}) must be on the same drive as the app`);const c=o.split(He).join("/").replace(Ye,".$1js");return c.startsWith(".")?c:`./${c}`},U=b.filter(e=>e.entrypoint!==void 0),Me=U.length>0?"ServiceFetcher, ServiceRpc":"ServiceFetcher",Se=R?`import type { ${Me} } from "${r.server}";
77
+ ${U.map(e=>`import type * as lunoraService_${e.name} from ${JSON.stringify(De(e.main))};
78
+ `).join("")}`:"",Fe=R?`
79
79
 
80
80
  /** This project's service bindings (\`lunora.config\` \`services\`), addressable from \`ctx.services\` in actions. */
81
81
  export interface LunoraServices {
82
- ${b.map(e=>{h(e.name,`service "${e.name}"`);const l=e.entrypoint===void 0?"ServiceFetcher":`ServiceRpc<typeof lunoraService_${e.name}.${e.entrypoint}>`;return` readonly ${e.name}: ${l};`}).join(`
82
+ ${b.map(e=>{h(e.name,`service "${e.name}"`);const o=e.entrypoint===void 0?"ServiceFetcher":`ServiceRpc<typeof lunoraService_${e.name}.${e.entrypoint}>`;return` readonly ${e.name}: ${o};`}).join(`
83
83
  `)}
84
- }`:"",Se=R?`
85
- readonly services: LunoraServices;`:"",B=u.length>0,Fe=B?`import type { AgentHandle } from "@lunora/agent";
86
- `:"",We=B?`
84
+ }`:"",We=R?`
85
+ readonly services: LunoraServices;`:"",B=u.length>0,Qe=B?`import type { AgentHandle } from "@lunora/agent";
86
+ `:"",je=B?`
87
87
 
88
88
  /** This project's declared agents, addressable from \`ctx.agents\` by their \`lunora/agents.ts\` export name. */
89
89
  export interface LunoraAgents {
90
90
  ${u.map(e=>(h(e.exportName,`agent export "${e.exportName}"`),` readonly ${e.exportName}: AgentHandle;`)).join(`
91
91
  `)}
92
- }`:"",U=B?`
93
- readonly agents: LunoraAgents;`:"",Qe=d?`import type { InferIdentity } from "${r.server}";
92
+ }`:"",X=B?`
93
+ readonly agents: LunoraAgents;`:"",Ee=l?`import type { InferIdentity } from "${r.server}";
94
94
  import type * as lunoraIdentityContract from "../identity.js";
95
- `:"",Ee=d?`
95
+ `:"",Pe=l?`
96
96
 
97
97
  /** This app's declared identity claim contract (\`defineIdentity\` in \`lunora/identity.ts\`) — the typed shape of \`ctx.auth.getIdentity()\`, the RLS policy \`ctx.auth.identity\`, and the \`authorizeShard\`/\`authorizeFanOut\` identity argument. */
98
- export type Identity = InferIdentity<typeof lunoraIdentityContract.${d.exportName}>;
98
+ export type Identity = InferIdentity<typeof lunoraIdentityContract.${l.exportName}>;
99
99
 
100
100
  /** \`ctx.auth\` narrowed so \`getIdentity()\` resolves the declared {@link Identity} contract instead of the untyped claim bag. */
101
- type NarrowedAuth = Omit<QueryCtxBase["auth"], "getIdentity"> & { getIdentity: () => Promise<Identity | null> };`:"",O=d?' | "auth"':"",A=d?`
102
- readonly auth: NarrowedAuth;`:"",Pe=d?", Identity":"",je=t?`import type * as lunoraEnvContract from "../env.js";
103
- `:"",Le=t?`
101
+ type NarrowedAuth = Omit<QueryCtxBase["auth"], "getIdentity"> & { getIdentity: () => Promise<Identity | null> };`:"",O=l?' | "auth"':"",A=l?`
102
+ readonly auth: NarrowedAuth;`:"",Le=l?", Identity":"",qe=t?`import type * as lunoraEnvContract from "../env.js";
103
+ `:"",_e=t?`
104
104
 
105
105
  /** This app's declared env contract (\`defineEnv\` in \`lunora/env.ts\`) — the validated, coercion-aware shape of \`ctx.env\`. */
106
- export type LunoraEnv = ReturnType<typeof lunoraEnvContract.${t.exportName}>;`:"",N=t?' | "env"':"",C=t?"\n /** Validated, typed environment declared by `defineEnv` in `lunora/env.ts` — parsed & coercion-aware config values (`ctx.env.STRIPE_KEY`); a missing or invalid value throws at read time. */\n readonly env: LunoraEnv;":"";return`${ze}import { createPolicyDsl, defineMutator as defineMutatorBase, initLunora, v as vBase } from "${r.server}";
106
+ export type LunoraEnv = ReturnType<typeof lunoraEnvContract.${t.exportName}>;`:"",N=t?' | "env"':"",C=t?"\n /** Validated, typed environment declared by `defineEnv` in `lunora/env.ts` — parsed & coercion-aware config values (`ctx.env.STRIPE_KEY`); a missing or invalid value throws at read time. */\n readonly env: LunoraEnv;":"";return`${Xe}import { createPolicyDsl, defineMutator as defineMutatorBase, initLunora, v as vBase } from "${r.server}";
107
107
  import type {
108
108
  ActionBuilder,
109
109
  ActionCtx as ActionCtxBase,
@@ -160,7 +160,7 @@ export type {
160
160
  } from "${r.serverDataModel}";
161
161
 
162
162
  import type { DataModel, Doc, GeoIndexNamesByTable, Id as IdOfTable, IndexNamesByTable, Insert, InsertModel, RankIndexNamesByTable, Relations, SearchIndexNamesByTable, TableName } from "./dataModel.js";
163
- ${ke}${ie}${le}${ue}${ye}${we}${Ie}${De}${Fe}${Qe}${je}
163
+ ${ke}${de}${ce}${pe}${he}${Ie}${Be}${Se}${Qe}${Ee}${qe}
164
164
  export type { AppTableName, DataModel, Doc, Id, TableName } from "./dataModel.js";
165
165
 
166
166
  /**
@@ -220,7 +220,7 @@ export interface OrmWriter extends OrmReader {
220
220
  }
221
221
 
222
222
  /** Storage buckets this schema declares (\`v.storage("name")\`), narrowing \`ctx.storage.bucket(name)\`. */
223
- export type StorageBucketName = ${se};${he}${$e}${Ae}${Me}${We}${Ee}${Le}
223
+ export type StorageBucketName = ${ie};${fe}${Re}${Ce}${Fe}${je}${Pe}${_e}
224
224
 
225
225
  /**
226
226
  * Project-typed contexts. The base contexts from \`@lunora/server\` are
@@ -286,19 +286,19 @@ type TypedAsId = <T extends string>(tableName: AsIdTable<T>, id: string) => IdOf
286
286
  export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"${g}${O}${N}> {
287
287
  readonly db: Omit<DatabaseReader, "asId" | "query" | "get"> & DatabaseReaderFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
288
288
  readonly orm: OrmReader;
289
- readonly storage: ReadOnlyStorage<StorageBucketName>;${ve}${T}${f}${v}${k}${x}${C}${A}
289
+ readonly storage: ReadOnlyStorage<StorageBucketName>;${$e}${T}${f}${v}${w}${x}${C}${A}
290
290
  }
291
291
 
292
- export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${g}${q}${O}${N}> {
292
+ export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${g}${_}${O}${N}> {
293
293
  readonly db: Omit<DatabaseWriter, "asId" | "query" | "get"> & DatabaseWriterFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
294
294
  readonly orm: OrmWriter;
295
- readonly storage: MutationStorage<StorageBucketName>;${L}${T}${f}${v}${k}${x}${C}${_}${G}${H}${U}${A}
295
+ readonly storage: MutationStorage<StorageBucketName>;${q}${T}${f}${v}${w}${x}${C}${V}${H}${z}${X}${A}
296
296
  }
297
297
 
298
- export interface ActionCtx extends Omit<ActionCtxBase, "db" | "storage"${g}${q}${O}${N}> {
298
+ export interface ActionCtx extends Omit<ActionCtxBase, "db" | "storage"${g}${_}${O}${N}> {
299
299
  readonly db: Omit<DatabaseWriter, "asId" | "query" | "get"> & DatabaseWriterFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
300
300
  readonly orm: OrmWriter;
301
- readonly storage: StorageBase<StorageBucketName>;${L}${T}${de}${ce}${pe}${me}${f}${v}${k}${be}${fe}${xe}${x}${ge}${Te}${Se}${C}${_}${G}${H}${U}${A}
301
+ readonly storage: StorageBase<StorageBucketName>;${q}${T}${le}${ue}${ye}${be}${f}${v}${w}${xe}${ge}${Te}${x}${ve}${we}${We}${C}${V}${H}${z}${X}${A}
302
302
  }
303
303
 
304
304
  /**
@@ -356,7 +356,7 @@ export const defineMutator = defineMutatorBase as unknown as <Args extends Recor
356
356
  * Runtime-identical to \`@lunora/server\`'s \`definePolicy\`; only the types narrow,
357
357
  * so the \`rls()\` chain discovers a policy authored either way the same.
358
358
  */
359
- export const definePolicy = createPolicyDsl<DataModel, Relations${Pe}>();
359
+ export const definePolicy = createPolicyDsl<DataModel, Relations${Le}>();
360
360
 
361
361
  /**
362
362
  * The validator builder \`v\`, with \`v.id(...)\` constrained to THIS schema's
@@ -373,4 +373,4 @@ export const definePolicy = createPolicyDsl<DataModel, Relations${Pe}>();
373
373
  export const v = vBase as unknown as Omit<typeof vBase, "id"> & {
374
374
  id: <T extends TableName>(table: T) => ColumnValidator<IdOfTable<T>, IdOfTable<T>>;
375
375
  };
376
- `};export{ot as default};
376
+ `};export{st as default};
@@ -1 +1 @@
1
- import"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import"./isD1GlobalTable-udvHAAzD.mjs";import"./ir-DBSvhNa-.mjs";import"./json-data-Chfs2Cz5.mjs";import{e as f}from"./shard-D6EZdlSg.mjs";import"./shard-runtime-D9GRosnD.mjs";import"./shared-DjUziztz.mjs";export{f as default};
1
+ import"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import"./isD1GlobalTable-udvHAAzD.mjs";import"./ir-DBSvhNa-.mjs";import"./json-data-Chfs2Cz5.mjs";import{e as f}from"./shard-CFSbecwR.mjs";import"./shard-runtime-CT_oddIR.mjs";import"./shared-DjUziztz.mjs";export{f as default};
@@ -1,4 +1,4 @@
1
- import{LunoraError as jt}from"@lunora/errors";import{serializeSchemaSnapshot as Ht,hashSchemaSnapshot as Vt}from"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import{isHyperdriveGlobalTable as Kt,isD1GlobalTable as Gt}from"./isD1GlobalTable-udvHAAzD.mjs";import{p as Qt,i as zt}from"./ir-DBSvhNa-.mjs";import{r as l}from"./json-data-Chfs2Cz5.mjs";import{r as q,e as Xt,a as Jt,b as Yt,c as Zt,d as er,f as tr,g as rr,h as ar,i as nr,j as sr,k as or,l as ir,m as dr,n as cr,o as lr,p as hr,q as ur,s as pr,t as mr,u as gr,v as br,w as fr,x as wr,y as yr,z as vr,A as kr}from"./shard-runtime-D9GRosnD.mjs";import{u as re,i as Sr,G as Rr,d as xr}from"./shared-DjUziztz.mjs";const Ar=` /**
1
+ import{LunoraError as jt}from"@lunora/errors";import{serializeSchemaSnapshot as Ht,hashSchemaSnapshot as Vt}from"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import{isHyperdriveGlobalTable as Kt,isD1GlobalTable as Gt}from"./isD1GlobalTable-udvHAAzD.mjs";import{p as Qt,i as zt}from"./ir-DBSvhNa-.mjs";import{r as l}from"./json-data-Chfs2Cz5.mjs";import{r as q,e as Xt,a as Jt,b as Yt,c as Zt,d as er,f as tr,g as rr,h as ar,i as nr,j as sr,k as or,l as ir,m as dr,n as cr,o as lr,p as hr,q as ur,s as pr,t as mr,u as gr,v as br,w as fr,x as wr,y as yr,z as vr,A as kr}from"./shard-runtime-CT_oddIR.mjs";import{u as re,i as Sr,G as Rr,d as xr}from"./shared-DjUziztz.mjs";const Ar=` /**
2
2
  * The bare writer every admin/maintenance entry point writes through.
3
3
  *
4
4
  * Admin and maintenance writes go through the SAME reactive-cache hooks as a
@@ -229,7 +229,7 @@ ${m()}
229
229
  // ActionCtx-only helpers (external, non-deterministic I/O): constructed
230
230
  // and attached only for an \`action\` so query/mutation ctx never carry them.
231
231
  if (isAction) {
232
- ${a}${r.map(v=>` ctx.${v} = ${v};`).join(`
232
+ ${a.replaceAll(/^(?=.)/gmu," ")}${r.map(v=>` ctx.${v} = ${v};`).join(`
233
233
  `)}
234
234
  }
235
235
  `:"";return` private buildCtx(options: { bookmarks?: DispatchBookmark; functionPath?: string; headroom?: TransactionHeadroomTracker; identity?: SubscriptionIdentity; kind?: "query"; onRead?: (table: string, idOrScan?: string) => void; onReadRange?: (range: KeyRange) => void; scope?: QueryReadScope; trusted?: boolean } = {}): unknown {
@@ -1,4 +1,4 @@
1
- import{s as h}from"./ir-DBSvhNa-.mjs";import{r as g}from"./json-data-Chfs2Cz5.mjs";import{a,G as d}from"./shared-DjUziztz.mjs";const w=e=>e?{importFragment:"serveRelationFanout, ",override:`
1
+ import{s as h}from"./ir-DBSvhNa-.mjs";import{r as f}from"./json-data-Chfs2Cz5.mjs";import{a,G as p}from"./shared-DjUziztz.mjs";const w=e=>e?{importFragment:"serveRelationFanout, ",override:`
2
2
  protected override async runRelationFanoutRead(functionPath: string, args: Record<string, unknown>): Promise<unknown> {
3
3
  this.ensureMigrated();
4
4
 
@@ -23,12 +23,12 @@ import{s as h}from"./ir-DBSvhNa-.mjs";import{r as g}from"./json-data-Chfs2Cz5.mj
23
23
  telemetry: { metrics, trace },
24
24
  });
25
25
  `,configField:`
26
- ai?: (env: Record<string, unknown>) => AiBindingLike;`}:{build:"",configField:""},l=(e,t,n,{cast:r="",sync:o=[]}={})=>{const i=n.map(u=>` ${u}: ${o.includes(u)?"":"async "}() => {
26
+ ai?: (env: Record<string, unknown>) => AiBindingLike;`}:{build:"",configField:""},u=(e,t,n,{cast:r="",sync:o=[]}={})=>{const l=n.map(d=>` ${d}: ${o.includes(d)?"":"async "}() => {
27
27
  ${t}
28
28
  },`).join(`
29
29
  `);return`
30
30
  const ${e} = {
31
- ${i}
31
+ ${l}
32
32
  }${r};
33
33
  `},c={build:"",configField:"",contextField:"",importLines:[],stub:""},S=e=>e.size===0?{configField:"",constant:"",override:""}:{configField:"\n /** The `ShardRegistryDO` namespace (typically `env.SHARD_REGISTRY`). This shard registers its key for each `.shardBy()` table it writes, so cross-shard export, sync and migrations reach it. */\n shardRegistry?: (env: Record<string, unknown>) => unknown;",constant:`
34
34
  /** The \`.shardBy()\` tables this shard registers with the shard registry when it writes them. */
@@ -53,32 +53,32 @@ const SHARDED_TABLES: ReadonlySet<string> = new Set([${[...e].map(t=>JSON.string
53
53
  ]);
54
54
  `,configField:`
55
55
  kv?: (env: Record<string, unknown>) => KVNamespaceLike;`,contextField:`
56
- kv,`,importLines:['import type { Kv, KVNamespaceLike } from "@lunora/bindings/kv";','import { createKv } from "@lunora/bindings/kv";'],stub:l("kvStub: Kv",'throw new Error("ctx.kv: no KV binding found. Add a \\`kv_namespaces\\` binding (env.KV) to wrangler.jsonc, or pass \\`kv\\` to createShardDO().");',["delete","get","getRaw","getWithMetadata","list","put"])}:c,L=(e,t)=>e?{build:`
56
+ kv,`,importLines:['import type { Kv, KVNamespaceLike } from "@lunora/bindings/kv";','import { createKv } from "@lunora/bindings/kv";'],stub:u("kvStub: Kv",'throw new Error("ctx.kv: no KV binding found. Add a \\`kv_namespaces\\` binding (env.KV) to wrangler.jsonc, or pass \\`kv\\` to createShardDO().");',["delete","get","getRaw","getWithMetadata","list","put"])}:c,$=(e,t)=>e?{build:`
57
57
  const flags: import("${t}").LunoraFlags = createFlags(flagsConfig, env, {
58
58
  provider: () => config.flags?.(env),
59
59
  targetingKey: () => flagsConfig.identify?.({ identity: identity ?? null, userId: userId ?? null }),
60
60
  });
61
61
  `,configField:`
62
62
  flags?: (env: Record<string, unknown>) => import("${t}").Provider;`,contextField:`
63
- flags,`,importLines:[`import { createFlags } from "${t}";`,'import flagsConfig from "../flags.js";'],stub:""}:c,$=e=>e?{build:`
63
+ flags,`,importLines:[`import { createFlags } from "${t}";`,'import flagsConfig from "../flags.js";'],stub:""}:c,L=e=>e?{build:`
64
64
  const { notify, push } = createNotify(notifyConfig, env, { log, metrics });
65
65
  `,configField:"",contextField:`
66
66
  notify,
67
67
  push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:c,A=e=>e?{build:`
68
68
  const envConfig = lunoraEnvContract.${e.exportName}(env);
69
69
  `,configField:"",contextField:`
70
- env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:c,F=e=>e?{build:`
70
+ env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:c,C=e=>e?{build:`
71
71
  const access = accessFacade(identity, userId);
72
72
  `,configField:"",contextField:`
73
- access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:c,C=(e,t,n)=>{if(!t)return{constant:"",evaluateOverride:"",subscriptionOverride:""};const r=s=>`
73
+ access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:c,F=(e,t,n)=>{if(!t)return{constant:"",evaluateOverride:"",subscriptionOverride:""};const r=s=>`
74
74
  const env = (this.env ?? {}) as Record<string, unknown>;
75
75
  const flags: import("${n}").LunoraFlags = createFlags(flagsConfig, env, {
76
76
  provider: () => config.flags?.(env),
77
77
  targetingKey: ${s},
78
78
  });`,o=`
79
79
  /** Statically-discovered feature flags (\`ctx.flags.<type>("key")\` reads) served via \`__lunora_admin__:listFlags\` + the reactive \`__lunora_flags__:\` channel. */
80
- const LUNORA_FLAG_KEYS = ${g(e,'ReadonlyArray<{ key: string; type: "boolean" | "number" | "object" | "string" }>')};
81
- `,i=`
80
+ const LUNORA_FLAG_KEYS = ${f(e,'ReadonlyArray<{ key: string; type: "boolean" | "number" | "object" | "string" }>')};
81
+ `,l=`
82
82
  protected override async evaluateFlags(context?: Record<string, unknown>): Promise<FlagsResult> {${r("undefined")}
83
83
  const evalContext = context as import("${n}").EvaluationContext | undefined;
84
84
  const evaluations: FlagsResult["flags"] = [];
@@ -99,7 +99,7 @@ const LUNORA_FLAG_KEYS = ${g(e,'ReadonlyArray<{ key: string; type: "boolean" | "
99
99
 
100
100
  return { configured: true, flags: evaluations };
101
101
  }
102
- `,u=`
102
+ `,d=`
103
103
  protected override runFlagSubscriptionRead(_functionPath: string, args: Record<string, unknown>, identity?: SubscriptionIdentity): Promise<unknown> {${r("() => flagsConfig.identify?.({ identity: identity?.identity ?? null, userId: identity?.userId ?? null })")}
104
104
  const key = typeof args.key === "string" ? args.key : "";
105
105
 
@@ -132,25 +132,25 @@ const LUNORA_FLAG_KEYS = ${g(e,'ReadonlyArray<{ key: string; type: "boolean" | "
132
132
 
133
133
  return flags.boolean(key, typeof args.default === "boolean" ? args.default : false, context);
134
134
  }
135
- `;return{constant:o,evaluateOverride:i,subscriptionOverride:u}},_=e=>e?{build:`
135
+ `;return{constant:o,evaluateOverride:l,subscriptionOverride:d}},E=e=>e?{build:`
136
136
  const analyticsBinding = config.analytics?.(env) ?? (env as Record<string, unknown>).ANALYTICS;
137
137
  const analytics: AnalyticsClient = analyticsBinding ? createAnalytics(analyticsBinding as AnalyticsEngineDatasetLike) : analyticsStub;
138
138
  `,configField:`
139
139
  analytics?: (env: Record<string, unknown>) => AnalyticsEngineDatasetLike;`,contextField:`
140
- analytics,`,importLines:['import type { AnalyticsClient, AnalyticsEngineDatasetLike } from "@lunora/bindings/analytics";','import { createAnalytics } from "@lunora/bindings/analytics";'],stub:l("analyticsStub: AnalyticsClient",'throw new Error("ctx.analytics: no Analytics Engine binding found. Add an \\`analytics_engine_datasets\\` binding (env.ANALYTICS) to wrangler.jsonc, or pass \\`analytics\\` to createShardDO().");',["track","writeDataPoint"],{sync:["track","writeDataPoint"]})}:c,E=e=>e?{build:`
140
+ analytics,`,importLines:['import type { AnalyticsClient, AnalyticsEngineDatasetLike } from "@lunora/bindings/analytics";','import { createAnalytics } from "@lunora/bindings/analytics";'],stub:u("analyticsStub: AnalyticsClient",'throw new Error("ctx.analytics: no Analytics Engine binding found. Add an \\`analytics_engine_datasets\\` binding (env.ANALYTICS) to wrangler.jsonc, or pass \\`analytics\\` to createShardDO().");',["track","writeDataPoint"],{sync:["track","writeDataPoint"]})}:c,_=e=>e?{build:`
141
141
  const imagesBinding = config.images?.(env) ?? (env as Record<string, unknown>).IMAGES;
142
142
  const images: Images = imagesBinding ? createImages({ binding: imagesBinding as ImagesBindingLike }) : imagesStub;
143
143
  `,configField:`
144
144
  images?: (env: Record<string, unknown>) => ImagesBindingLike;`,contextField:`
145
- images,`,importLines:['import type { Images, ImagesBindingLike } from "@lunora/bindings/images";','import { createImages } from "@lunora/bindings/images";'],stub:l("imagesStub: Images",'throw new Error("ctx.images: no Images binding found. Add an \\`images\\` binding (env.IMAGES) to wrangler.jsonc, or pass \\`images\\` to createShardDO().");',["info","transform"])}:c,O=e=>e?{build:`
145
+ images,`,importLines:['import type { Images, ImagesBindingLike } from "@lunora/bindings/images";','import { createImages } from "@lunora/bindings/images";'],stub:u("imagesStub: Images",'throw new Error("ctx.images: no Images binding found. Add an \\`images\\` binding (env.IMAGES) to wrangler.jsonc, or pass \\`images\\` to createShardDO().");',["info","transform"])}:c,O=e=>e?{build:`
146
146
  const sql: SqlClient = config.sql ? config.sql(env) : sqlStub;
147
147
  `,configField:`
148
148
  sql?: (env: Record<string, unknown>) => SqlClient;`,contextField:`
149
- sql,`,importLines:['import type { SqlClient } from "@lunora/hyperdrive";'],stub:l("sqlStub: SqlClient",'throw new Error("ctx.sql: provide a \\`sql\\` config thunk that builds a SqlClient from your driver, e.g. \\`sql: (env) => fromPostgresJs(postgres(env.HYPERDRIVE.connectionString))\\`.");',["query"])}:c,P=e=>e?{build:`
149
+ sql,`,importLines:['import type { SqlClient } from "@lunora/hyperdrive";'],stub:u("sqlStub: SqlClient",'throw new Error("ctx.sql: provide a \\`sql\\` config thunk that builds a SqlClient from your driver, e.g. \\`sql: (env) => fromPostgresJs(postgres(env.HYPERDRIVE.connectionString))\\`.");',["query"])}:c,P=e=>e?{build:`
150
150
  const browser: Browser = config.browser ? config.browser(env) : browserStub;
151
151
  `,configField:`
152
152
  browser?: (env: Record<string, unknown>) => Browser;`,contextField:`
153
- browser,`,importLines:['import type { Browser } from "@lunora/browser";'],stub:l("browserStub: Browser","throw new Error(\"ctx.browser: provide a \\`browser\\` config thunk, e.g. \\`browser: (env) => createBrowser({ binding: env.BROWSER, launch })\\` with \\`import { launch } from '@cloudflare/playwright'\\`. Session reuse (connect/sessions) additionally needs those two exports passed the same way.\");",["cancelCrawl","connect","content","crawl","crawlResult","launch","pdf","quickAction","scrape","screenshot","sessions"])}:c,q=e=>e?{build:`
153
+ browser,`,importLines:['import type { Browser } from "@lunora/browser";'],stub:u("browserStub: Browser","throw new Error(\"ctx.browser: provide a \\`browser\\` config thunk, e.g. \\`browser: (env) => createBrowser({ binding: env.BROWSER, launch })\\` with \\`import { launch } from '@cloudflare/playwright'\\`. Session reuse (connect/sessions) additionally needs those two exports passed the same way.\");",["cancelCrawl","connect","content","crawl","crawlResult","launch","pdf","quickAction","scrape","screenshot","sessions"])}:c,q=e=>e?{build:`
154
154
  const r2sqlEnv = env as Record<string, unknown>;
155
155
  const r2sqlAccountId = (r2sqlEnv.R2_SQL_ACCOUNT_ID ?? r2sqlEnv.CLOUDFLARE_ACCOUNT_ID) as string | undefined;
156
156
  const r2sqlToken = r2sqlEnv.R2_SQL_TOKEN as string | undefined;
@@ -161,18 +161,19 @@ const LUNORA_FLAG_KEYS = ${g(e,'ReadonlyArray<{ key: string; type: "boolean" | "
161
161
  ? createR2Sql({ accountId: r2sqlAccountId, apiToken: r2sqlToken, bucket: r2sqlBucket })
162
162
  : r2sqlStub;
163
163
  `,configField:`
164
- r2sql?: (env: Record<string, unknown>) => R2SqlClient;`,contextField:"",importLines:['import type { R2SqlClient } from "@lunora/bindings/r2sql";','import { createR2Sql } from "@lunora/bindings/r2sql";'],stub:l("r2sqlStub: R2SqlClient",'throw new Error("ctx.r2sql: no R2 SQL credentials found. Set \\`R2_SQL_TOKEN\\`, \\`R2_SQL_ACCOUNT_ID\\` (or \\`CLOUDFLARE_ACCOUNT_ID\\`), and \\`R2_SQL_BUCKET\\` in your env/.dev.vars, or pass an \\`r2sql\\` config thunk to createShardDO().");',["describe","explain","from","query","showDatabases","showTables"],{sync:["from"]})}:c,I=e=>e?{build:`
164
+ r2sql?: (env: Record<string, unknown>) => R2SqlClient;`,contextField:"",importLines:['import type { R2SqlClient } from "@lunora/bindings/r2sql";','import { createR2Sql } from "@lunora/bindings/r2sql";'],stub:u("r2sqlStub: R2SqlClient",'throw new Error("ctx.r2sql: no R2 SQL credentials found. Set \\`R2_SQL_TOKEN\\`, \\`R2_SQL_ACCOUNT_ID\\` (or \\`CLOUDFLARE_ACCOUNT_ID\\`), and \\`R2_SQL_BUCKET\\` in your env/.dev.vars, or pass an \\`r2sql\\` config thunk to createShardDO().");',["describe","explain","from","query","showDatabases","showTables"],{sync:["from"]})}:c,I=e=>e?{build:`
165
165
  const pipelinesBinding = config.pipelines?.(env) ?? (env as Record<string, unknown>).PIPELINES;
166
166
  const pipelines: PipelineClient = pipelinesBinding ? createPipelines({ binding: pipelinesBinding as PipelineBindingLike }) : pipelinesStub;
167
167
  `,configField:`
168
- pipelines?: (env: Record<string, unknown>) => PipelineBindingLike;`,contextField:"",importLines:['import type { PipelineBindingLike, PipelineClient } from "@lunora/bindings/pipelines";','import { createPipelines } from "@lunora/bindings/pipelines";'],stub:l("pipelinesStub: PipelineClient",'throw new Error("ctx.pipelines: no Pipelines binding found. Add a \\`pipelines\\` binding (env.PIPELINES) to wrangler.jsonc, or pass \\`pipelines\\` to createShardDO().");',["send"])}:c,B=(e,t)=>{if(e.length===0)return"";const n=t?`, ${JSON.stringify(t)}`:"",r=e.map(i=>(a(i.exportName,`container export "${i.exportName}"`),a(i.className,`container class "${i.className}"`),`/** Container DO for the \`${i.exportName}\` definition (binding \`${i.bindingName}\`). */
169
- export class ${i.className} extends LunoraContainer {
170
- public constructor(ctx: ConstructorParameters<typeof LunoraContainer>[0], env: Record<string, unknown>) {
168
+ pipelines?: (env: Record<string, unknown>) => PipelineBindingLike;`,contextField:"",importLines:['import type { PipelineBindingLike, PipelineClient } from "@lunora/bindings/pipelines";','import { createPipelines } from "@lunora/bindings/pipelines";'],stub:u("pipelinesStub: PipelineClient",'throw new Error("ctx.pipelines: no Pipelines binding found. Add a \\`pipelines\\` binding (env.PIPELINES) to wrangler.jsonc, or pass \\`pipelines\\` to createShardDO().");',["send"])}:c,B=(e,t)=>{if(e.length===0)return"";const n=t?`, ${JSON.stringify(t)}`:"",r=e.map(i=>{a(i.exportName,`container export "${i.exportName}"`),a(i.className,`container class "${i.className}"`);const m=i.sandbox===!0?"LunoraSandboxContainer":"LunoraContainer";return`/** Container DO for the \`${i.exportName}\` definition (binding \`${i.bindingName}\`). */
169
+ export class ${i.className} extends ${m} {
170
+ public constructor(ctx: ConstructorParameters<typeof ${m}>[0], env: Record<string, unknown>) {
171
171
  super(ctx, env, ${i.exportName}, "${i.exportName}"${n});
172
172
  }
173
173
  }
174
- `)).join(`
175
- `),o=e.map(i=>i.exportName).join(", ");return`${d}/**
174
+ `}).join(`
175
+ `),o=e.map(i=>i.exportName).join(", "),l=e.some(i=>i.sandbox===!0),d=e.some(i=>i.sandbox!==!0)?`import { LunoraContainer } from "@lunora/container/do";
176
+ `:"";return`${p}/**
176
177
  * Container-enabled Durable Object classes for the containers declared in
177
178
  * \`lunora/containers.ts\`. Re-export them from your worker entry — wrangler
178
179
  * requires each \`containers[].class_name\` to be exported by the worker:
@@ -184,12 +185,18 @@ export class ${i.className} extends LunoraContainer {
184
185
  * \`handle.egress\` controls) routes container outbound traffic through this
185
186
  * WorkerEntrypoint, so it too must be exported by the deployed worker.
186
187
  */
187
- import { LunoraContainer } from "@lunora/container/do";
188
-
188
+ ${d}${l?`import { LunoraSandboxContainer } from "@lunora/container/sandbox";
189
+ `:""}
189
190
  import { ${o} } from "../containers.js";
190
191
 
191
192
  export { ContainerProxy } from "@lunora/container/do";
192
-
193
+ ${l?`
194
+ /**
195
+ * \`DirectoryBackup\` and \`S3Mount\` route a \`sandbox: true\` container's storage
196
+ * traffic through these WorkerEntrypoints, so the deployed worker must export them.
197
+ */
198
+ export { DirectoryBackupGateway, S3Gateway } from "@lunora/container/sandbox";
199
+ `:""}
193
200
  ${r}`},W=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const r of e)a(r.exportName,`container export "${r.exportName}"`),a(r.bindingName,`container binding "${r.bindingName}"`);const n=e.map(r=>{const o=r.schedulingPolicy!==void 0||r.maxInstances===void 0?"":`, maxInstances: ${String(r.maxInstances)}`;return` { binding: "${r.bindingName}", exportName: "${r.exportName}"${o} },`}).join(`
194
201
  `);return{build:`
195
202
  const containers = createContainerContext(env, LUNORA_CONTAINERS, ${t?JSON.stringify(t):"undefined"}, this.getCurrentTraceparent(), this.getCurrentSampleErrors());
@@ -206,7 +213,7 @@ export class ${r.className} extends LunoraWorkflow<WorkflowParamsOf<typeof ${r.e
206
213
  }
207
214
  }
208
215
  `)).join(`
209
- `),n=e.map(r=>r.exportName).join(", ");return`${d}/**
216
+ `),n=e.map(r=>r.exportName).join(", ");return`${p}/**
210
217
  * WorkflowEntrypoint classes for the workflows declared in
211
218
  * \`lunora/workflows.ts\`. Re-export them from your worker entry — wrangler
212
219
  * requires each \`workflows[].class_name\` to be exported by the worker:
@@ -227,21 +234,21 @@ type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params
227
234
  /** Output type carried by a \`defineWorkflow\` definition (its phantom \`__output\`), so each entrypoint keeps the authored return type. */
228
235
  type WorkflowOutputOf<Definition> = Definition extends { __output?: infer Output } ? Output : unknown;
229
236
 
230
- ${t}`},T=e=>{if(e.length===0)return"";const n=e.filter(s=>s.voice).length>0,r=e.map(s=>{a(s.exportName,`agent export "${s.exportName}"`),a(s.className,`agent class "${s.className}"`);const p=`/** WorkflowEntrypoint for the \`${s.exportName}\` agent, reached as \`ctx.exports.${s.className}\`. */
237
+ ${t}`},T=e=>{if(e.length===0)return"";const n=e.filter(s=>s.voice).length>0,r=e.map(s=>{a(s.exportName,`agent export "${s.exportName}"`),a(s.className,`agent class "${s.className}"`);const g=`/** WorkflowEntrypoint for the \`${s.exportName}\` agent, reached as \`ctx.exports.${s.className}\`. */
231
238
  export class ${s.className} extends LunoraWorkflow<AgentRunInput, AgentRunResult> {
232
239
  public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
233
240
  super(ctx, env, compileAgentWorkflow(${s.exportName}, "${s.exportName}"), "${s.exportName}");
234
241
  }
235
242
  }
236
- `;if(!s.voice)return p;const m=s.voiceClassName??"",y=s.voiceBindingName??"";a(m,`agent voice class "${m}"`);const b=`
237
- /** Voice-session Durable Object for the \`${s.exportName}\` agent (binding \`${y}\`). */
238
- export class ${m} extends VoiceSessionDO {
243
+ `;if(!s.voice)return g;const i=s.voiceClassName??"",m=s.voiceBindingName??"";a(i,`agent voice class "${i}"`);const b=`
244
+ /** Voice-session Durable Object for the \`${s.exportName}\` agent (binding \`${m}\`). */
245
+ export class ${i} extends VoiceSessionDO {
239
246
  public constructor(ctx: ConstructorParameters<typeof VoiceSessionDO>[0], env: Record<string, unknown>) {
240
247
  super(ctx, env, ${s.exportName}, "${s.exportName}");
241
248
  }
242
249
  }
243
- `;return`${p}${b}`}).join(`
244
- `),o=e.map(s=>s.exportName).join(", ");return`${d}/**
250
+ `;return`${g}${b}`}).join(`
251
+ `),o=e.map(s=>s.exportName).join(", ");return`${p}/**
245
252
  * WorkflowEntrypoint classes for the agents declared in \`lunora/agents.ts\`.
246
253
  * Each \`defineAgent\` compiles a replay-safe tool-loop onto a Cloudflare
247
254
  * Workflow. Re-export them from your worker entry — wrangler requires each
@@ -256,7 +263,7 @@ import type { AgentRunInput, AgentRunResult } from "@lunora/agent";
256
263
  import { ${o} } from "../agents.js";
257
264
 
258
265
  ${r}`},j=e=>{const t=e.filter(o=>o.mode==="push");if(t.length===0)return"";for(const o of t)a(o.exportName,`queue export "${o.exportName}"`);const n=t.map(o=>o.exportName).join(", "),r=t.map(o=>` ${JSON.stringify(o.name)}: { binding: ${JSON.stringify(o.bindingName)}, definition: ${o.exportName}, exportName: ${JSON.stringify(o.exportName)} },`).join(`
259
- `);return`${d}/**
266
+ `);return`${p}/**
260
267
  * Push-consumer registry for the queues declared in \`lunora/queues.ts\`. The
261
268
  * composed worker's \`queue(batch, env, ctx)\` entry routes each delivered batch
262
269
  * by \`batch.queue\` to the matching \`defineQueue\` handler. Wired automatically
@@ -288,7 +295,7 @@ ${t}
288
295
  const LUNORA_QUEUES: ReadonlyArray<QueueBindingSpec> = [
289
296
  ${t}
290
297
  ];
291
- `}},Q=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};const n=e.map(r=>{a(r.exportName,`topic export "${r.exportName}"`);const o=h(t,r.exportName).map(i=>`{ binding: "${i.bindingName}", exportName: "${i.exportName}" }`).join(", ");return` { exportName: "${r.exportName}", subscriptions: [${o}] },`}).join(`
298
+ `}},Q=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};const n=e.map(r=>{a(r.exportName,`topic export "${r.exportName}"`);const o=h(t,r.exportName).map(l=>`{ binding: "${l.bindingName}", exportName: "${l.exportName}" }`).join(", ");return` { exportName: "${r.exportName}", subscriptions: [${o}] },`}).join(`
292
299
  `);return{build:`
293
300
  const topics = createTopicContext(env, LUNORA_TOPICS);
294
301
  `,contextField:`
@@ -314,22 +321,22 @@ ${n}
314
321
  const LUNORA_AGENTS: ReadonlyArray<AgentBindingSpec> = [
315
322
  ${t}
316
323
  ];
317
- `}},f=(e,t,n,r,o)=>({constant:`
324
+ `}},y=(e,t,n,r,o)=>({constant:`
318
325
  ${o}
319
- const ${e} = ${g(r,t)};
326
+ const ${e} = ${f(r,t)};
320
327
  `,override:`
321
328
  protected override ${n}(): ${t} {
322
329
  return ${e};
323
330
  }
324
- `}),H=e=>{if(e.length===0)return{constant:"",override:""};const t={workflows:e.map(n=>({className:n.className,exportName:n.exportName,name:n.name}))};return f("LUNORA_WORKFLOWS_INFO","WorkflowsResult","workflowsMetadata",t,"/** Read-only declared-workflow metadata (discovered from `lunora/workflows.ts`) served via `__lunora_admin__:listWorkflows` for the studio's workflows view. */")},G=e=>{if(e.length===0)return{constant:"",override:""};const t={queues:e.map(n=>({binding:n.bindingName,...n.tuning.deadLetterQueue===void 0?{}:{deadLetterQueue:n.tuning.deadLetterQueue},exportName:n.exportName,mode:n.mode,name:n.name,...n.topic===void 0?{}:{topic:n.topic}}))};return f("LUNORA_QUEUES_INFO","QueuesResult","queuesMetadata",t,"/** Read-only declared-queue metadata (discovered from `lunora/queues.ts`) served via `__lunora_admin__:listQueues` for the studio's queues view. */")},Y=e=>e?{imports:['import type { LunoraDatabaseLike as LunoraPaymentDbLike, LunoraPayment, PaymentsFromContextOptions } from "@lunora/payment";','import { paymentsFromContext } from "@lunora/payment";'],build:`
331
+ `}),G=e=>{if(e.length===0)return{constant:"",override:""};const t={workflows:e.map(n=>({className:n.className,exportName:n.exportName,name:n.name}))};return y("LUNORA_WORKFLOWS_INFO","WorkflowsResult","workflowsMetadata",t,"/** Read-only declared-workflow metadata (discovered from `lunora/workflows.ts`) served via `__lunora_admin__:listWorkflows` for the studio's workflows view. */")},H=e=>{if(e.length===0)return{constant:"",override:""};const t={queues:e.map(n=>({binding:n.bindingName,...n.tuning.deadLetterQueue===void 0?{}:{deadLetterQueue:n.tuning.deadLetterQueue},exportName:n.exportName,mode:n.mode,name:n.name,...n.topic===void 0?{}:{topic:n.topic}}))};return y("LUNORA_QUEUES_INFO","QueuesResult","queuesMetadata",t,"/** Read-only declared-queue metadata (discovered from `lunora/queues.ts`) served via `__lunora_admin__:listQueues` for the studio's queues view. */")},Y=e=>e?{imports:['import type { LunoraDatabaseLike as LunoraPaymentDbLike, LunoraPayment, PaymentsFromContextOptions } from "@lunora/payment";','import { paymentsFromContext } from "@lunora/payment";'],build:`
325
332
  const payments: LunoraPayment = config.payment
326
333
  ? paymentsFromContext({ auth: { userId: userId ?? null }, db: db as unknown as LunoraPaymentDbLike }, config.payment(env))
327
334
  : paymentStub;
328
335
  `,configField:`
329
336
  payment?: (env: Record<string, unknown>) => PaymentsFromContextOptions;`,contextField:`
330
- payments,`,stub:l("paymentStub: LunoraPayment",'throw new Error("ctx.payments: no payment configured. Pass \\`payment\\` to createShardDO().");',["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"],{cast:" as unknown as LunoraPayment",sync:["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"]})}:{build:"",configField:"",contextField:"",imports:[],stub:""},J=e=>e?{imports:['import type { X402Pay, X402PayConfig } from "@lunora/x402/pay";','import { lazyX402Pay } from "@lunora/x402/pay";'],build:`
337
+ payments,`,stub:u("paymentStub: LunoraPayment",'throw new Error("ctx.payments: no payment configured. Pass \\`payment\\` to createShardDO().");',["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"],{cast:" as unknown as LunoraPayment",sync:["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"]})}:{build:"",configField:"",contextField:"",imports:[],stub:""},J=e=>e?{imports:['import type { X402Pay, X402PayConfig } from "@lunora/x402/pay";','import { lazyX402Pay } from "@lunora/x402/pay";'],build:`
331
338
  const x402: X402Pay = config.x402
332
339
  ? lazyX402Pay(config.x402(env), { getSecret: (name: string) => secrets.get(name) })
333
340
  : x402Stub;
334
341
  `,configField:`
335
- x402?: (env: Record<string, unknown>) => X402PayConfig;`,stub:l("x402Stub: X402Pay",'throw new Error("ctx.x402: no pay rail configured. Pass \\`x402\\` to createShardDO().");',["fetch"],{cast:" as unknown as X402Pay",sync:["fetch"]})}:{build:"",configField:"",imports:[],stub:""},X=(e,t,n,r,o)=>["AdvisorProcedure","AdvisoryFinding","DatabaseWriterLike","DataMigrationLike","DispatchBookmark","ExportRow",...r?["FlagsResult"]:[],"ImportShardResult","KeyRange","MaskPoliciesResult","MigrationRunResult","QueryReadScope",...n?["QueuesResult"]:[],"RelatedPage","RunShardApplyCdcArgs","RunShardExportArgs","RunShardFindRelatedArgs","RunShardImportArgs","RunShardMigrationArgs","RlsPoliciesResult","RunShardRankBeforeArgs","RunShardRankPageArgs","RunShardWriteArgs","RunShardWriteResult","SchedulerLike",...o?["SearchBackfillProgress"]:[],"TransactionHeadroomTracker","SchemaLike","ShardDOState","ShardRankPageResult","SqlExec","StorageRulesResult","StudioFeaturesResult","SubscriptionIdentity","SystemReaderStorageLike","TelemetrySink",...e?["VectorBackfillProgress"]:[],...t?["WorkflowsResult"]:[],...e?["WriteHook"]:[]];export{$ as A,T as B,B as C,D,j as E,N as a,L as b,C as c,A as d,R as e,_ as f,E as g,O as h,P as i,q as j,I as k,M as l,Q as m,K as n,W as o,U as p,V as q,l as r,Y as s,J as t,H as u,G as v,S as w,X as x,w as y,F as z};
342
+ x402?: (env: Record<string, unknown>) => X402PayConfig;`,stub:u("x402Stub: X402Pay",'throw new Error("ctx.x402: no pay rail configured. Pass \\`x402\\` to createShardDO().");',["fetch"],{cast:" as unknown as X402Pay",sync:["fetch"]})}:{build:"",configField:"",imports:[],stub:""},X=(e,t,n,r,o)=>["AdvisorProcedure","AdvisoryFinding","DatabaseWriterLike","DataMigrationLike","DispatchBookmark","ExportRow",...r?["FlagsResult"]:[],"ImportShardResult","KeyRange","MaskPoliciesResult","MigrationRunResult","QueryReadScope",...n?["QueuesResult"]:[],"RelatedPage","RunShardApplyCdcArgs","RunShardExportArgs","RunShardFindRelatedArgs","RunShardImportArgs","RunShardMigrationArgs","RlsPoliciesResult","RunShardRankBeforeArgs","RunShardRankPageArgs","RunShardWriteArgs","RunShardWriteResult","SchedulerLike",...o?["SearchBackfillProgress"]:[],"TransactionHeadroomTracker","SchemaLike","ShardDOState","ShardRankPageResult","SqlExec","StorageRulesResult","StudioFeaturesResult","SubscriptionIdentity","SystemReaderStorageLike","TelemetrySink",...e?["VectorBackfillProgress"]:[],...t?["WorkflowsResult"]:[],...e?["WriteHook"]:[]];export{L as A,T as B,B as C,D,j as E,N as a,$ as b,F as c,A as d,R as e,E as f,_ as g,O as h,P as i,q as j,I as k,M as l,Q as m,K as n,W as o,U as p,V as q,u as r,Y as s,J as t,G as u,H as v,S as w,X as x,w as y,C as z};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/codegen",
3
- "version": "1.0.0-alpha.246",
3
+ "version": "1.0.0-alpha.248",
4
4
  "description": "Code generator for Lunora: emits _generated/{api,server,dataModel}.ts from your schema",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -46,13 +46,13 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@lunora/advisor": "1.0.0-alpha.178",
50
- "@lunora/agent": "1.0.0-alpha.160",
51
- "@lunora/container": "1.0.0-alpha.64",
49
+ "@lunora/advisor": "1.0.0-alpha.180",
50
+ "@lunora/agent": "1.0.0-alpha.162",
51
+ "@lunora/container": "1.0.0-alpha.65",
52
52
  "@lunora/errors": "1.0.0-alpha.48",
53
- "@lunora/platform": "1.0.0-alpha.48",
54
- "@lunora/queue": "1.0.0-alpha.84",
55
- "@lunora/scheduler": "1.0.0-alpha.102",
53
+ "@lunora/platform": "1.0.0-alpha.49",
54
+ "@lunora/queue": "1.0.0-alpha.85",
55
+ "@lunora/scheduler": "1.0.0-alpha.103",
56
56
  "@lunora/values": "1.0.0-alpha.58",
57
57
  "@lunora/workflow": "1.0.0-alpha.69",
58
58
  "jiti": "^2.7.0",
@@ -1 +0,0 @@
1
- import{existsSync as $}from"node:fs";import{join as S}from"node:path";import{containerClassName as P,containerBindingName as T,DURABLE_OBJECT_POLICY_FORBIDDEN_KEYS as A,isManagedImage as j,isCloudflareRegistryDigest as O,normalizeContainerImage as b}from"@lunora/container";import{SyntaxKind as d,Node as o}from"ts-morph";import{diagnosticAt as a}from"./CodegenDiagnosticError-BUXlG3P-.mjs";import{propertyKeyName as y,stringPropertyFor as I,findObjectProperty as p,symbolConstInitializer as k}from"./listLunoraSourceFiles-CSlcBYlo.mjs";const C="containers.ts",D=t=>{const e=t.getSymbol();if(!e)return t.getText()==="defineContainer";for(const r of e.getDeclarations())if(o.isImportSpecifier(r))return r.getImportDeclaration().getModuleSpecifierValue()!=="@lunora/container"?!1:r.getNameNode().getText()==="defineContainer";return!1},f=I("container"),h=(t,e,r)=>{if(o.isNumericLiteral(t))return t.getLiteralValue();throw a(t,`container "${e}": \`${r}\` must be a static number literal — it is deploy configuration codegen writes into wrangler.jsonc`)},w=(t,e)=>{if(o.isStringLiteral(t)||o.isNoSubstitutionTemplateLiteral(t))return b(t.getLiteralValue());if(o.isObjectLiteralExpression(t)){const r=p(t,"registry");if(r&&o.isPropertyAssignment(r)){const i=r.getInitializerOrThrow();return b({registry:f(i,e,"image.registry")})}const n=p(t,"build");if(n&&o.isPropertyAssignment(n)){const i=n.getInitializerOrThrow();return b({build:f(i,e,"image.build")})}}throw a(t,`container "${e}": \`image\` must be a static string path, { registry: "…" }, or { build: "…" } literal`)},M=new Set(["buildArgs","image","images","instanceType","maxInstances","name","rollout","schedulingPolicy"]),_=new Set(["gracePeriodSeconds","stepPercentage"]),E=t=>{let e=t;for(;o.isAsExpression(e)||o.isSatisfiesExpression(e)||o.isTypeAssertion(e)||o.isParenthesizedExpression(e);)e=e.getExpression();return e},F=(t,e)=>{const r=i=>{let s=i;for(;o.isPropertyAccessExpression(s)||o.isElementAccessExpression(s)||o.isParenthesizedExpression(s);)s=s.getExpression();return s===i?void 0:s},n=i=>i!==void 0&&o.isIdentifier(i)&&i.getSymbol()===t;return e.getDescendants().some(i=>{if(o.isBinaryExpression(i)){const s=i.getOperatorToken().getKind();return s>=d.FirstAssignment&&s<=d.LastAssignment&&n(r(i.getLeft()))}if(o.isPrefixUnaryExpression(i)||o.isPostfixUnaryExpression(i)){const s=i.getOperatorToken();return(s===d.PlusPlusToken||s===d.MinusMinusToken)&&n(r(i.getOperand()))}return o.isDeleteExpression(i)?n(r(i.getExpression())):o.isCallExpression(i)&&i.getExpression().getText()==="Object.assign"&&n(i.getArguments()[0])})},B=16,v=(t,e,r,n)=>{let i={name:r,symbol:t},s;for(let l=0;l<B;l+=1){const c=k(i.symbol);if(c===void 0||!o.isExpression(c))return s;if(s=E(c),o.isObjectLiteralExpression(s)&&i.symbol!==void 0&&F(i.symbol,e.getSourceFile()))throw a(e,`${n}: \`${i.name}\` is a const object that is written to elsewhere in this file, so its initializer is not the value the container runs with. Declare the settings where they are final.`);if(!o.isIdentifier(s))return s;i={name:s.getText(),symbol:s.getSymbol()}}return s},L=(t,e)=>{const r=E(t);return o.isIdentifier(r)?v(r.getSymbol(),r,r.getText(),e)??r:r},R=t=>{const e=t.getNonNullableType();return(e.isUnion()?e.getUnionTypes():[e]).flatMap(n=>n.getApparentType().getProperties().map(i=>i.getName()))},V=(t,e,r)=>{const n=t.getExpression().getType(),i=e==="every"||n.isAny()||n.isUnknown()?["its keys"]:[...new Set(R(n))].filter(s=>e.has(s)).map(s=>`\`${s}\``);if(i.length>0)throw a(t,`${r}: this spread can set ${i.join(", ")}, which codegen writes into wrangler.jsonc and so must read statically. Spread a module-scope \`const\` object literal, or write the keys inline.`)},z=(t,e,r)=>{const n=y(t),i=o.isShorthandPropertyAssignment(t)?v(t.getValueSymbol(),t,n,r):void 0;if(i!==void 0)return[n,i];if(e==="every"||e.has(n))throw a(t,`${r}: \`${n}\` is deploy configuration codegen writes into wrangler.jsonc, so it must be a static literal — inline it, or name a module-scope \`const\` initialized with one.`)},m=(t,e,r,n=new Set)=>{const i=[],s=new Set(n).add(t);for(const l of t.getProperties())if(o.isPropertyAssignment(l))i.push([y(l),L(l.getInitializerOrThrow(),r)]);else if(o.isSpreadAssignment(l))i.push(...K(l,e,r,s));else{const c=z(l,e,r);c!==void 0&&i.push(c)}return i},K=(t,e,r,n)=>{const i=L(t.getExpression(),r);if(!o.isObjectLiteralExpression(i))return V(t,e,r),[];if(n.has(i))throw a(t,`${r}: this spread refers back to an object it is part of, so it has no static value.`);return m(i,e,r,n)},U=(t,e)=>{if(!o.isObjectLiteralExpression(t))throw a(t,`container "${e}": \`buildArgs\` must be a static object literal — it is deploy configuration codegen writes into wrangler.jsonc`);const r={};for(const[n,i]of m(t,"every",`container "${e}" buildArgs`))r[n]=f(i,e,`buildArgs.${n}`);return Object.keys(r).length>0?r:void 0},x=(t,e)=>{if(!o.isObjectLiteralExpression(t))throw a(t,`container "${e}": \`rollout\` must be a static object literal — it is deploy configuration codegen writes into wrangler.jsonc`);const r={};for(const[n,i]of m(t,_,`container "${e}" rollout`))(n==="gracePeriodSeconds"||n==="stepPercentage")&&(r[n]=h(i,e,`rollout.${n}`));return r.gracePeriodSeconds===void 0&&r.stepPercentage===void 0?void 0:r},N=t=>{if(o.isTrueLiteral(t))return!0;if(o.isFalseLiteral(t))return!1},Y=t=>{if(o.isStringLiteral(t)||o.isNoSubstitutionTemplateLiteral(t)||o.isNumericLiteral(t))return t.getLiteralValue()},q=(t,e)=>{if(o.isStringLiteral(t))return t.getLiteralValue();if(o.isObjectLiteralExpression(t)){const r={};for(const n of t.getProperties()){if(!o.isPropertyAssignment(n))throw a(n,`container "${e}": \`instanceType\` must be an object of static number literals`);const i=y(n);if(i!=="diskMb"&&i!=="memoryMib"&&i!=="vcpu")throw a(n,`container "${e}": unknown \`instanceType\` field "${i}" — expected vcpu, memoryMib, or diskMb`);r[i]=h(n.getInitializerOrThrow(),e,`instanceType.${i}`)}return r}throw a(t,`container "${e}": \`instanceType\` must be a static string or { vcpu, memoryMib, diskMb } literal`)},W=(t,e)=>{if(!o.isObjectLiteralExpression(t))throw a(t,`container "${e}": \`images\` must be a static object literal — codegen writes it into wrangler.jsonc`);const r={};for(const[n,i]of m(t,"every",`container "${e}" images`)){const s=w(i,e);if(s.kind==="build")throw a(i,`container "${e}": \`images["${n}"]\` cannot be a Railpack { build } source — use a Dockerfile path or a { registry } reference`);if(s.kind==="registry"&&!O(s.reference))throw a(i,`container "${e}": \`images["${n}"].registry\` must be a digest-pinned (@sha256) reference under registry.cloudflare.com — push other registries' images there first`);r[n]=s}return r},G=(t,e)=>{const r=t.findLast(([i])=>i==="schedulingPolicy");if(r===void 0)return;const n=f(r[1],e,"schedulingPolicy");if(n!=="default"&&n!=="durable_object")throw a(r[1],`container "${e}": unknown \`schedulingPolicy\` "${n}" — use "default" or "durable_object"`);return n==="durable_object"?n:void 0},H=(t,e,r,n)=>{if(r!==void 0&&A.includes(t))throw a(e,`container "${n}": \`${t}\` is not supported with schedulingPolicy "durable_object"`);if(r===void 0&&t==="images")throw a(e,`container "${n}": \`images\` needs schedulingPolicy "durable_object"`)},J=(t,e,r,n)=>{const{base:i,policy:s}=r;switch(t){case"buildArgs":{i.buildArgs=U(e,n);break}case"enableInternet":{i.enableInternet=N(e);break}case"image":{r.scheduled||(s.image=w(e,n));break}case"images":{s.images=W(e,n);break}case"instanceType":{i.instanceType=q(e,n);break}case"maxInstances":{s.maxInstances=h(e,n,"maxInstances");break}case"name":{i.name=f(e,n,"name");break}case"rollout":{s.rollout=x(e,n);break}case"sleepAfter":{i.sleepAfter=Y(e);break}}},X=(t,e,r)=>{const n=t.findLast(([s])=>s==="image")?.[1];if(n===void 0||!(o.isStringLiteral(n)||o.isNoSubstitutionTemplateLiteral(n)))return;const i=n.getLiteralValue();if(!Object.hasOwn(e??{},i)&&!j(i))throw a(n,`container "${r}": \`image\` "${i}" must name an entry of \`images\` or a Cloudflare-managed "cloudflare/…" image`)},Q=(t,e)=>{const r=t.getArguments()[0];if(!r||!o.isObjectLiteralExpression(r))throw a(t,`container "${e}": defineContainer must be passed an inline object literal`);const n=m(r,M,`container "${e}"`),i=G(n,e),s={base:{bindingName:T(e),className:P(e),exportName:e},policy:{},scheduled:i!==void 0};for(const[u,g]of n)H(u,g,i,e),J(u,g,s,e);const{base:l,policy:c}=s;if(i==="durable_object")return X(n,c.images,e),{...l,...c.images===void 0?{}:{images:c.images},schedulingPolicy:i};if(c.image===void 0)throw a(r,`container "${e}": defineContainer requires a static \`image\` property`);return{...l,image:c.image,...c.maxInstances===void 0?{}:{maxInstances:c.maxInstances},...c.rollout===void 0?{}:{rollout:c.rollout}}},Z=t=>{const e=[],r=new Map;for(const n of t.getVariableDeclarations()){if(!n.isExported())continue;const i=n.getInitializer();if(i?.getKind()!==d.CallExpression)continue;const s=i,l=s.getExpression();if(!o.isIdentifier(l)||!D(l))continue;const c=n.getNameNode();if(!o.isIdentifier(c))throw a(c,"defineContainer exports must be plain named exports (no destructuring)");const u=Q(s,c.getText()),g=r.get(u.bindingName);if(g!==void 0)throw a(c,`containers "${g}" and "${u.exportName}" both map to the binding ${u.bindingName} — rename one so each container gets its own Durable Object binding`);r.set(u.bindingName,u.exportName),e.push(u)}return e},oe=(t,e)=>{const r=S(e,C);if(!$(r))return[];const n=t.getSourceFile(r)??t.addSourceFileAtPath(r),i=Z(n);return i.sort((s,l)=>s.exportName.localeCompare(l.exportName)),i};export{C as CONTAINERS_FILENAME,oe as discoverContainers};
@@ -1 +0,0 @@
1
- import{NODE_CAPABILITIES as f,CLOUDFLARE_CAPABILITIES as h,CELLD_CAPABILITIES as v}from"@lunora/platform";import{readProjectConfigLiterals as g}from"./loadProjectConfig-6Zk3abcc.mjs";const c="cloudflare",b=t=>{const{target:e}=g(t);return e!==void 0&&e.length>0?e:void 0},L=(t,e)=>e??b(t)??c,x=(t,e)=>{if(e!==void 0)return[];const{target:a,unreadable:r}=g(t);return r!==!0||a!==void 0?[]:[{level:"warn",message:`lunora.config declares a \`target\` that codegen cannot read without evaluating it, so the "${c}" surface was emitted. \`runCodegen\` resolves the target synchronously, which means it reads literals only.`,name:"platform_unreadable_target",remediation:`Write \`target\` as a string literal on the config's default export (\`export default { target: "${c}" }\`), or pass \`--target\`.`,target:c}]},u={celld:v,cloudflare:h,node:f},C=()=>Object.keys(u).toSorted((t,e)=>t.localeCompare(e)),w={access:null,ai:"ai",analytics:"analytics",browser:"browser",container:"containers",flags:null,hyperdrive:"hyperdrive",images:"images",kv:"keyValueStore",mail:"mail",notify:null,payments:null,pipelines:"pipelines",r2sql:null,scheduler:"scheduler",storage:"objectStorage",vectors:"vectorStore",workflows:"workflows",x402:null},S=["agents","commitOrderedTables","containerEgressPolicy","containerRuntimeScheduling","cronTriggers","crossShardFanout","durableStreams","globalTables","queues","relationGraph","secrets","services","topics","vectorStore","workerLoaders","workflowRollback","workflowSchedules"],m={agents:"durable agents (`defineAgent`)",commitOrderedTables:"commit-ordered tables (`.commitOrdered()`)",containerEgressPolicy:"container egress policies (`defineContainer({ allowedHosts | deniedHosts | interceptHttps })`)",containerRuntimeScheduling:'per-instance container images and snapshots (`defineContainer({ schedulingPolicy: "durable_object" })`)',cronTriggers:"declared cron triggers (`cronJobs()`)",crossShardFanout:"cross-shard fan-out queries (a `.shardBy(...)` schema)",durableStreams:"durable streams (`.stream(handler, { durable: true })`)",globalTables:"global tables (`.global()`)",queues:"queues (`defineQueue`)",relationGraph:"relation-graph traversal (`ctx.db.related`, derived from `v.id(...)` columns)",secrets:"the secrets store (`ctx.secrets`)",services:"service bindings to sibling Workers (`lunora.config` `services`)",topics:"pub/sub topics (`defineTopic` / `defineSubscription`)",vectorStore:"vector indexes (`.vectorize()`)",workerLoaders:"sandboxed agent scripts (`jsCodeTool`, on Worker Loaders)",workflowRollback:"workflow step rollback (`defineStep({ rollback })`)",workflowSchedules:"scheduled workflow instances (`defineWorkflow({ schedules })`)"},y=(t,e,a)=>({level:"error",message:`${e.name} does not support ${m[t]}, which this app declares.`,name:"platform_unsupported_feature",remediation:`Remove the declaration, or deploy to a target whose capability matrix marks "${t}" as native or emulated.`,target:a}),T=(t,e,a)=>({level:"error",message:`${e.name}'s capability matrix does not declare a support level for ${m[t]}, which this app declares. Treated as unsupported.`,name:"platform_undeclared_feature",remediation:`Rate "${t}" in the ${e.name} capability matrix as "native", "emulated", or "unsupported" — an undeclared feature fails closed rather than letting the app deploy onto a primitive the host may not provide.`,target:a}),k=t=>{const{diagnostics:e,gatedSignals:a,matrix:r,reported:n,signals:d,target:i}=t;for(const s of S){if(d[s]!==!0)continue;const o=r.features[s]?.level;o!=="unsupported"&&o!==void 0||(a[s]=!1,!n.has(s)&&e.push(o==="unsupported"?y(s,r,i):T(s,r,i)))}},_=(t,e,a,r={})=>{const n={...t},d={...r},i=[],s=new Set;for(const[o,l]of Object.entries(w)){if(l===null||!t[o])continue;const p=e.features[l]?.level;p==="unsupported"?(n[o]=!1,s.add(l),i.push({feature:o,level:"error",message:`${e.name} does not support "${o}" (ctx.${o}).`,name:"platform_unsupported_feature",remediation:`Remove the ctx.${o} usage, or deploy to a target whose capability matrix marks "${l}" as native or emulated.`,target:a})):p===void 0&&(n[o]=!1,s.add(l),i.push({feature:o,level:"error",message:`${e.name}'s capability matrix does not declare a support level for "${o}" (ctx.${o}). Treated as unsupported.`,name:"platform_undeclared_feature",remediation:`Rate "${l}" in the ${e.name} capability matrix as "native", "emulated", or "unsupported" — an undeclared feature fails closed rather than shipping a surface the host may not provide.`,target:a}))}return k({diagnostics:i,gatedSignals:d,matrix:e,reported:s,signals:r,target:a}),{diagnostics:i,signals:d,usage:n}},E=(t,e,a={})=>{const r=u[e];return r===void 0?{diagnostics:[{level:"error",message:`Unknown deploy target "${e}" — no capability matrix is registered for it. Codegen emitted the full Cloudflare surface un-gated.`,name:"platform_unknown_target",remediation:`Use a registered target (${Object.keys(u).join(", ")}) or install the target's @lunora/platform-${e} package.`,target:e}],signals:{...a},usage:{...t}}:_(t,r,e,a)},I=t=>{const e=u[t];if(e===void 0)return;const a=Object.entries(e.features).filter(([,r])=>r.level==="unsupported").map(([r])=>r).toSorted((r,n)=>r.localeCompare(n));return{id:e.id,name:e.name,unsupported:a}};export{w as CAPABILITY_TO_FEATURE,c as DEFAULT_TARGET,_ as gateAgainstMatrix,E as gatePlatformFeatures,C as platformMatrixIds,b as readProjectTarget,x as readTargetDiagnostics,L as resolveCodegenTarget,I as studioPlatformFor};