@lunora/codegen 1.0.0-alpha.80 → 1.0.0-alpha.82

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,4 +1,4 @@
1
- import{agentComponent as Ye}from"@lunora/agent/component";import{LunoraError as Z}from"@lunora/errors";import{serializeSchemaSnapshot as zt,hashSchemaSnapshot as Xt}from"./SCHEMA_SNAPSHOT_VERSION-CFhF_hmg.mjs";import{n as S}from"./paths-BmX5O1sG.mjs";const Ze=[{contextProperty:"access",key:"access",moduleSpecifier:"@lunora/cloudflare-access"},{appMethod:{configKey:"ai",doc:"Override the Workers AI binding backing `ctx.ai` (defaults to `env.AI`).",method:"ai"},contextProperty:"ai",key:"ai",moduleSpecifier:"@lunora/ai"},{appMethod:{configKey:"analytics",doc:"Override the Analytics Engine dataset backing `ctx.analytics` (defaults to `env.ANALYTICS`).",method:"analytics"},contextProperty:"analytics",key:"analytics",moduleSpecifier:"@lunora/bindings/analytics",serverCtxField:{field:`
1
+ import{agentComponent as Ze}from"@lunora/agent/component";import{LunoraError as Z}from"@lunora/errors";import{serializeSchemaSnapshot as en,hashSchemaSnapshot as tn}from"./SCHEMA_SNAPSHOT_VERSION-CFhF_hmg.mjs";import{n as S}from"./paths-BmX5O1sG.mjs";const et=[{contextProperty:"access",key:"access",moduleSpecifier:"@lunora/cloudflare-access"},{appMethod:{configKey:"ai",doc:"Override the Workers AI binding backing `ctx.ai` (defaults to `env.AI`).",method:"ai"},contextProperty:"ai",key:"ai",moduleSpecifier:"@lunora/ai"},{appMethod:{configKey:"analytics",doc:"Override the Analytics Engine dataset backing `ctx.analytics` (defaults to `env.ANALYTICS`).",method:"analytics"},contextProperty:"analytics",key:"analytics",moduleSpecifier:"@lunora/bindings/analytics",serverCtxField:{field:`
2
2
  /** Analytics Engine telemetry sink. Fire-and-forget and sampled; do not read it back in-handler. */
3
3
  readonly analytics: import("@lunora/bindings/analytics").AnalyticsClient;`,tier:"every"}},{appMethod:{configKey:"browser",doc:"Override the Browser Rendering binding backing `ctx.browser` (defaults to `env.BROWSER`).",method:"browser"},contextProperty:"browser",key:"browser",moduleSpecifier:"@lunora/browser",serverCtxField:{field:`
4
4
  /** Browser Rendering (screenshots/PDF/scrape). Non-deterministic — available only in actions. */
@@ -15,50 +15,50 @@ import{agentComponent as Ye}from"@lunora/agent/component";import{LunoraError as
15
15
  /**
16
16
  * R2 SQL over Apache Iceberg tables (window functions, DISTINCT, set operations). Non-deterministic — available only in actions. Reads here are NOT tracked by Lunora live queries.
17
17
  */
18
- readonly r2sql: import("@lunora/bindings/r2sql").R2SqlClient;`,tier:"action"}},{contextProperty:"scheduler",key:"scheduler",moduleSpecifier:"@lunora/scheduler"},{contextProperty:"storage",key:"storage",moduleSpecifier:"@lunora/storage"},{appMethod:{configKey:"vectors",doc:"Wire the Vectorize index map backing `ctx.vectors`.",method:"vectors"},contextProperty:"vectors",key:"vectors",moduleSpecifier:"@lunora/bindings/vectors"},{contextProperty:"workflows",key:"workflows",moduleSpecifier:"@lunora/workflow"}],Yt=Ze,Zt=new Map(Yt.flatMap(e=>e.serverCtxField?[[e.key,e.serverCtxField]]:[])),mr=Ze.flatMap(e=>"appMethod"in e?[{appMethod:e.appMethod,key:e.key}]:[]),et=/^(?:"(?:[^"\\]|\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4}))*"|'[^'\\]*'|-?\d+(?:\.\d+)?|true|false|null)$/u,en=new Set(["any","bigint","boolean","date","id","null","number","storage","string","timestamp"]),tt=e=>e.column!==void 0,tn=(e,t)=>{switch(e){case"bigint":return`if (typeof ${t} !== "bigint") return DEFER;
18
+ readonly r2sql: import("@lunora/bindings/r2sql").R2SqlClient;`,tier:"action"}},{contextProperty:"scheduler",key:"scheduler",moduleSpecifier:"@lunora/scheduler"},{contextProperty:"storage",key:"storage",moduleSpecifier:"@lunora/storage"},{appMethod:{configKey:"vectors",doc:"Wire the Vectorize index map backing `ctx.vectors`.",method:"vectors"},contextProperty:"vectors",key:"vectors",moduleSpecifier:"@lunora/bindings/vectors"},{contextProperty:"workflows",key:"workflows",moduleSpecifier:"@lunora/workflow"}],nn=et,rn=new Map(nn.flatMap(e=>e.serverCtxField?[[e.key,e.serverCtxField]]:[])),xr=et.flatMap(e=>"appMethod"in e?[{appMethod:e.appMethod,key:e.key}]:[]),tt=/^(?:"(?:[^"\\]|\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4}))*"|'[^'\\]*'|-?\d+(?:\.\d+)?|true|false|null)$/u,an=new Set(["any","bigint","boolean","date","id","null","number","storage","string","timestamp"]),nt=e=>e.column!==void 0,on=(e,t)=>{switch(e){case"bigint":return`if (typeof ${t} !== "bigint") return DEFER;
19
19
  `;case"boolean":return`if (typeof ${t} !== "boolean") return DEFER;
20
20
  `;case"date":case"number":case"timestamp":return`if (typeof ${t} !== "number" || !Number.isFinite(${t})) return DEFER;
21
21
  `;case"null":return`if (${t} !== null) return DEFER;
22
22
  `;default:return`if (typeof ${t} !== "string") return DEFER;
23
- `}},nn=(e,t)=>{const n=e.literalValue?.trim();if(!(n===void 0||!et.test(n)))return{out:t,pre:`if (${t} !== ${n}) return DEFER;
24
- `}},Fe=(e,t,n)=>{if(!tt(e)&&!(e.hasRefinement||e.sourceText!==void 0)){if(en.has(e.kind))return e.kind==="any"?{out:t,pre:""}:{out:t,pre:tn(e.kind,t)};switch(e.kind){case"array":return rn(e,t,n);case"literal":return nn(e,t);case"object":return on(e,t,n);default:return}}},rn=(e,t,n)=>{const{inner:r}=e;if(!r)return;const a=n.next(),o=`__arr${String(a)}`,s=`__i${String(a)}`,i=`__e${String(a)}`,l=Fe(r,i,n);if(!l)return;const u=`if (!Array.isArray(${t})) return DEFER;
23
+ `}},sn=(e,t)=>{const n=e.literalValue?.trim();if(!(n===void 0||!tt.test(n)))return{out:t,pre:`if (${t} !== ${n}) return DEFER;
24
+ `}},Fe=(e,t,n)=>{if(!nt(e)&&!(e.hasRefinement||e.sourceText!==void 0)){if(an.has(e.kind))return e.kind==="any"?{out:t,pre:""}:{out:t,pre:on(e.kind,t)};switch(e.kind){case"array":return ln(e,t,n);case"literal":return sn(e,t);case"object":return cn(e,t,n);default:return}}},ln=(e,t,n)=>{const{inner:r}=e;if(!r)return;const a=n.next(),o=`__arr${String(a)}`,i=`__i${String(a)}`,s=`__e${String(a)}`,l=Fe(r,s,n);if(!l)return;const u=`if (!Array.isArray(${t})) return DEFER;
25
25
  const ${o} = new Array(${t}.length);
26
- for (let ${s} = 0; ${s} < ${t}.length; ${s}++) {
27
- const ${i} = ${t}[${s}];
28
- ${l.pre}${o}[${s}] = ${l.out};
26
+ for (let ${i} = 0; ${i} < ${t}.length; ${i}++) {
27
+ const ${s} = ${t}[${i}];
28
+ ${l.pre}${o}[${i}] = ${l.out};
29
29
  }
30
- `;return{out:o,pre:u}},an=(e,t,n,r)=>{const a=JSON.stringify(e);if(t.kind==="optional"){if(t.hasRefinement||t.sourceText!==void 0||tt(t))return;const{inner:s}=t;if(!s)return;const i=Fe(s,n,r);if(!i)return;const l=r.next(),u=`__has${String(l)}`,p=`__val${String(l)}`,f=`let ${u} = false;
30
+ `;return{out:o,pre:u}},dn=(e,t,n,r)=>{const a=JSON.stringify(e);if(t.kind==="optional"){if(t.hasRefinement||t.sourceText!==void 0||nt(t))return;const{inner:i}=t;if(!i)return;const s=Fe(i,n,r);if(!s)return;const l=r.next(),u=`__has${String(l)}`,p=`__val${String(l)}`,f=`let ${u} = false;
31
31
  let ${p};
32
32
  if (${n} !== undefined) {
33
- ${i.pre}${p} = ${i.out};
33
+ ${s.pre}${p} = ${s.out};
34
34
  ${u} = true;
35
35
  }
36
- `;return{entry:`...(${u} ? { ${a}: ${p} } : {})`,pre:f}}const o=Fe(t,n,r);if(o)return{entry:`${a}: ${o.out}`,pre:o.pre}},nt=(e,t,n)=>{let r="";const a=[];for(const o of Object.keys(e)){const s=e[o];if(!s)return;const i=an(o,s,t(o),n);if(!i)return;r+=i.pre,a.push(i.entry)}return{entries:a.join(", "),pre:r}},on=(e,t,n)=>{const r=e.shape??{},a=nt(r,l=>`${t}[${JSON.stringify(l)}]`,n);if(!a)return;const o=n.next(),s=`__obj${String(o)}`,i=`if (typeof ${t} !== "object" || ${t} === null || Array.isArray(${t})) return DEFER;
37
- ${a.pre}const ${s} = { ${a.entries} };
38
- `;return{out:s,pre:i}},sn=e=>{let t=0;const n=nt(e,r=>`source[${JSON.stringify(r)}]`,{next:()=>(t+=1,t)});if(n)return`(source) => {
36
+ `;return{entry:`...(${u} ? { ${a}: ${p} } : {})`,pre:f}}const o=Fe(t,n,r);if(o)return{entry:`${a}: ${o.out}`,pre:o.pre}},rt=(e,t,n)=>{let r="";const a=[];for(const o of Object.keys(e)){const i=e[o];if(!i)return;const s=dn(o,i,t(o),n);if(!s)return;r+=s.pre,a.push(s.entry)}return{entries:a.join(", "),pre:r}},cn=(e,t,n)=>{const r=e.shape??{},a=rt(r,l=>`${t}[${JSON.stringify(l)}]`,n);if(!a)return;const o=n.next(),i=`__obj${String(o)}`,s=`if (typeof ${t} !== "object" || ${t} === null || Array.isArray(${t})) return DEFER;
37
+ ${a.pre}const ${i} = { ${a.entries} };
38
+ `;return{out:i,pre:s}},un=e=>{let t=0;const n=rt(e,r=>`source[${JSON.stringify(r)}]`,{next:()=>(t+=1,t)});if(n)return`(source) => {
39
39
  if (typeof source !== "object" || source === null || Array.isArray(source)) return DEFER;
40
40
  ${n.pre}return { ${n.entries} };
41
41
  }`},k=`// GENERATED by @lunora/codegen — do not edit.
42
42
  // Run \`lunora codegen\` to regenerate.
43
43
 
44
- `,H=(e=!1)=>e?{client:"lunorash/client",do:"lunorash/do",flags:"lunorash/flags",server:"lunorash/server",serverDataModel:"lunorash/server/data-model",serverDrizzle:"lunorash/server/drizzle",serverTypes:"lunorash/server/types",values:"lunorash/values"}:{client:"@lunora/client",do:"@lunora/do",flags:"@lunora/flags",server:"@lunora/server",serverDataModel:"@lunora/server/data-model",serverDrizzle:"@lunora/server/drizzle",serverTypes:"@lunora/server/types",values:"@lunora/values"},rt=/^[A-Za-z_$][\w$]*$/u,ln=/^[\w./-]+$/u,m=(e,t)=>{if(!rt.test(e))throw new Z("INTERNAL",`@lunora/codegen: ${t} is not a valid JS identifier: ${JSON.stringify(e)}`)},Ee=e=>e.charAt(0).toUpperCase()+e.slice(1),D=e=>rt.test(e)?e:JSON.stringify(e),dn={any:"unknown",bigint:"bigint",boolean:"boolean",bytes:"ArrayBuffer",date:"number",geoPoint:"{ lat: number; lng: number }",null:"null",number:"number",storage:"string",string:"string",timestamp:"number"},cn=e=>{if(e===void 0)return"unknown";if(!et.test(e))throw new Z("INTERNAL",`@lunora/codegen: v.literal() argument is not a parseable string/number/boolean/null literal: ${JSON.stringify(e)}`);return e},O=e=>{const t=dn[e.kind];if(t!==void 0)return t;switch(e.kind){case"array":return`Array<${e.inner?O(e.inner):"unknown"}>`;case"from":return e.tsType??"unknown";case"id":{const n=e.tableName??"_unknown_";return m(n,"v.id() table name"),`Id<"${n}">`}case"literal":return cn(e.literalValue);case"object":return e.shape?`{ ${Object.entries(e.shape).map(([n,r])=>`${D(n)}: ${O(r)}`).join("; ")} }`:"Record<string, unknown>";case"optional":return`${e.inner?O(e.inner):"unknown"} | undefined`;case"record":{const n=e.keyType?O(e.keyType):"string",r=e.valueType?O(e.valueType):"unknown";return`Record<${n}, ${r}>`}case"union":return e.members&&e.members.length>0?e.members.map(n=>O(n)).join(" | "):"never";default:return"unknown"}},me=e=>{const t=Object.entries(e);return t.length===0?"{}":`{ ${t.map(([n,r])=>{const a=D(n);if(r.kind==="optional"){const o=r.inner?O(r.inner):"unknown";return`${a}?: ${o}`}return`${a}: ${O(r)}`}).join("; ")} }`},un=e=>e.kind==="optional"||!!e.column?.hasDefault,pn=e=>{m(e.name,"table name");const t=Object.entries(e.shape).map(([r,a])=>{const o=a.kind==="optional"&&a.inner?a.inner:a,s=O(o),i=D(r);return un(a)?` ${i}?: ${s};`:` ${i}: ${s};`}).join(`
44
+ `,H=(e=!1)=>e?{client:"lunorash/client",do:"lunorash/do",flags:"lunorash/flags",server:"lunorash/server",serverDataModel:"lunorash/server/data-model",serverDrizzle:"lunorash/server/drizzle",serverTypes:"lunorash/server/types",values:"lunorash/values"}:{client:"@lunora/client",do:"@lunora/do",flags:"@lunora/flags",server:"@lunora/server",serverDataModel:"@lunora/server/data-model",serverDrizzle:"@lunora/server/drizzle",serverTypes:"@lunora/server/types",values:"@lunora/values"},at=/^[A-Za-z_$][\w$]*$/u,pn=/^[\w./-]+$/u,m=(e,t)=>{if(!at.test(e))throw new Z("INTERNAL",`@lunora/codegen: ${t} is not a valid JS identifier: ${JSON.stringify(e)}`)},Ee=e=>e.charAt(0).toUpperCase()+e.slice(1),D=e=>at.test(e)?e:JSON.stringify(e),hn={any:"unknown",bigint:"bigint",boolean:"boolean",bytes:"ArrayBuffer",date:"number",geoPoint:"{ lat: number; lng: number }",null:"null",number:"number",storage:"string",string:"string",timestamp:"number"},gn=e=>{if(e===void 0)return"unknown";if(!tt.test(e))throw new Z("INTERNAL",`@lunora/codegen: v.literal() argument is not a parseable string/number/boolean/null literal: ${JSON.stringify(e)}`);return e},C=e=>{const t=hn[e.kind];if(t!==void 0)return t;switch(e.kind){case"array":return`Array<${e.inner?C(e.inner):"unknown"}>`;case"from":return e.tsType??"unknown";case"id":{const n=e.tableName??"_unknown_";return m(n,"v.id() table name"),`Id<"${n}">`}case"literal":return gn(e.literalValue);case"object":return e.shape?`{ ${Object.entries(e.shape).map(([n,r])=>ot(n,r)).join("; ")} }`:"Record<string, unknown>";case"optional":return`${e.inner?C(e.inner):"unknown"} | undefined`;case"record":{const n=e.keyType?C(e.keyType):"string",r=e.valueType?C(e.valueType):"unknown";return`Record<${n}, ${r}>`}case"union":return e.members&&e.members.length>0?e.members.map(n=>C(n)).join(" | "):"never";default:return"unknown"}},ot=(e,t)=>{const n=D(e);if(t.kind==="optional"){const r=t.inner?C(t.inner):"unknown";return`${n}?: ${r}`}return`${n}: ${C(t)}`},me=e=>{const t=Object.entries(e);return t.length===0?"{}":`{ ${t.map(([n,r])=>ot(n,r)).join("; ")} }`},mn=e=>e.kind==="optional"||!!e.column?.hasDefault,fn=e=>{m(e.name,"table name");const t=Object.entries(e.shape).map(([r,a])=>{const o=a.kind==="optional"&&a.inner?a.inner:a,i=C(o),s=D(r);return mn(a)?` ${s}?: ${i};`:` ${s}: ${i};`}).join(`
45
45
  `),n=t?`
46
46
  ${t}
47
47
  `:"";return`export interface Insert_${e.name} {
48
48
  _id?: Id<"${e.name}">;
49
- _creationTime?: number;${n}}`},fr=(e,t=!1)=>{const n=H(t);for(const c of e.tables)m(c.name,"table name");const r=e.tables.map(c=>`"${c.name}"`).join(" | ")||"never",a=e.tables.filter(c=>c.extensionKey===void 0).map(c=>`"${c.name}"`).join(" | ")||"never",o=e.tables.map(c=>{const g=Object.entries(c.shape).map(([x,v])=>{const A=D(x);if(v.kind==="optional"){const N=v.inner?O(v.inner):"unknown";return` ${A}?: ${N};`}return` ${A}: ${O(v)};`}).join(`
49
+ _creationTime?: number;${n}}`},kr=(e,t=!1)=>{const n=H(t);for(const c of e.tables)m(c.name,"table name");const r=e.tables.map(c=>`"${c.name}"`).join(" | ")||"never",a=e.tables.filter(c=>c.extensionKey===void 0).map(c=>`"${c.name}"`).join(" | ")||"never",o=e.tables.map(c=>{const g=Object.entries(c.shape).map(([x,v])=>{const O=D(x);if(v.kind==="optional"){const N=v.inner?C(v.inner):"unknown";return` ${O}?: ${N};`}return` ${O}: ${C(v)};`}).join(`
50
50
  `),b=g?`
51
51
  ${g}
52
52
  `:"";return`export interface Doc_${c.name} {
53
53
  _id: Id<"${c.name}">;
54
54
  _creationTime: number;${b}}`}).join(`
55
55
 
56
- `),s=e.tables.map(c=>` ${c.name}: Doc_${c.name};`).join(`
57
- `),i=e.tables.map(c=>{const g=c.indexes.map(b=>JSON.stringify(b.name)).join(" | ");return` ${c.name}: ${g||"never"};`}).join(`
56
+ `),i=e.tables.map(c=>` ${c.name}: Doc_${c.name};`).join(`
57
+ `),s=e.tables.map(c=>{const g=c.indexes.map(b=>JSON.stringify(b.name)).join(" | ");return` ${c.name}: ${g||"never"};`}).join(`
58
58
  `),l=e.tables.map(c=>{const g=c.searchIndexes.map(b=>JSON.stringify(b.name)).join(" | ");return` ${c.name}: ${g||"never"};`}).join(`
59
59
  `),u=e.tables.map(c=>{const g=c.rankIndexes.map(b=>JSON.stringify(b.name)).join(" | ");return` ${c.name}: ${g||"never"};`}).join(`
60
60
  `),p=e.tables.map(c=>{const g=c.shardMode==="global"?"":(c.geoIndexes??[]).map(b=>JSON.stringify(b.name)).join(" | ");return` ${c.name}: ${g||"never"};`}).join(`
61
- `),f=e.vectorIndexes.map(c=>JSON.stringify(c.name)).join(" | ")||"never",y=e.tables.map(c=>pn(c)).join(`
61
+ `),f=e.vectorIndexes.map(c=>JSON.stringify(c.name)).join(" | ")||"never",y=e.tables.map(c=>fn(c)).join(`
62
62
 
63
63
  `),R=e.tables.map(c=>` ${c.name}: Insert_${c.name};`).join(`
64
64
  `),d=e.tables.map(c=>{const g=c.relations.map(b=>(m(b.table,"relation target table"),` ${D(b.name)}: ${b.kind==="one"?"OneRelation":"ManyRelation"}<"${b.table}">;`)).join(`
@@ -121,7 +121,7 @@ export type Id<TName extends string> = string & { readonly __table: TName };
121
121
  ${o}
122
122
 
123
123
  export interface DataModel {
124
- ${s}
124
+ ${i}
125
125
  }
126
126
 
127
127
  export type Doc<T extends keyof DataModel> = DataModel[T];
@@ -131,7 +131,7 @@ export type Doc<T extends keyof DataModel> = DataModel[T];
131
131
  * Used by \`TableReader.withIndex()\` to constrain callers to declared names.
132
132
  */
133
133
  export interface IndexNamesByTable {
134
- ${i}
134
+ ${s}
135
135
  }
136
136
 
137
137
  export type IndexName<T extends keyof DataModel> = IndexNamesByTable[T];
@@ -234,11 +234,11 @@ export interface OrmWriter extends OrmReader {
234
234
  replace: <T extends keyof DataModel>(table: T, id: Id<T>) => OrmReplaceBuilder<T>;
235
235
  update: <T extends keyof DataModel>(table: T, id: Id<T>) => OrmUpdateBuilder<T>;
236
236
  }
237
- `},hn=/import\("(?<spec>(?:\.\.?\/)*_generated\/[^"]+)"\)/gu,gn=/^(?:\.\.?\/)*_generated\//u,mn=/\.[A-Za-z]\w*$/u,Me=e=>e.replaceAll(hn,(t,n)=>{const r=n.replace(gn,"./");return`import("${mn.test(r)?r:`${r}.js`}")`}),fn=/import\("@lunora\/(?<pkg>client|do|runtime|server|values)(?<subpath>\/[^"]*)?"\)/gu,at=(e,t)=>t?e.replaceAll(fn,(n,r,a)=>`import("lunorash/${r}${a??""}")`):e,qe=e=>["Doc","Id"].filter(t=>new RegExp(String.raw`\b${t}<`,"u").test(e)),bn=e=>e.output===void 0||e.output.kind==="any"?e.returnType:O(e.output),ze=e=>{const t=new Map;for(const r of e){const a=t.get(r.filePath)??[];a.push(r),t.set(r.filePath,a)}const n=([r,a])=>{const o=a.toSorted((s,i)=>s.exportName.localeCompare(i.exportName)).map(s=>{const i=me(s.args),l=Me(bn(s));return` ${s.exportName}: FunctionReference<"${s.kind}", ${i}, ${l}>;`}).join(`
237
+ `},bn=/import\("(?<spec>(?:\.\.?\/)*_generated\/[^"]+)"\)/gu,st=/^(?:\.\.?\/)*_generated\//u,it=/\.[A-Za-z]\w*$/u,Me=e=>e.replaceAll(bn,(t,n)=>{const r=n.replace(st,"./");return`import("${it.test(r)?r:`${r}.js`}")`}),yn=/import\("(?<spec>\.\.?\/[^"]+)"\)/gu,wn=/^(?:\.\.?\/)+/u,xn=e=>{const t=[];for(const n of e.split("/"))if(!(n===""||n===".")){if(n===".."&&t.length>0&&t.at(-1)!==".."){t.pop();continue}t.push(n)}return t.join("/")},qe=(e,t)=>e.replaceAll(yn,(n,r)=>{if(st.test(r.replace(wn,"")))return n;const a=t.includes("/")?t.slice(0,t.lastIndexOf("/")):"",o=`../${xn(`${a}/${r}`)}`;return`import("${it.test(o)?o:`${o}.js`}")`}),kn=/import\("@lunora\/(?<pkg>client|do|runtime|server|values)(?<subpath>\/[^"]*)?"\)/gu,lt=(e,t)=>t?e.replaceAll(kn,(n,r,a)=>`import("lunorash/${r}${a??""}")`):e,Be=e=>["Doc","Id"].filter(t=>new RegExp(String.raw`\b${t}<`,"u").test(e)),vn=e=>e.output===void 0||e.output.kind==="any"?e.returnType:C(e.output),Xe=e=>{const t=new Map;for(const r of e){const a=t.get(r.filePath)??[];a.push(r),t.set(r.filePath,a)}const n=([r,a])=>{const o=a.toSorted((i,s)=>i.exportName.localeCompare(s.exportName)).map(i=>{const s=me(i.args),l=Me(qe(vn(i),i.filePath));return` ${i.exportName}: FunctionReference<"${i.kind}", ${s}, ${l}>;`}).join(`
238
238
  `);return` ${D(S(r))}: {
239
239
  ${o}
240
240
  };`};return[...t.entries()].toSorted(([r],[a])=>r.localeCompare(a)).map(r=>n(r)).join(`
241
- `)},yn=(e,t)=>{if(e.length===0&&t.length===0)return{block:"",importLine:""};const n=[];let r="";if(e.length>0&&(r+="\n/** Params type carried by a `defineWorkflow` definition (its phantom `__params`). */\ntype WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params } ? (unknown extends Params ? Record<string, unknown> : Params) : Record<string, unknown>;\n"),r+=`
241
+ `)},$n=(e,t)=>{if(e.length===0&&t.length===0)return{block:"",importLine:""};const n=[];let r="";if(e.length>0&&(r+="\n/** Params type carried by a `defineWorkflow` definition (its phantom `__params`). */\ntype WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params } ? (unknown extends Params ? Record<string, unknown> : Params) : Record<string, unknown>;\n"),r+=`
242
242
  /** A typed reference to a durable workflow, addressable for \`cronJobs()\` targets. Mirrors \`@lunora/scheduler\`'s \`WorkflowReference\` structurally. */
243
243
  export interface WorkflowReference<Params = Record<string, unknown>> {
244
244
  readonly isLunoraWorkflow: true;
@@ -246,8 +246,8 @@ export interface WorkflowReference<Params = Record<string, unknown>> {
246
246
  readonly binding: string;
247
247
  readonly name: string;
248
248
  }
249
- `,e.length>0){const a=[...e].toSorted((i,l)=>i.exportName.localeCompare(l.exportName)),o=a.map(i=>` ${i.exportName}: WorkflowReference<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${i.exportName}>>;`).join(`
250
- `),s=a.map(i=>` ${i.exportName}: { isLunoraWorkflow: true, binding: ${JSON.stringify(i.bindingName)}, name: ${JSON.stringify(i.exportName)} },`).join(`
249
+ `,e.length>0){const a=[...e].toSorted((s,l)=>s.exportName.localeCompare(l.exportName)),o=a.map(s=>` ${s.exportName}: WorkflowReference<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${s.exportName}>>;`).join(`
250
+ `),i=a.map(s=>` ${s.exportName}: { isLunoraWorkflow: true, binding: ${JSON.stringify(s.bindingName)}, name: ${JSON.stringify(s.exportName)} },`).join(`
251
251
  `);r+=`
252
252
  /** This project's durable workflows, addressable as typed references (e.g. \`crons.daily("digest", …, workflows.digestPipeline, params)\`). */
253
253
  export interface WorkflowsRef {
@@ -255,11 +255,11 @@ ${o}
255
255
  }
256
256
 
257
257
  export const workflows: WorkflowsRef = {
258
- ${s}
258
+ ${i}
259
259
  };
260
260
  `,n.push(`import type * as lunoraWorkflowDefinitions from "../workflows.js";
261
- `)}if(t.length>0){const a=[...t].toSorted((i,l)=>i.exportName.localeCompare(l.exportName)),o=a.map(i=>` ${i.exportName}: WorkflowReference<AgentRunInput>;`).join(`
262
- `),s=a.map(i=>` ${i.exportName}: { isLunoraWorkflow: true, binding: ${JSON.stringify(i.bindingName)}, name: ${JSON.stringify(i.name)} },`).join(`
261
+ `)}if(t.length>0){const a=[...t].toSorted((s,l)=>s.exportName.localeCompare(l.exportName)),o=a.map(s=>` ${s.exportName}: WorkflowReference<AgentRunInput>;`).join(`
262
+ `),i=a.map(s=>` ${s.exportName}: { isLunoraWorkflow: true, binding: ${JSON.stringify(s.bindingName)}, name: ${JSON.stringify(s.name)} },`).join(`
263
263
  `);r+=`
264
264
  /** This project's durable agents, addressable as typed references for \`cronJobs()\` — each fire starts a fresh agent run (e.g. \`crons.daily("sweep", …, agents.support, { input, threadKey })\`). */
265
265
  export interface AgentsRef {
@@ -267,11 +267,11 @@ ${o}
267
267
  }
268
268
 
269
269
  export const agents: AgentsRef = {
270
- ${s}
270
+ ${i}
271
271
  };
272
272
  `,n.push(`import type { AgentRunInput } from "@lunora/agent";
273
- `)}return{block:r,importLine:n.join("")}},wn=()=>Object.keys(Ye().functions).toSorted((e,t)=>e.localeCompare(t)),ot=e=>new Set(e.filter(t=>S(t.filePath)==="agents").map(t=>t.exportName)),xn=()=>new Set(Object.entries(Ye().functions).filter(([,e])=>e.visibility==="internal").map(([e])=>e)),kn=(e,t)=>{const n={importLine:"",lines:"",prelude:""};if(e.length===0)return n;const r=ot(t),a=xn(),o=t.find(i=>S(i.filePath)==="agents"&&a.has(i.exportName));if(o)throw new Z("INTERNAL",`@lunora/codegen: "agents:${o.exportName}" is reserved for the durable agent loop's internal dispatch — rename the "${o.exportName}" export in ${o.filePath}`);const s=wn().filter(i=>!r.has(i));return s.length===0?n:{importLine:`import { agentComponent } from "@lunora/agent/component";
274
- `,lines:s.map(i=>` "agents:${i}": lunoraAgentRuntimeFunctions.${i} as unknown as RegisteredLunoraFunction,`).join(`
273
+ `)}return{block:r,importLine:n.join("")}},Sn=()=>Object.keys(Ze().functions).toSorted((e,t)=>e.localeCompare(t)),dt=e=>new Set(e.filter(t=>S(t.filePath)==="agents").map(t=>t.exportName)),Rn=()=>new Set(Object.entries(Ze().functions).filter(([,e])=>e.visibility==="internal").map(([e])=>e)),Nn=(e,t)=>{const n={importLine:"",lines:"",prelude:""};if(e.length===0)return n;const r=dt(t),a=Rn(),o=t.find(s=>S(s.filePath)==="agents"&&a.has(s.exportName));if(o)throw new Z("INTERNAL",`@lunora/codegen: "agents:${o.exportName}" is reserved for the durable agent loop's internal dispatch — rename the "${o.exportName}" export in ${o.filePath}`);const i=Sn().filter(s=>!r.has(s));return i.length===0?n:{importLine:`import { agentComponent } from "@lunora/agent/component";
274
+ `,lines:i.map(s=>` "agents:${s}": lunoraAgentRuntimeFunctions.${s} as unknown as RegisteredLunoraFunction,`).join(`
275
275
  `),prelude:`
276
276
  /**
277
277
  * The \`@lunora/agent\` runtime component — auto-registered because \`lunora/agents.ts\`
@@ -279,13 +279,13 @@ ${s}
279
279
  * subscribe to the public queries (\`agents:agentMessages\` is the live thread view).
280
280
  */
281
281
  const lunoraAgentRuntimeFunctions = agentComponent().functions;
282
- `}},vn=(e,t)=>{if(!e)return{importLine:"",lines:"",prelude:""};const n=t.find(r=>S(r.filePath)==="sandbox"&&r.exportName==="invoke");if(n)throw new Z("INTERNAL",`@lunora/codegen: "sandbox:invoke" is reserved for the batteries-included sandbox tool dispatcher (browserTool/containerTool) — rename the "invoke" export in ${n.filePath}`);return{importLine:`import { sandboxComponent } from "@lunora/agent/component";
283
- `,lines:' "sandbox:invoke": lunoraSandbox.invoke as unknown as RegisteredLunoraFunction,',prelude:"\n/**\n * The `@lunora/agent` sandbox dispatcher — auto-registered because `lunora/`\n * imports a sandbox tool (`browserTool`/`containerTool`). The batteries-included\n * tools dispatch to this internal action, which runs on an action ctx carrying\n * `ctx.browser` + `ctx.containers` (the durable tool step itself has neither).\n */\nconst lunoraSandbox = sandboxComponent();\n"}},$n=(e,t)=>{if(e.length===0)return[];const n=ot(t),r=[{args:{key:{kind:"string"},limit:{inner:{kind:"number"},kind:"optional"}},exportName:"agentMessages",filePath:"agents",kind:"query",returnType:"Record<string, unknown>[]"},{args:{decision:{kind:"union",members:[{kind:"literal",literalValue:'"approve"'},{kind:"literal",literalValue:'"reject"'}]},instanceId:{kind:"string"},note:{inner:{kind:"string"},kind:"optional"},threadKey:{kind:"string"},toolCallId:{kind:"string"}},exportName:"agentResolveApproval",filePath:"agents",kind:"mutation",returnType:"{ resolved: boolean }"},{args:{agent:{kind:"string"},input:{kind:"string"},threadKey:{kind:"string"},title:{inner:{kind:"string"},kind:"optional"}},exportName:"agentRun",filePath:"agents",kind:"mutation",returnType:"{ id: string; threadKey: string }"},{args:{key:{kind:"string"}},exportName:"agentState",filePath:"agents",kind:"query",returnType:"Record<string, unknown> | undefined"},{args:{key:{kind:"string"}},exportName:"agentThread",filePath:"agents",kind:"query",returnType:"Record<string, unknown> | undefined"}];for(const a of e)a.voice&&r.push({args:{threadKey:{kind:"string"}},exportName:`${a.exportName}Voice`,filePath:"agents",kind:"stream",returnType:"Record<string, unknown>"});return r.filter(a=>!n.has(a.exportName))},Sn=(e,t)=>{if(e.length===0)return[];const n=new Set(t.filter(r=>S(r.filePath)==="mutators").map(r=>r.exportName));return e.filter(r=>!n.has(r.exportName)).map(r=>({args:r.args,exportName:r.exportName,filePath:r.filePath,kind:"mutation",returnType:r.returnType}))},Rn=e=>{const t=e.filter(s=>s.stream);if(t.length===0)return{block:"",body:""};const n=new Map;for(const s of t){const i=n.get(s.filePath)??[];i.push(s),n.set(s.filePath,i)}const r=[...n.entries()].toSorted(([s],[i])=>s.localeCompare(i)),a=r.map(([s,i])=>{const l=i.map(u=>{const p=Me(u.chunkType??"unknown");return` ${D(u.exportName)}: HttpStreamRef<${p}, ${me(u.searchParams)}, ${me(u.params)}>;`}).join(`
284
- `);return` ${D(S(s))}: {
282
+ `}},On=(e,t)=>{if(!e)return{importLine:"",lines:"",prelude:""};const n=t.find(r=>S(r.filePath)==="sandbox"&&r.exportName==="invoke");if(n)throw new Z("INTERNAL",`@lunora/codegen: "sandbox:invoke" is reserved for the batteries-included sandbox tool dispatcher (browserTool/containerTool) — rename the "invoke" export in ${n.filePath}`);return{importLine:`import { sandboxComponent } from "@lunora/agent/component";
283
+ `,lines:' "sandbox:invoke": lunoraSandbox.invoke as unknown as RegisteredLunoraFunction,',prelude:"\n/**\n * The `@lunora/agent` sandbox dispatcher — auto-registered because `lunora/`\n * imports a sandbox tool (`browserTool`/`containerTool`). The batteries-included\n * tools dispatch to this internal action, which runs on an action ctx carrying\n * `ctx.browser` + `ctx.containers` (the durable tool step itself has neither).\n */\nconst lunoraSandbox = sandboxComponent();\n"}},Tn=(e,t)=>{if(e.length===0)return[];const n=dt(t),r=[{args:{key:{kind:"string"},limit:{inner:{kind:"number"},kind:"optional"}},exportName:"agentMessages",filePath:"agents",kind:"query",returnType:"Record<string, unknown>[]"},{args:{decision:{kind:"union",members:[{kind:"literal",literalValue:'"approve"'},{kind:"literal",literalValue:'"reject"'}]},instanceId:{kind:"string"},note:{inner:{kind:"string"},kind:"optional"},threadKey:{kind:"string"},toolCallId:{kind:"string"}},exportName:"agentResolveApproval",filePath:"agents",kind:"mutation",returnType:"{ resolved: boolean }"},{args:{agent:{kind:"string"},input:{kind:"string"},threadKey:{kind:"string"},title:{inner:{kind:"string"},kind:"optional"}},exportName:"agentRun",filePath:"agents",kind:"mutation",returnType:"{ id: string; threadKey: string }"},{args:{key:{kind:"string"}},exportName:"agentState",filePath:"agents",kind:"query",returnType:"Record<string, unknown> | undefined"},{args:{key:{kind:"string"}},exportName:"agentThread",filePath:"agents",kind:"query",returnType:"Record<string, unknown> | undefined"}];for(const a of e)a.voice&&r.push({args:{threadKey:{kind:"string"}},exportName:`${a.exportName}Voice`,filePath:"agents",kind:"stream",returnType:"Record<string, unknown>"});return r.filter(a=>!n.has(a.exportName))},An=(e,t)=>{if(e.length===0)return[];const n=new Set(t.filter(r=>S(r.filePath)==="mutators").map(r=>r.exportName));return e.filter(r=>!n.has(r.exportName)).map(r=>({args:r.args,exportName:r.exportName,filePath:r.filePath,kind:"mutation",returnType:r.returnType}))},Ln=e=>{const t=e.filter(i=>i.stream);if(t.length===0)return{block:"",body:""};const n=new Map;for(const i of t){const s=n.get(i.filePath)??[];s.push(i),n.set(i.filePath,s)}const r=[...n.entries()].toSorted(([i],[s])=>i.localeCompare(s)),a=r.map(([i,s])=>{const l=s.map(u=>{const p=Me(qe(u.chunkType??"unknown",u.filePath));return` ${D(u.exportName)}: HttpStreamRef<${p}, ${me(u.searchParams)}, ${me(u.params)}>;`}).join(`
284
+ `);return` ${D(S(i))}: {
285
285
  ${l}
286
286
  };`}).join(`
287
- `),o=r.map(([s,i])=>{const l=i.map(u=>` ${D(u.exportName)}: { method: ${JSON.stringify(u.method)}, path: ${JSON.stringify(u.path)} },`).join(`
288
- `);return` ${D(S(s))}: {
287
+ `),o=r.map(([i,s])=>{const l=s.map(u=>` ${D(u.exportName)}: { method: ${JSON.stringify(u.method)}, path: ${JSON.stringify(u.path)} },`).join(`
288
+ `);return` ${D(S(i))}: {
289
289
  ${l}
290
290
  },`}).join(`
291
291
  `);return{block:`
@@ -297,15 +297,15 @@ ${a}
297
297
  export const httpStreams: HttpStreamsRef = {
298
298
  ${o}
299
299
  };
300
- `,body:a}},br=e=>{const{agents:t=[],functions:n,httpRoutes:r=[],mutators:a=[],useUmbrella:o=!1,workflows:s=[]}=e,i=H(o),l=[...n.filter($=>$.visibility!=="internal"),...$n(t,n),...Sn(a,n)],u=n.filter($=>$.visibility==="internal"),p=ze(l),f=ze(u),y=Rn(r),R=`${p}
300
+ `,body:a}},vr=e=>{const{agents:t=[],functions:n,httpRoutes:r=[],mutators:a=[],useUmbrella:o=!1,workflows:i=[]}=e,s=H(o),l=[...n.filter($=>$.visibility!=="internal"),...Tn(t,n),...An(a,n)],u=n.filter($=>$.visibility==="internal"),p=Xe(l),f=Xe(u),y=Ln(r),R=`${p}
301
301
  ${f}
302
- ${y.body}`,d=qe(R),c=d.length>0?`
302
+ ${y.body}`,d=Be(R),c=d.length>0?`
303
303
  import type { ${d.join(", ")} } from "./dataModel.js";
304
304
  `:"",g=p?`
305
305
  ${p}
306
306
  `:"",b=f?`
307
307
  ${f}
308
- `:"",x=yn(s,t),v=`export interface ApiTypes {${g}}
308
+ `:"",x=$n(i,t),v=`export interface ApiTypes {${g}}
309
309
 
310
310
  export const api = anyApi as unknown as ApiTypes;
311
311
 
@@ -313,10 +313,10 @@ export const api = anyApi as unknown as ApiTypes;
313
313
  export interface InternalApiTypes {${b}}
314
314
 
315
315
  export const internal = anyApi as unknown as InternalApiTypes;
316
- ${x.block}${y.block}`,A=[...v.includes("FunctionReference<")?["FunctionReference"]:[],...y.block===""?[]:["HttpStreamRef"]],N=A.length>0?`import type { ${A.join(", ")} } from "${i.client}";
317
- `:"";return at(`${k}import { anyApi } from "${i.serverTypes}";
316
+ ${x.block}${y.block}`,O=[...v.includes("FunctionReference<")?["FunctionReference"]:[],...y.block===""?[]:["HttpStreamRef"]],N=O.length>0?`import type { ${O.join(", ")} } from "${s.client}";
317
+ `:"";return lt(`${k}import { anyApi } from "${s.client}";
318
318
  ${N}${x.importLine}${c}
319
- ${v}`,o)},yr=e=>e?`${k}import { createSeedClient as createSeedClientBase } from "@lunora/seed";
319
+ ${v}`,o)},$r=e=>e?`${k}import { createSeedClient as createSeedClientBase } from "@lunora/seed";
320
320
  import type { SeedClient, SeedClientOptions } from "@lunora/seed";
321
321
 
322
322
  import schema from "../schema.js";
@@ -333,7 +333,7 @@ import type { InsertModel } from "./dataModel.js";
333
333
  * const { posts } = await seed.posts((x) => x([10, 20]));
334
334
  */
335
335
  export const createSeedClient = (options?: SeedClientOptions): SeedClient<InsertModel> => createSeedClientBase<InsertModel>(schema, options);
336
- `:"",wr=(e,t,n=!1)=>{if(e.length===0||!t)return"";const r=H(n),a=l=>l.table===void 0?"Row":`Doc<${JSON.stringify(l.table)}> & Row`,o=e.map(l=>{m(l.exportName,"shape export name");const u=a(l),p=me(l.args),f=Object.keys(l.args).length>0,y=f?` args: ${p};`:` args?: ${p};`,R=f?`(args: ${p}) => void`:`(args?: ${p}) => void`,d=`${l.exportName}CollectionOptions`;return`/** Options for the \`${l.exportName}\` shape binding. */
336
+ `:"",Sr=(e,t,n=!1)=>{if(e.length===0||!t)return"";const r=H(n),a=l=>l.table===void 0?"Row":`Doc<${JSON.stringify(l.table)}> & Row`,o=e.map(l=>{m(l.exportName,"shape export name");const u=a(l),p=me(l.args),f=Object.keys(l.args).length>0,y=f?` args: ${p};`:` args?: ${p};`,R=f?`(args: ${p}) => void`:`(args?: ${p}) => void`,d=`${l.exportName}CollectionOptions`;return`/** Options for the \`${l.exportName}\` shape binding. */
337
337
  export interface ${Ee(d)} {
338
338
  ${y}
339
339
  /**
@@ -379,15 +379,15 @@ export const ${l.exportName}Collection = (
379
379
  return { checkpoints, collection: createCollection(config), scope };
380
380
  };`}).join(`
381
381
 
382
- `),s=qe(o),i=s.length>0?`import type { ${s.join(", ")} } from "./dataModel.js";
382
+ `),i=Be(o),s=i.length>0?`import type { ${i.join(", ")} } from "./dataModel.js";
383
383
  `:"";return`${k}import type { LunoraClient, SubscriptionError } from "${r.client}";
384
384
  import { lunoraCollectionOptions } from "@lunora/db/collections";
385
385
  import type { CheckpointRegistry, LunoraCollectionOptions, Row } from "@lunora/db";
386
386
  import type { Collection } from "@tanstack/db";
387
387
  import { createCollection } from "@tanstack/db";
388
- ${i}
388
+ ${s}
389
389
  ${o}
390
- `},Nn=(e,t)=>`lunora_${S(e)}_${String(t)}`,On=`const callRegistered = async <R>(context: CallerCtx, functionPath: string, args: Record<string, unknown> | undefined): Promise<R> => {
390
+ `},Cn=(e,t)=>`lunora_${S(e)}_${String(t)}`,In=`const callRegistered = async <R>(context: CallerCtx, functionPath: string, args: Record<string, unknown> | undefined): Promise<R> => {
391
391
  const registered = LUNORA_FUNCTIONS[functionPath];
392
392
 
393
393
  if (!registered) {
@@ -395,30 +395,30 @@ ${o}
395
395
  }
396
396
 
397
397
  return (await registered.handler(context, args ?? {})) as R;
398
- };`,An=(e,t,n=[],r=[])=>{const a=new Map,o=d=>{a.has(d)||a.set(d,Nn(d,a.size))};for(const d of e)o(d.filePath);for(const d of t)o(d.filePath);for(const d of n)o(d.filePath);for(const d of r)o(d.filePath);const s=[...a.entries()].map(([d,c])=>{if(!ln.test(d))throw new Z("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(d)}`);return`import * as ${c} from "../${d}.js";`}).join(`
399
- `),i=e.map(d=>` "${S(d.filePath)}:${d.exportName}": ${a.get(d.filePath)??""}.${d.exportName} as unknown as RegisteredLunoraFunction,`).join(`
398
+ };`,Dn=(e,t,n=[],r=[])=>{const a=new Map,o=d=>{a.has(d)||a.set(d,Cn(d,a.size))};for(const d of e)o(d.filePath);for(const d of t)o(d.filePath);for(const d of n)o(d.filePath);for(const d of r)o(d.filePath);const i=[...a.entries()].map(([d,c])=>{if(!pn.test(d))throw new Z("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(d)}`);return`import * as ${c} from "../${d}.js";`}).join(`
399
+ `),s=e.map(d=>` "${S(d.filePath)}:${d.exportName}": ${a.get(d.filePath)??""}.${d.exportName} as unknown as RegisteredLunoraFunction,`).join(`
400
400
  `),l=t.map(d=>` ${JSON.stringify(d.id)}: ${a.get(d.filePath)??""}.${d.exportName} as unknown as RegisteredDataMigration,`).join(`
401
401
  `),u=n.map(d=>` "${S(d.filePath)}:${d.exportName}": ${a.get(d.filePath)??""}.${d.exportName} as unknown as RegisteredLunoraFunction,`).join(`
402
402
  `),p=r.map(d=>` "${d.exportName}": ${a.get(d.filePath)??""}.${d.exportName} as unknown as RegisteredShape,`).join(`
403
- `),f=n.map(d=>`${S(d.filePath)}:${d.exportName}`),y=[i,u].filter(d=>d.length>0).join(`
404
- `),R=e.map(d=>{if(d.lifecycle||Object.keys(d.args).length===0)return;const c=sn(d.args);return c===void 0?void 0:`installCompiledValidatorMap(${a.get(d.filePath)??""}.${d.exportName}.args, ${c});`}).filter(d=>d!==void 0).join(`
403
+ `),f=n.map(d=>`${S(d.filePath)}:${d.exportName}`),y=[s,u].filter(d=>d.length>0).join(`
404
+ `),R=e.map(d=>{if(d.lifecycle||Object.keys(d.args).length===0)return;const c=un(d.args);return c===void 0?void 0:`installCompiledValidatorMap(${a.get(d.filePath)??""}.${d.exportName}.args, ${c});`}).filter(d=>d!==void 0).join(`
405
405
  `);return{dispatchBody:y.length>0?`
406
406
  ${y}
407
- `:"",importBlock:s.length>0?`${s}
407
+ `:"",importBlock:i.length>0?`${i}
408
408
 
409
409
  `:"",installBlock:R,migrationBody:l.length>0?`
410
410
  ${l}
411
411
  `:"",mutatorPaths:f,shapeBody:p.length>0?`
412
412
  ${p}
413
- `:""}},Tn=e=>{const t=new Map;for(const a of e){const o=t.get(a.filePath)??[];o.push(a),t.set(a.filePath,o)}const n=[...t.entries()].toSorted(([a],[o])=>a.localeCompare(o)),r=n.map(([a,o])=>{const s=o.map(i=>{const l=me(i.args),u=l==="{}"?"?":"",p=Me(i.returnType);return i.kind==="stream"?` ${i.exportName}: (args${u}: ${l}) => Promise<AsyncIterable<${p}>>;`:` ${i.exportName}: (args${u}: ${l}) => Promise<${p}>;`}).join(`
413
+ `:""}},_n=e=>{const t=new Map;for(const a of e){const o=t.get(a.filePath)??[];o.push(a),t.set(a.filePath,o)}const n=[...t.entries()].toSorted(([a],[o])=>a.localeCompare(o)),r=n.map(([a,o])=>{const i=o.map(s=>{const l=me(s.args),u=l==="{}"?"?":"",p=Me(qe(s.returnType,s.filePath));return s.kind==="stream"?` ${s.exportName}: (args${u}: ${l}) => Promise<AsyncIterable<${p}>>;`:` ${s.exportName}: (args${u}: ${l}) => Promise<${p}>;`}).join(`
414
414
  `);return` ${D(S(a))}: {
415
- ${s}
416
- };`}).join(`
417
- `);return{implementation:n.map(([a,o])=>{const s=S(a),i=o.map(l=>` ${l.exportName}: (args) => callRegistered(context, "${s}:${l.exportName}", args),`).join(`
418
- `);return` ${D(s)}: {
419
415
  ${i}
416
+ };`}).join(`
417
+ `);return{implementation:n.map(([a,o])=>{const i=S(a),s=o.map(l=>` ${l.exportName}: (args) => callRegistered(context, "${i}:${l.exportName}", args),`).join(`
418
+ `);return` ${D(i)}: {
419
+ ${s}
420
420
  },`}).join(`
421
- `),types:r}},Ln=(e,t=[])=>{const n=new Set;for(const r of e.tables)for(const a of Object.values(r.shape)){const o=a.kind==="optional"&&a.inner?a.inner:a;o.kind==="storage"&&typeof o.bucket=="string"&&o.bucket!==""&&n.add(o.bucket)}for(const r of t)r!==""&&r!=="default"&&n.add(r);return["default",...[...n].toSorted((r,a)=>r.localeCompare(a))]},xr=({agents:e=[],containers:t=[],env:n,hasAccessFacade:r=!1,hasAi:a=!1,hasAnalytics:o=!1,hasBrowser:s=!1,hasFlags:i=!1,hasHyperdrive:l=!1,hasImages:u=!1,hasKv:p=!1,hasNotify:f=!1,hasPayments:y=!1,hasPipelines:R=!1,hasR2sql:d=!1,hasX402:c=!1,identity:g,queues:b=[],schema:x,storageRuleBuckets:v=[],useUmbrella:A=!1,workflows:N=[]}={})=>{const $=H(A),w=Ln(x??{tables:[]},v).map(h=>JSON.stringify(h)).join(" | "),E=a?`import type { LunoraAi } from "@lunora/ai";
421
+ `),types:r}},Pn=(e,t=[])=>{const n=new Set;for(const r of e.tables)for(const a of Object.values(r.shape)){const o=a.kind==="optional"&&a.inner?a.inner:a;o.kind==="storage"&&typeof o.bucket=="string"&&o.bucket!==""&&n.add(o.bucket)}for(const r of t)r!==""&&r!=="default"&&n.add(r);return["default",...[...n].toSorted((r,a)=>r.localeCompare(a))]},Rr=({agents:e=[],containers:t=[],env:n,hasAccessFacade:r=!1,hasAi:a=!1,hasAnalytics:o=!1,hasBrowser:i=!1,hasFlags:s=!1,hasHyperdrive:l=!1,hasImages:u=!1,hasKv:p=!1,hasNotify:f=!1,hasPayments:y=!1,hasPipelines:R=!1,hasR2sql:d=!1,hasX402:c=!1,identity:g,queues:b=[],schema:x,storageRuleBuckets:v=[],useUmbrella:O=!1,workflows:N=[]}={})=>{const $=H(O),w=Pn(x??{tables:[]},v).map(h=>JSON.stringify(h)).join(" | "),E=a?`import type { LunoraAi } from "@lunora/ai";
422
422
  `:"",ee=a?`
423
423
  readonly ai: LunoraAi;`:"",F=y?`import type { LunoraPayment } from "@lunora/payment";
424
424
  `:"",te=y?`
@@ -428,12 +428,12 @@ ${i}
428
428
  `:"",z=t.length>0?`
429
429
  readonly containers: {${t.map(h=>`
430
430
  readonly ${h.exportName}: ContainerAccessor;`).join("")}
431
- };`:"",L=[...a?[" /** Workers AI binding (the conventional `env.AI`), narrowing `ctx.ai`. */\n readonly AI?: unknown;"]:[],...t.map(h=>(m(h.bindingName,`container binding "${h.bindingName}"`),` /** Durable Object namespace for the \`${h.exportName}\` container. */
431
+ };`:"",A=[...a?[" /** Workers AI binding (the conventional `env.AI`), narrowing `ctx.ai`. */\n readonly AI?: unknown;"]:[],...t.map(h=>(m(h.bindingName,`container binding "${h.bindingName}"`),` /** Durable Object namespace for the \`${h.exportName}\` container. */
432
432
  readonly ${h.bindingName}?: unknown;`)),...N.map(h=>(m(h.bindingName,`workflow binding "${h.bindingName}"`),` /** Workflow binding for the \`${h.exportName}\` workflow. */
433
433
  readonly ${h.bindingName}?: unknown;`)),...b.map(h=>(m(h.bindingName,`queue binding "${h.bindingName}"`),` /** Queue producer binding for the \`${h.exportName}\` queue. */
434
434
  readonly ${h.bindingName}?: unknown;`)),...e.map(h=>(m(h.bindingName,`agent binding "${h.bindingName}"`),` /** Workflow binding for the \`${h.exportName}\` agent. */
435
435
  readonly ${h.bindingName}?: unknown;`))].join(`
436
- `),_=`
436
+ `),I=`
437
437
 
438
438
  /**
439
439
  * This project's Cloudflare bindings, as far as codegen can discover them from
@@ -446,18 +446,18 @@ ${i}
446
446
  * surface, so treat them as \`Fetcher\`/\`Service<unknown>\` and cast.
447
447
  */
448
448
  export interface CloudflareBindings {
449
- readonly [binding: string]: unknown;${L?`
450
- ${L}`:""}
449
+ readonly [binding: string]: unknown;${A?`
450
+ ${A}`:""}
451
451
  }
452
452
 
453
453
  /** Alias for {@link CloudflareBindings} — the typed shape of \`env\`. */
454
- export type Env = CloudflareBindings;`,M=(h,_e)=>_e?Zt.get(h)?.field??"":"",re=M("kv",p),ae=M("analytics",o),xe=M("hyperdrive",l),ke=M("browser",s),ve=M("images",u),oe=M("pipelines",R),K=M("r2sql",d),P=(x?.vectorIndexes.length??0)>0,Q=P?' | "vectors"':"",X=P?`
455
- readonly vectors: VectorSearch<VectorIndexName>;`:"",ie=P?`
456
- readonly vectors: VectorSearchReader<VectorIndexName>;`:"",V=P?`import type { VectorSearch, VectorSearchReader } from "${$.server}";
454
+ export type Env = CloudflareBindings;`,M=(h,De)=>De?rn.get(h)?.field??"":"",re=M("kv",p),ae=M("analytics",o),xe=M("hyperdrive",l),ke=M("browser",i),ve=M("images",u),oe=M("pipelines",R),K=M("r2sql",d),P=(x?.vectorIndexes.length??0)>0,Q=P?' | "vectors"':"",X=P?`
455
+ readonly vectors: VectorSearch<VectorIndexName>;`:"",se=P?`
456
+ readonly vectors: VectorSearchReader<VectorIndexName>;`:"",J=P?`import type { VectorSearch, VectorSearchReader } from "${$.server}";
457
457
  import type { VectorIndexName } from "./dataModel.js";
458
458
  `:"",j=r?`
459
459
  /** Verified Cloudflare Access identity — a synchronous facade over the resolved claims (email / groups / hasGroup / claims). Anonymous when no Access token is present. */
460
- readonly access: import("@lunora/cloudflare-access/context").AccessFacade;`:"",W=i?`
460
+ readonly access: import("@lunora/cloudflare-access/context").AccessFacade;`:"",W=s?`
461
461
  /** Feature-flag evaluation (OpenFeature). Reads are memoized per request; evaluations never throw — a provider error resolves to the supplied default. */
462
462
  readonly flags: import("${$.flags}").LunoraFlags;`:"",U=f?`
463
463
  /** 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. */
@@ -479,9 +479,9 @@ export interface LunoraWorkflows {
479
479
  ${N.map(h=>` get(name: ${JSON.stringify(h.exportName)}): WorkflowHandle<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${h.exportName}>>;`).join(`
480
480
  `)}
481
481
  }`:"",fe=q?' | "workflows"':"",be=q?`
482
- readonly workflows: LunoraWorkflows;`:"",se=b.length>0,Se=se?`import type { QueueProducer } from "@lunora/queue";
482
+ readonly workflows: LunoraWorkflows;`:"",ie=b.length>0,Se=ie?`import type { QueueProducer } from "@lunora/queue";
483
483
  import type * as lunoraQueueDefinitions from "../queues.js";
484
- `:"",Re=se?`
484
+ `:"",Re=ie?`
485
485
 
486
486
  /** Message body type carried by a \`defineQueue\` definition (its phantom \`__lunoraBody\`). */
487
487
  type QueueBodyOf<Definition> = Definition extends { __lunoraBody?: infer Body } ? (unknown extends Body ? unknown : NonNullable<Body>) : unknown;
@@ -490,7 +490,7 @@ type QueueBodyOf<Definition> = Definition extends { __lunoraBody?: infer Body }
490
490
  export interface LunoraQueues {
491
491
  ${b.map(h=>` readonly ${h.exportName}: QueueProducer<QueueBodyOf<typeof lunoraQueueDefinitions.${h.exportName}>>;`).join(`
492
492
  `)}
493
- }`:"",ye=se?`
493
+ }`:"",ye=ie?`
494
494
  readonly queues: LunoraQueues;`:"",le=e.length>0,Ne=le?`import type { AgentHandle } from "@lunora/agent";
495
495
  `:"",Oe=le?`
496
496
 
@@ -499,9 +499,9 @@ export interface LunoraAgents {
499
499
  ${e.map(h=>(m(h.exportName,`agent export "${h.exportName}"`),` readonly ${h.exportName}: AgentHandle;`)).join(`
500
500
  `)}
501
501
  }`:"",we=le?`
502
- readonly agents: LunoraAgents;`:"",Ae=g?`import type { InferIdentity } from "${$.server}";
502
+ readonly agents: LunoraAgents;`:"",Te=g?`import type { InferIdentity } from "${$.server}";
503
503
  import type * as lunoraIdentityContract from "../identity.js";
504
- `:"",Te=g?`
504
+ `:"",Ae=g?`
505
505
 
506
506
  /** 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. */
507
507
  export type Identity = InferIdentity<typeof lunoraIdentityContract.${g.exportName}>;
@@ -509,7 +509,7 @@ export type Identity = InferIdentity<typeof lunoraIdentityContract.${g.exportNam
509
509
  /** \`ctx.auth\` narrowed so \`getIdentity()\` resolves the declared {@link Identity} contract instead of the untyped claim bag. */
510
510
  type NarrowedAuth = Omit<QueryCtxBase["auth"], "getIdentity"> & { getIdentity: () => Promise<Identity | null> };`:"",de=g?' | "auth"':"",ce=g?`
511
511
  readonly auth: NarrowedAuth;`:"",Le=g?", Identity":"",Ce=n?`import type * as lunoraEnvContract from "../env.js";
512
- `:"",De=n?`
512
+ `:"",Ie=n?`
513
513
 
514
514
  /** This app's declared env contract (\`defineEnv\` in \`lunora/env.ts\`) — the validated, coercion-aware shape of \`ctx.env\`. */
515
515
  export type LunoraEnv = ReturnType<typeof lunoraEnvContract.${n.exportName}>;`:"",ue=n?' | "env"':"",pe=n?"\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`${k}import { createPolicyDsl, defineMutator as defineMutatorBase, initLunora, v as vBase } from "${$.server}";
@@ -535,12 +535,12 @@ import type {
535
535
  Validator,
536
536
  } from "${$.server}";
537
537
 
538
- import type { DataModel, DatabaseReaderFacade, DatabaseWriterFacade, Doc, Id as IdOfTable, OrmReader, OrmWriter, Relations, TableName } from "./dataModel.js";
539
- ${V}${E}${F}${ne}${T}${Y}${Se}${Ne}${Ae}${Ce}
538
+ import type { DataModel, DatabaseReaderFacade, DatabaseWriterFacade, Doc, GeoIndexNamesByTable, Id as IdOfTable, IndexNamesByTable, OrmReader, OrmWriter, Relations, SearchIndexNamesByTable, TableName } from "./dataModel.js";
539
+ ${J}${E}${F}${ne}${T}${Y}${Se}${Ne}${Te}${Ce}
540
540
  export type { AppTableName, DataModel, Doc, Id, TableName } from "./dataModel.js";
541
541
 
542
542
  /** Storage buckets this schema declares (\`v.storage("name")\`), narrowing \`ctx.storage.bucket(name)\`. */
543
- export type StorageBucketName = ${w};${_}${$e}${Re}${Oe}${Te}${De}
543
+ export type StorageBucketName = ${w};${I}${$e}${Re}${Oe}${Ae}${Ie}
544
544
 
545
545
  /**
546
546
  * Project-typed contexts. The base contexts from \`@lunora/server\` are
@@ -559,8 +559,17 @@ export type StorageBucketName = ${w};${_}${$e}${Re}${Oe}${Te}${De}
559
559
  * Intersected with the wide \`(string) => TableReader\` signature so the bound
560
560
  * \`ctx.db\` is still structurally assignable to schema-agnostic consumers that
561
561
  * call \`db.query(someString)\` (e.g. \`@lunora/ratelimit\`'s \`createDbStore\`).
562
+ *
563
+ * The three index-name unions are what make \`.withIndex("by_TYPO")\` a compile
564
+ * error: each resolves to the table's declared names, or \`never\` when it
565
+ * declares none of that kind. Without them a renamed or dropped index left
566
+ * every call site typechecking, and the query either threw at runtime or
567
+ * degraded silently to a full table scan.
562
568
  */
563
- type TypedTableQuery = (<T extends TableName>(table: T) => TableReader<Doc<T>>) & ((table: string) => TableReader);
569
+ type TypedTableQuery = (<T extends TableName>(
570
+ table: T,
571
+ ) => TableReader<Doc<T>, IndexNamesByTable[T], SearchIndexNamesByTable[T], GeoIndexNamesByTable[T]>) &
572
+ ((table: string) => TableReader);
564
573
 
565
574
  /**
566
575
  * The point read \`ctx.db.get(id)\`, bound to this schema: an \`Id<"table">\`
@@ -597,7 +606,7 @@ type TypedAsId = <T extends string>(tableName: AsIdTable<T>, id: string) => IdOf
597
606
  export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"${Q}${de}${ue}> {
598
607
  readonly db: Omit<DatabaseReader, "asId" | "query" | "get"> & DatabaseReaderFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
599
608
  readonly orm: OrmReader;
600
- readonly storage: ReadOnlyStorage<StorageBucketName>;${ie}${j}${re}${W}${U}${ae}${pe}${ce}
609
+ readonly storage: ReadOnlyStorage<StorageBucketName>;${se}${j}${re}${W}${U}${ae}${pe}${ce}
601
610
  }
602
611
 
603
612
  export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${Q}${fe}${de}${ue}> {
@@ -684,12 +693,12 @@ export const definePolicy = createPolicyDsl<DataModel, Relations${Le}>();
684
693
  export const v = vBase as unknown as Omit<typeof vBase, "id"> & {
685
694
  id: <T extends TableName>(table: T) => ColumnValidator<IdOfTable<T>, IdOfTable<T>>;
686
695
  };
687
- `},Cn=e=>{const t={connect:[],disconnect:[]};for(const n of e)n.lifecycle&&t[n.lifecycle].push(`${S(n.filePath)}:${n.exportName}`);return t},kr=e=>{const{agents:t=[],functions:n,migrations:r=[],mutators:a=[],shapes:o=[],useUmbrella:s=!1,usesSandbox:i=!1}=e,l=n.length>0,u=H(s),{dispatchBody:p,importBlock:f,installBlock:y,migrationBody:R,mutatorPaths:d,shapeBody:c}=An(n,r,a,o),g=kn(t,n),b=vn(i,n),x=[g.lines,b.lines].filter(_=>_.length>0).join(`
696
+ `},En=e=>{const t={connect:[],disconnect:[]};for(const n of e)n.lifecycle&&t[n.lifecycle].push(`${S(n.filePath)}:${n.exportName}`);return t},Nr=e=>{const{agents:t=[],functions:n,migrations:r=[],mutators:a=[],shapes:o=[],useUmbrella:i=!1,usesSandbox:s=!1}=e,l=n.length>0,u=H(i),{dispatchBody:p,importBlock:f,installBlock:y,migrationBody:R,mutatorPaths:d,shapeBody:c}=Dn(n,r,a,o),g=Nn(t,n),b=On(s,n),x=[g.lines,b.lines].filter(I=>I.length>0).join(`
688
697
  `);let v=p;x.length>0&&(v=p.length>0?`${p.trimEnd()}
689
698
  ${x}
690
699
  `:`
691
700
  ${x}
692
- `);const A=Cn(n),N=o.length>0?`import type { RegisteredShape } from "${u.server}";
701
+ `);const O=En(n),N=o.length>0?`import type { RegisteredShape } from "${u.server}";
693
702
  `:"",$=o.length>0?`
694
703
  /**
695
704
  * Replication-shape registry — one entry per \`defineShape\` in \`lunora/shapes.ts\`.
@@ -704,7 +713,7 @@ export const LUNORA_SHAPES: Record<string, RegisteredShape> = {${c}};
704
713
  * ShardDO's \`isCustomMutator\` override routes through the client-watermark push
705
714
  * protocol (\`x-lunora-client-id\`/\`x-lunora-client-seq\` ordering).
706
715
  */
707
- export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${d.map(_=>JSON.stringify(_)).join(", ")}]);
716
+ export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${d.map(I=>JSON.stringify(I)).join(", ")}]);
708
717
  `:"",E=y.length>0?`import { DEFER_VALIDATION as DEFER, installCompiledValidatorMap } from "${u.values}";
709
718
  `:"",ee=y.length>0?`
710
719
  /**
@@ -713,14 +722,14 @@ export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${d.map(_=>JSO
713
722
  * parser as a zero-allocation fast path; anything it can't model is deferred.
714
723
  */
715
724
  ${y}
716
- `:"",F=Tn(n),te=F.types?`
725
+ `:"",F=_n(n),te=F.types?`
717
726
  ${F.types}
718
727
  `:"",ne=F.implementation?`
719
728
  ${F.implementation}
720
- `:"",B=qe(F.types),T=B.length>0?`import type { ${B.join(", ")} } from "./dataModel.js";
721
- `:"",z=l?"context":"_context",L=l?`${On}
729
+ `:"",B=Be(F.types),T=B.length>0?`import type { ${B.join(", ")} } from "./dataModel.js";
730
+ `:"",z=l?"context":"_context",A=l?`${In}
722
731
 
723
- `:"";return at(`${k}${f}${g.importLine}${b.importLine}${E}${N}import { LunoraError } from "${u.server}";
732
+ `:"";return lt(`${k}${f}${g.importLine}${b.importLine}${E}${N}import { LunoraError } from "${u.server}";
724
733
  import type { ActionCtx, MutationCtx, QueryCtx } from "./server.js";
725
734
  ${T}
726
735
  /**
@@ -755,8 +764,8 @@ ${ee}${$}${w}
755
764
  * DO runs every hook under the socket's verified identity via system dispatch.
756
765
  */
757
766
  export const LUNORA_LIFECYCLE_HOOKS: { connect: readonly string[]; disconnect: readonly string[] } = {
758
- connect: [${A.connect.map(_=>JSON.stringify(_)).join(", ")}],
759
- disconnect: [${A.disconnect.map(_=>JSON.stringify(_)).join(", ")}],
767
+ connect: [${O.connect.map(I=>JSON.stringify(I)).join(", ")}],
768
+ disconnect: [${O.disconnect.map(I=>JSON.stringify(I)).join(", ")}],
760
769
  };
761
770
 
762
771
  /**
@@ -789,7 +798,7 @@ export type CallerCtx = ActionCtx | MutationCtx | QueryCtx;
789
798
  */
790
799
  export interface Caller {${te}}
791
800
 
792
- ${L}/** Build a {@link Caller} bound to \`context\` (typically a handler's \`ctx\`). */
801
+ ${A}/** Build a {@link Caller} bound to \`context\` (typically a handler's \`ctx\`). */
793
802
  export const createCaller = (${z}: CallerCtx): Caller => ({${ne}});
794
803
 
795
804
  /**
@@ -810,7 +819,7 @@ export interface RegisteredDataMigration {
810
819
  * shard DO's admin RPC and the CLI resolve migrations to run through this map.
811
820
  */
812
821
  export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${R}};
813
- `,s)},Dn=e=>{const t={};for(const n of e.tables){const r={};for(const[a,o]of Object.entries(n.shape)){const s=o.kind==="optional"&&o.inner?o.inner:o;s.kind==="id"&&s.tableName!==void 0&&(r[a]=s.tableName)}Object.keys(r).length>0&&(t[n.name]=r)}return t},_n=e=>{const t={};for(const n of e.tables){const r=[];for(const[a,o]of Object.entries(n.shape))(o.kind==="optional"&&o.inner?o.inner:o).kind==="storage"&&r.push(a);r.length>0&&(t[n.name]=r)}return t},In=e=>{const t={};for(const n of e.tables){const r=[...n.indexes.map(a=>({fields:[...a.fields],name:a.name,type:"index",...a.unique===!0?{unique:!0}:{}})),...n.searchIndexes.map(a=>({fields:[a.field,...a.filterFields??[]],name:a.name,type:"search"})),...(n.geoIndexes??[]).map(a=>({fields:[a.field],name:a.name,type:"geo"})),...n.rankIndexes.map(a=>({fields:a.sortBy.map(o=>o.field),name:a.name,type:"rank"})),...n.vectorIndexes.map(a=>({fields:a.field===void 0?[]:[a.field],name:a.name,type:"vector"}))];r.length>0&&(t[n.name]=r)}return t},Pn=e=>{const t=[];for(const n of e.tables)!n.ttl||n.shardMode==="global"||t.push({...n.ttl.after===void 0?{}:{after:n.ttl.after},field:n.ttl.field,...n.softDelete?{softDeleteField:n.softDelete.field}:{},table:n.name});return t},En=e=>{const t={};for(const n of e.tables){const r=[{name:"_id",optional:!1,pk:!0,type:"id"},{name:"_creationTime",optional:!1,type:"number"}];for(const[a,o]of Object.entries(n.shape)){const s=o.kind==="optional"||!!o.column?.hasDefault,i=o.kind==="optional"&&o.inner?o.inner:o,l={name:a,optional:s,type:i.kind};i.kind==="id"&&i.tableName!==void 0&&(l.ref=i.tableName),i.kind==="storage"&&(l.isStorage=!0),r.push(l)}t[n.name]=r}return t},Fn=e=>e?{importFragment:"serveRelationFanout, ",override:`
822
+ `,i)},Fn=e=>{const t={};for(const n of e.tables){const r={};for(const[a,o]of Object.entries(n.shape)){const i=o.kind==="optional"&&o.inner?o.inner:o;i.kind==="id"&&i.tableName!==void 0&&(r[a]=i.tableName)}Object.keys(r).length>0&&(t[n.name]=r)}return t},Mn=e=>{const t={};for(const n of e.tables){const r=[];for(const[a,o]of Object.entries(n.shape))(o.kind==="optional"&&o.inner?o.inner:o).kind==="storage"&&r.push(a);r.length>0&&(t[n.name]=r)}return t},qn=e=>{const t={};for(const n of e.tables){const r=[...n.indexes.map(a=>({fields:[...a.fields],name:a.name,type:"index",...a.unique===!0?{unique:!0}:{}})),...n.searchIndexes.map(a=>({fields:[a.field,...a.filterFields??[]],name:a.name,type:"search"})),...(n.geoIndexes??[]).map(a=>({fields:[a.field],name:a.name,type:"geo"})),...n.rankIndexes.map(a=>({fields:a.sortBy.map(o=>o.field),name:a.name,type:"rank"})),...n.vectorIndexes.map(a=>({fields:a.field===void 0?[]:[a.field],name:a.name,type:"vector"}))];r.length>0&&(t[n.name]=r)}return t},Bn=e=>{const t=[];for(const n of e.tables)!n.ttl||n.shardMode==="global"||t.push({...n.ttl.after===void 0?{}:{after:n.ttl.after},field:n.ttl.field,...n.softDelete?{softDeleteField:n.softDelete.field}:{},table:n.name});return t},jn=e=>{const t={};for(const n of e.tables){const r=[{name:"_id",optional:!1,pk:!0,type:"id"},{name:"_creationTime",optional:!1,type:"number"}];for(const[a,o]of Object.entries(n.shape)){const i=o.kind==="optional"||!!o.column?.hasDefault,s=o.kind==="optional"&&o.inner?o.inner:o,l={name:a,optional:i,type:s.kind};s.kind==="id"&&s.tableName!==void 0&&(l.ref=s.tableName),s.kind==="storage"&&(l.isStorage=!0),r.push(l)}t[n.name]=r}return t},Wn=e=>e?{importFragment:"serveRelationFanout, ",override:`
814
823
  protected override async runRelationFanoutRead(functionPath: string, args: Record<string, unknown>): Promise<unknown> {
815
824
  this.ensureMigrated();
816
825
 
@@ -818,7 +827,7 @@ export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${R}}
818
827
 
819
828
  return serveRelationFanout(schema as unknown as SchemaLike, db, functionPath, args);
820
829
  }
821
- `}:{importFragment:"",override:""},Mn=e=>{if(!e)return{build:"",configField:"",contextField:"",stub:""};const t='throw new Error("ctx.ai: no AI binding found. Add an \\`ai\\` binding (env.AI) to wrangler.jsonc, or pass \\`ai\\` to createShardDO().");';return{build:`
830
+ `}:{importFragment:"",override:""},Un=e=>{if(!e)return{build:"",configField:"",contextField:"",stub:""};const t='throw new Error("ctx.ai: no AI binding found. Add an \\`ai\\` binding (env.AI) to wrangler.jsonc, or pass \\`ai\\` to createShardDO().");';return{build:`
822
831
  const aiBinding = config.ai?.(env) ?? (env as Record<string, unknown>).AI;
823
832
  // Correlate AI-Gateway-routed calls with the Lunora trace: thread the
824
833
  // function path + trace id into createAi, which folds them into the
@@ -849,7 +858,7 @@ const aiStub: LunoraAi = {
849
858
  ${t}
850
859
  }) as unknown as LunoraAi["workersai"],
851
860
  };
852
- `}},I={build:"",configField:"",contextField:"",importLines:[],stub:""},qn=e=>{if(!e)return I;const t='throw new Error("ctx.kv: no KV binding found. Add a \\`kv_namespaces\\` binding (env.KV) to wrangler.jsonc, or pass \\`kv\\` to createShardDO().");';return{build:`
861
+ `}},_={build:"",configField:"",contextField:"",importLines:[],stub:""},Kn=e=>{if(!e)return _;const t='throw new Error("ctx.kv: no KV binding found. Add a \\`kv_namespaces\\` binding (env.KV) to wrangler.jsonc, or pass \\`kv\\` to createShardDO().");';return{build:`
853
862
  const kvBinding = config.kv?.(env) ?? (env as Record<string, unknown>).KV;
854
863
  const kv: Kv = kvBinding ? createKv({ namespace: kvBinding as KVNamespaceLike }) : kvStub;
855
864
  `,configField:`
@@ -875,7 +884,7 @@ const kvStub: Kv = {
875
884
  ${t}
876
885
  },
877
886
  };
878
- `}},Bn=(e,t)=>e?{build:`
887
+ `}},Qn=(e,t)=>e?{build:`
879
888
  const flags: import("${t}").LunoraFlags = createFlags({
880
889
  hooks: flagsConfig.hooks,
881
890
  logger: flagsConfig.logger,
@@ -884,23 +893,23 @@ const kvStub: Kv = {
884
893
  });
885
894
  `,configField:`
886
895
  flags?: (env: Record<string, unknown>) => import("${t}").Provider;`,contextField:`
887
- flags,`,importLines:[`import { createFlags } from "${t}";`,'import flagsConfig from "../flags.js";'],stub:""}:I,jn=e=>e?{build:`
896
+ flags,`,importLines:[`import { createFlags } from "${t}";`,'import flagsConfig from "../flags.js";'],stub:""}:_,Jn=e=>e?{build:`
888
897
  const { notify, push } = createNotify(notifyConfig, env, { log, metrics });
889
898
  `,configField:"",contextField:`
890
899
  notify,
891
- push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:I,Wn=e=>e?{build:`
900
+ push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:_,Vn=e=>e?{build:`
892
901
  const envConfig = lunoraEnvContract.${e.exportName}(env);
893
902
  `,configField:"",contextField:`
894
- env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:I,Un=e=>e?{build:`
903
+ env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:_,Gn=e=>e?{build:`
895
904
  const access = accessFacade(identity, userId);
896
905
  `,configField:"",contextField:`
897
- access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:I,Kn=(e,t,n)=>{if(!t)return{constant:"",evaluateOverride:"",subscriptionOverride:""};const r=i=>`
906
+ access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:_,Hn=(e,t,n)=>{if(!t)return{constant:"",evaluateOverride:"",subscriptionOverride:""};const r=s=>`
898
907
  const env = (this.env ?? {}) as Record<string, unknown>;
899
908
  const flags: import("${n}").LunoraFlags = createFlags({
900
909
  hooks: flagsConfig.hooks,
901
910
  logger: flagsConfig.logger,
902
911
  provider: () => config.flags?.(env) ?? flagsConfig.provider(env),
903
- targetingKey: ${i},
912
+ targetingKey: ${s},
904
913
  });`,a=`
905
914
  /** Statically-discovered feature flags (\`ctx.flags.<type>("key")\` reads) served via \`__lunora_admin__:listFlags\` + the reactive \`__lunora_flags__:\` channel. */
906
915
  const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number" | "object" | "string" }> = ${JSON.stringify(e,void 0,4)};
@@ -925,7 +934,7 @@ const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number"
925
934
 
926
935
  return { configured: true, flags: evaluations };
927
936
  }
928
- `,s=`
937
+ `,i=`
929
938
  protected override runFlagSubscriptionRead(_functionPath: string, args: Record<string, unknown>, identity?: { identity?: Record<string, unknown>; userId?: string }): Promise<unknown> {${r("() => flagsConfig.identify?.({ identity: identity?.identity ?? null, userId: identity?.userId ?? null })")}
930
939
  const key = typeof args.key === "string" ? args.key : "";
931
940
 
@@ -958,7 +967,7 @@ const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number"
958
967
 
959
968
  return flags.boolean(key, typeof args.default === "boolean" ? args.default : false, context);
960
969
  }
961
- `;return{constant:a,evaluateOverride:o,subscriptionOverride:s}},Qn=e=>{if(!e)return I;const t='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().");';return{build:`
970
+ `;return{constant:a,evaluateOverride:o,subscriptionOverride:i}},zn=e=>{if(!e)return _;const t='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().");';return{build:`
962
971
  const analyticsBinding = config.analytics?.(env) ?? (env as Record<string, unknown>).ANALYTICS;
963
972
  const analytics: AnalyticsClient = analyticsBinding ? createAnalytics(analyticsBinding as AnalyticsEngineDatasetLike) : analyticsStub;
964
973
  `,configField:`
@@ -972,7 +981,7 @@ const analyticsStub: AnalyticsClient = {
972
981
  ${t}
973
982
  },
974
983
  };
975
- `}},Vn=e=>{if(!e)return I;const t='throw new Error("ctx.images: no Images binding found. Add an \\`images\\` binding (env.IMAGES) to wrangler.jsonc, or pass \\`images\\` to createShardDO().");';return{build:`
984
+ `}},Xn=e=>{if(!e)return _;const t='throw new Error("ctx.images: no Images binding found. Add an \\`images\\` binding (env.IMAGES) to wrangler.jsonc, or pass \\`images\\` to createShardDO().");';return{build:`
976
985
  const imagesBinding = config.images?.(env) ?? (env as Record<string, unknown>).IMAGES;
977
986
  const images: Images = imagesBinding ? createImages({ binding: imagesBinding as ImagesBindingLike }) : imagesStub;
978
987
  `,configField:`
@@ -986,7 +995,7 @@ const imagesStub: Images = {
986
995
  ${t}
987
996
  },
988
997
  };
989
- `}},Jn=e=>e?{build:`
998
+ `}},Yn=e=>e?{build:`
990
999
  const sql: SqlClient = config.sql ? config.sql(env) : sqlStub;
991
1000
  `,configField:`
992
1001
  sql?: (env: Record<string, unknown>) => SqlClient;`,contextField:`
@@ -996,7 +1005,7 @@ const sqlStub: SqlClient = {
996
1005
  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))\\\`.");
997
1006
  },
998
1007
  };
999
- `}:I,Gn=e=>{if(!e)return I;const t="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.\");";return{build:`
1008
+ `}:_,Zn=e=>{if(!e)return _;const t="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.\");";return{build:`
1000
1009
  const browser: Browser = config.browser ? config.browser(env) : browserStub;
1001
1010
  `,configField:`
1002
1011
  browser?: (env: Record<string, unknown>) => Browser;`,contextField:`
@@ -1024,7 +1033,7 @@ const browserStub: Browser = {
1024
1033
  ${t}
1025
1034
  },
1026
1035
  };
1027
- `}},Hn=e=>{if(!e)return I;const t='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().");';return{build:`
1036
+ `}},er=e=>{if(!e)return _;const t='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().");';return{build:`
1028
1037
  const r2sqlEnv = env as Record<string, unknown>;
1029
1038
  const r2sqlAccountId = (r2sqlEnv.R2_SQL_ACCOUNT_ID ?? r2sqlEnv.CLOUDFLARE_ACCOUNT_ID) as string | undefined;
1030
1039
  const r2sqlToken = r2sqlEnv.R2_SQL_TOKEN as string | undefined;
@@ -1056,7 +1065,7 @@ const r2sqlStub: R2SqlClient = {
1056
1065
  ${t}
1057
1066
  },
1058
1067
  };
1059
- `}},zn=e=>e?{build:`
1068
+ `}},tr=e=>e?{build:`
1060
1069
  const pipelinesBinding = config.pipelines?.(env) ?? (env as Record<string, unknown>).PIPELINES;
1061
1070
  const pipelines: PipelineClient = pipelinesBinding ? createPipelines({ binding: pipelinesBinding as PipelineBindingLike }) : pipelinesStub;
1062
1071
  `,configField:`
@@ -1066,7 +1075,7 @@ const pipelinesStub: PipelineClient = {
1066
1075
  throw new Error("ctx.pipelines: no Pipelines binding found. Add a \\\`pipelines\\\` binding (env.PIPELINES) to wrangler.jsonc, or pass \\\`pipelines\\\` to createShardDO().");
1067
1076
  },
1068
1077
  };
1069
- `}:I,vr=(e,t)=>{if(e.length===0)return"";const n=t?`, ${JSON.stringify(t)}`:"",r=e.map(o=>(m(o.exportName,`container export "${o.exportName}"`),m(o.className,`container class "${o.className}"`),`/** Container DO for the \`${o.exportName}\` definition (binding \`${o.bindingName}\`). */
1078
+ `}:_,Or=(e,t)=>{if(e.length===0)return"";const n=t?`, ${JSON.stringify(t)}`:"",r=e.map(o=>(m(o.exportName,`container export "${o.exportName}"`),m(o.className,`container class "${o.className}"`),`/** Container DO for the \`${o.exportName}\` definition (binding \`${o.bindingName}\`). */
1070
1079
  export class ${o.className} extends LunoraContainer {
1071
1080
  public constructor(ctx: ConstructorParameters<typeof LunoraContainer>[0], env: Record<string, unknown>) {
1072
1081
  super(ctx, env, ${o.exportName}, "${o.exportName}"${n});
@@ -1091,7 +1100,7 @@ import { ${a} } from "../containers.js";
1091
1100
 
1092
1101
  export { ContainerProxy } from "@lunora/container/do";
1093
1102
 
1094
- ${r}`},Xn=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const r of e)m(r.exportName,`container export "${r.exportName}"`),m(r.bindingName,`container binding "${r.bindingName}"`);const n=e.map(r=>{const a=r.maxInstances===void 0?"":`, maxInstances: ${String(r.maxInstances)}`;return` { binding: "${r.bindingName}", exportName: "${r.exportName}"${a} },`}).join(`
1103
+ ${r}`},nr=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const r of e)m(r.exportName,`container export "${r.exportName}"`),m(r.bindingName,`container binding "${r.bindingName}"`);const n=e.map(r=>{const a=r.maxInstances===void 0?"":`, maxInstances: ${String(r.maxInstances)}`;return` { binding: "${r.bindingName}", exportName: "${r.exportName}"${a} },`}).join(`
1095
1104
  `);return{build:`
1096
1105
  const containers = createContainerContext(env, LUNORA_CONTAINERS, ${t?JSON.stringify(t):"undefined"}, this.getCurrentTraceparent());
1097
1106
  `,contextField:`
@@ -1100,7 +1109,7 @@ ${r}`},Xn=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[]
1100
1109
  const LUNORA_CONTAINERS: ReadonlyArray<ContainerBindingSpec> = [
1101
1110
  ${n}
1102
1111
  ];
1103
- `}},$r=e=>{if(e.length===0)return"";const t=e.map(r=>(m(r.exportName,`workflow export "${r.exportName}"`),m(r.className,`workflow class "${r.className}"`),`/** WorkflowEntrypoint for the \`${r.exportName}\` definition (binding \`${r.bindingName}\`). */
1112
+ `}},Tr=e=>{if(e.length===0)return"";const t=e.map(r=>(m(r.exportName,`workflow export "${r.exportName}"`),m(r.className,`workflow class "${r.className}"`),`/** WorkflowEntrypoint for the \`${r.exportName}\` definition (binding \`${r.bindingName}\`). */
1104
1113
  export class ${r.className} extends LunoraWorkflow<WorkflowParamsOf<typeof ${r.exportName}>, WorkflowOutputOf<typeof ${r.exportName}>> {
1105
1114
  public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
1106
1115
  super(ctx, env, ${r.exportName}, "${r.exportName}");
@@ -1128,15 +1137,15 @@ type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params
1128
1137
  /** Output type carried by a \`defineWorkflow\` definition (its phantom \`__output\`), so each entrypoint keeps the authored return type. */
1129
1138
  type WorkflowOutputOf<Definition> = Definition extends { __output?: infer Output } ? Output : unknown;
1130
1139
 
1131
- ${t}`},Sr=e=>{if(e.length===0)return"";const t=e.filter(a=>a.voice).length>0,n=e.map(a=>{m(a.exportName,`agent export "${a.exportName}"`),m(a.className,`agent class "${a.className}"`);const o=`/** WorkflowEntrypoint for the \`${a.exportName}\` agent (binding \`${a.bindingName}\`). */
1140
+ ${t}`},Ar=e=>{if(e.length===0)return"";const t=e.filter(a=>a.voice).length>0,n=e.map(a=>{m(a.exportName,`agent export "${a.exportName}"`),m(a.className,`agent class "${a.className}"`);const o=`/** WorkflowEntrypoint for the \`${a.exportName}\` agent (binding \`${a.bindingName}\`). */
1132
1141
  export class ${a.className} extends LunoraWorkflow<AgentRunInput, AgentRunResult> {
1133
1142
  public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
1134
1143
  super(ctx, env, compileAgentWorkflow(${a.exportName}, "${a.exportName}"), "${a.exportName}");
1135
1144
  }
1136
1145
  }
1137
- `;if(!a.voice)return o;const s=a.voiceClassName??"",i=a.voiceBindingName??"";m(s,`agent voice class "${s}"`);const l=`
1138
- /** Voice-session Durable Object for the \`${a.exportName}\` agent (binding \`${i}\`). */
1139
- export class ${s} extends VoiceSessionDO {
1146
+ `;if(!a.voice)return o;const i=a.voiceClassName??"",s=a.voiceBindingName??"";m(i,`agent voice class "${i}"`);const l=`
1147
+ /** Voice-session Durable Object for the \`${a.exportName}\` agent (binding \`${s}\`). */
1148
+ export class ${i} extends VoiceSessionDO {
1140
1149
  public constructor(ctx: ConstructorParameters<typeof VoiceSessionDO>[0], env: Record<string, unknown>) {
1141
1150
  super(ctx, env, ${a.exportName}, "${a.exportName}");
1142
1151
  }
@@ -1156,7 +1165,7 @@ import type { AgentRunInput, AgentRunResult } from "@lunora/agent";
1156
1165
 
1157
1166
  import { ${r} } from "../agents.js";
1158
1167
 
1159
- ${n}`},Rr=e=>{const t=e.filter(a=>a.mode==="push");if(t.length===0)return"";for(const a of t)m(a.exportName,`queue export "${a.exportName}"`);const n=t.map(a=>a.exportName).join(", "),r=t.map(a=>` ${JSON.stringify(a.name)}: { definition: ${a.exportName}, exportName: ${JSON.stringify(a.exportName)} },`).join(`
1168
+ ${n}`},Lr=e=>{const t=e.filter(a=>a.mode==="push");if(t.length===0)return"";for(const a of t)m(a.exportName,`queue export "${a.exportName}"`);const n=t.map(a=>a.exportName).join(", "),r=t.map(a=>` ${JSON.stringify(a.name)}: { definition: ${a.exportName}, exportName: ${JSON.stringify(a.exportName)} },`).join(`
1160
1169
  `);return`${k}/**
1161
1170
  * Push-consumer registry for the queues declared in \`lunora/queues.ts\`. The
1162
1171
  * composed worker's \`queue(batch, env, ctx)\` entry routes each delivered batch
@@ -1171,7 +1180,7 @@ import { ${n} } from "../queues.js";
1171
1180
  export const LUNORA_QUEUE_REGISTRY: QueueRegistry = {
1172
1181
  ${r}
1173
1182
  };
1174
- `},Yn=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`workflow export "${n.exportName}"`),m(n.bindingName,`workflow binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}" },`).join(`
1183
+ `},rr=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`workflow export "${n.exportName}"`),m(n.bindingName,`workflow binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}" },`).join(`
1175
1184
  `);return{build:`
1176
1185
  const workflows = createWorkflowContext(env, LUNORA_WORKFLOWS);
1177
1186
  `,contextField:`
@@ -1180,7 +1189,7 @@ ${r}
1180
1189
  const LUNORA_WORKFLOWS: ReadonlyArray<WorkflowBindingSpec> = [
1181
1190
  ${t}
1182
1191
  ];
1183
- `}},Zn=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`queue export "${n.exportName}"`),m(n.bindingName,`queue binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}", name: ${JSON.stringify(n.name)} },`).join(`
1192
+ `}},ar=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`queue export "${n.exportName}"`),m(n.bindingName,`queue binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}", name: ${JSON.stringify(n.name)} },`).join(`
1184
1193
  `);return{build:`
1185
1194
  const queues = createQueueContext(env, LUNORA_QUEUES);
1186
1195
  `,contextField:`
@@ -1189,7 +1198,7 @@ ${t}
1189
1198
  const LUNORA_QUEUES: ReadonlyArray<QueueBindingSpec> = [
1190
1199
  ${t}
1191
1200
  ];
1192
- `}},er=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`agent export "${n.exportName}"`),m(n.bindingName,`agent binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}"${n.publicRun===!0?", publicRun: true":""} },`).join(`
1201
+ `}},or=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`agent export "${n.exportName}"`),m(n.bindingName,`agent binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}"${n.publicRun===!0?", publicRun: true":""} },`).join(`
1193
1202
  `);return{build:`
1194
1203
  const agents = createAgentContext(env, LUNORA_AGENTS);
1195
1204
  `,contextField:`
@@ -1198,21 +1207,21 @@ ${t}
1198
1207
  const LUNORA_AGENTS: ReadonlyArray<AgentBindingSpec> = [
1199
1208
  ${t}
1200
1209
  ];
1201
- `}},tr=e=>{if(e.length===0)return{constant:"",override:""};const t={workflows:e.map(n=>({binding:n.bindingName,className:n.className,exportName:n.exportName,name:n.name}))};return{constant:`
1210
+ `}},sr=e=>{if(e.length===0)return{constant:"",override:""};const t={workflows:e.map(n=>({binding:n.bindingName,className:n.className,exportName:n.exportName,name:n.name}))};return{constant:`
1202
1211
  /** Read-only declared-workflow metadata (discovered from \`lunora/workflows.ts\`) served via \`__lunora_admin__:listWorkflows\` for the studio's workflows view. */
1203
1212
  const LUNORA_WORKFLOWS_INFO: WorkflowsResult = ${JSON.stringify(t,void 0,4)};
1204
1213
  `,override:`
1205
1214
  protected override workflowsMetadata(): WorkflowsResult {
1206
1215
  return LUNORA_WORKFLOWS_INFO;
1207
1216
  }
1208
- `}},nr=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}))};return{constant:`
1217
+ `}},ir=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}))};return{constant:`
1209
1218
  /** Read-only declared-queue metadata (discovered from \`lunora/queues.ts\`) served via \`__lunora_admin__:listQueues\` for the studio's queues view. */
1210
1219
  const LUNORA_QUEUES_INFO: QueuesResult = ${JSON.stringify(t,void 0,4)};
1211
1220
  `,override:`
1212
1221
  protected override queuesMetadata(): QueuesResult {
1213
1222
  return LUNORA_QUEUES_INFO;
1214
1223
  }
1215
- `}},rr=e=>{if(!e)return{build:"",configField:"",contextField:"",imports:[],stub:""};const t='throw new Error("ctx.payments: no payment configured. Pass \\`payment\\` to createShardDO().");';return{imports:['import type { LunoraDatabaseLike as LunoraPaymentDbLike, LunoraPayment, PaymentsFromContextOptions } from "@lunora/payment";','import { paymentsFromContext } from "@lunora/payment";'],build:`
1224
+ `}},lr=e=>{if(!e)return{build:"",configField:"",contextField:"",imports:[],stub:""};const t='throw new Error("ctx.payments: no payment configured. Pass \\`payment\\` to createShardDO().");';return{imports:['import type { LunoraDatabaseLike as LunoraPaymentDbLike, LunoraPayment, PaymentsFromContextOptions } from "@lunora/payment";','import { paymentsFromContext } from "@lunora/payment";'],build:`
1216
1225
  const payments: LunoraPayment = config.payment
1217
1226
  ? paymentsFromContext({ auth: { userId: userId ?? null }, db: db as unknown as LunoraPaymentDbLike }, config.payment(env))
1218
1227
  : paymentStub;
@@ -1248,7 +1257,7 @@ const paymentStub: LunoraPayment = {
1248
1257
  ${t}
1249
1258
  },
1250
1259
  } as unknown as LunoraPayment;
1251
- `}},ar=e=>e?{imports:['import type { X402Pay, X402PayConfig } from "@lunora/x402/pay";','import { lazyX402Pay } from "@lunora/x402/pay";'],build:`
1260
+ `}},dr=e=>e?{imports:['import type { X402Pay, X402PayConfig } from "@lunora/x402/pay";','import { lazyX402Pay } from "@lunora/x402/pay";'],build:`
1252
1261
  const x402: X402Pay = config.x402
1253
1262
  ? lazyX402Pay(config.x402(env), { getSecret: (name: string) => secrets.get(name) })
1254
1263
  : x402Stub;
@@ -1260,10 +1269,10 @@ const x402Stub: X402Pay = {
1260
1269
  throw new Error("ctx.x402: no pay rail configured. Pass \\\`x402\\\` to createShardDO().");
1261
1270
  },
1262
1271
  } as unknown as X402Pay;
1263
- `}:{build:"",configField:"",contextField:"",imports:[],stub:""},or=(e,t,n,r)=>["AdvisorProcedure","AdvisoryFinding","DatabaseWriterLike","DataMigrationLike",...r?["FlagsResult"]:[],"MaskPoliciesResult","MigrationRunResult",...n?["QueuesResult"]:[],"RunShardApplyCdcArgs","RunShardMigrationArgs","RlsPoliciesResult","RunShardRankBeforeArgs","RunShardRankPageArgs","RunShardWriteArgs","RunShardWriteResult","SchedulerLike","SchemaLike","ShardDOState","ShardRankPageResult","SqlExec","StorageRulesResult","StudioFeaturesResult","SystemReaderStorageLike","TelemetrySink",...t?["WorkflowsResult"]:[],...e?["WriteHook"]:[]],Nr=({advisories:e=[],advisorProcedures:t=[],agents:n=[],containers:r=[],env:a,flagKeys:o=[],hasAccessFacade:s=!1,hasAi:i=!1,hasAnalytics:l=!1,hasBrowser:u=!1,hasFlags:p=!1,hasHyperdrive:f=!1,hasImages:y=!1,hasKv:R=!1,hasNotify:d=!1,hasPayments:c=!1,hasPipelines:g=!1,hasR2sql:b=!1,hasX402:x=!1,maskMetadata:v,mutators:A=[],queues:N=[],rlsMetadata:$,schema:w,schemaSnapshot:E,shapes:ee=[],storageRules:F,studioFeatures:te,useUmbrella:ne=!1,workflows:B=[]})=>{const T=H(ne),z=A.length>0,L=ee.length>0,_=E===void 0?"":zt(E),M=E===void 0?"":`
1272
+ `}:{build:"",configField:"",contextField:"",imports:[],stub:""},cr=(e,t,n,r)=>["AdvisorProcedure","AdvisoryFinding","DatabaseWriterLike","DataMigrationLike","ExportRow",...r?["FlagsResult"]:[],"ImportShardResult","KeyRange","MaskPoliciesResult","MigrationRunResult",...n?["QueuesResult"]:[],"RunShardApplyCdcArgs","RunShardExportArgs","RunShardImportArgs","RunShardMigrationArgs","RlsPoliciesResult","RunShardRankBeforeArgs","RunShardRankPageArgs","RunShardWriteArgs","RunShardWriteResult","SchedulerLike","TransactionHeadroomTracker","SchemaLike","ShardDOState","ShardRankPageResult","SqlExec","StorageRulesResult","StudioFeaturesResult","SystemReaderStorageLike","TelemetrySink",...t?["WorkflowsResult"]:[],...e?["WriteHook"]:[]],Cr=({advisories:e=[],advisorProcedures:t=[],agents:n=[],containers:r=[],env:a,flagKeys:o=[],hasAccessFacade:i=!1,hasAi:s=!1,hasAnalytics:l=!1,hasBrowser:u=!1,hasFlags:p=!1,hasHyperdrive:f=!1,hasImages:y=!1,hasKv:R=!1,hasNotify:d=!1,hasPayments:c=!1,hasPipelines:g=!1,hasR2sql:b=!1,hasX402:x=!1,maskMetadata:v,mutators:O=[],queues:N=[],rlsMetadata:$,schema:w,schemaSnapshot:E,shapes:ee=[],storageRules:F,studioFeatures:te,useUmbrella:ne=!1,workflows:B=[]})=>{const T=H(ne),z=O.length>0,A=ee.length>0,I=E===void 0?"":en(E),M=E===void 0?"":`
1264
1273
  /** Structural schema snapshot + its content hash, recorded in the shard's \`__lunora_schema_history\` ledger on cold start so the studio can show a schema-version timeline and diff any two versions. */
1265
- const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(Xt(E))}, json: ${JSON.stringify(_)} };
1266
- `,re=E===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",{build:ae,configField:xe,contextField:ke,stub:ve}=Mn(i),oe=Un(s),K=qn(R),P=Bn(p,T.flags),Q=Kn(o,p,T.flags),X=jn(d),ie=Wn(a),V=Qn(l),j=Vn(y),W=Jn(f),U=Gn(u),q=Hn(b),Y=zn(g),{build:$e,contextField:fe,importLines:be,specs:se}=Zn(N),{build:Se,contextField:Re,importLines:ye,specs:le}=Xn(r,w.jurisdiction),{build:Ne,contextField:Oe,importLines:we,specs:Ae}=Yn(B),{build:Te,contextField:de,importLines:ce,specs:Le}=er(n),{build:Ce,configField:De,contextField:ue,imports:pe,stub:h}=rr(c),{build:_e,configField:st,imports:lt,stub:dt}=ar(x),ct=e,ut=t,pt=$??{policies:[],roles:[]},ht=v??{columns:[]},gt=F??{rules:[]},mt=te??{analytics:!1,auth:!1,containers:!1,flags:!1,kv:!1,mail:!1,notifications:!1,payments:!1,queues:!1,scheduler:!1,storage:!1,vectors:!1,workflows:!1},{constant:ft,override:bt}=tr(B),{constant:yt,override:wt}=nr(N),J=w.vectorIndexes.length>0,he=w.tables.some(C=>C.shardMode==="global"),Ie=w.tables.some(C=>C.shardMode==="global"&&C.globalBackend==="hyperdrive"),je=w.tables.some(C=>C.shardMode==="global"&&C.globalBackend!=="hyperdrive"),G=w.tables.some(C=>C.externalSource!==void 0);if(je&&Ie)throw new Z("INTERNAL",'lunora codegen: mixing `.global()` (D1) and `.global({ backend: "hyperdrive" })` tables in one app is not supported yet — use a single global backend.');const Pe=w.tables.length>0,xt=Dn(w),kt=In(w),vt=En(w),$t=_n(w),We=Pn(w),Ue=or(J,B.length>0,N.length>0,p);L&&Ue.push("WhereInput");const Ke=Fn(he),St=L?`
1274
+ const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(tn(E))}, json: ${JSON.stringify(I)} };
1275
+ `,re=E===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",{build:ae,configField:xe,contextField:ke,stub:ve}=Un(s),oe=Gn(i),K=Kn(R),P=Qn(p,T.flags),Q=Hn(o,p,T.flags),X=Jn(d),se=Vn(a),J=zn(l),j=Xn(y),W=Yn(f),U=Zn(u),q=er(b),Y=tr(g),{build:$e,contextField:fe,importLines:be,specs:ie}=ar(N),{build:Se,contextField:Re,importLines:ye,specs:le}=nr(r,w.jurisdiction),{build:Ne,contextField:Oe,importLines:we,specs:Te}=rr(B),{build:Ae,contextField:de,importLines:ce,specs:Le}=or(n),{build:Ce,configField:Ie,contextField:ue,imports:pe,stub:h}=lr(c),{build:De,configField:ut,imports:pt,stub:ht}=dr(x),gt=e,mt=t,ft=$??{policies:[],roles:[]},bt=v??{columns:[]},yt=F??{rules:[]},wt=te??{analytics:!1,auth:!1,containers:!1,flags:!1,kv:!1,mail:!1,notifications:!1,payments:!1,queues:!1,scheduler:!1,storage:!1,vectors:!1,workflows:!1},{constant:xt,override:kt}=sr(B),{constant:vt,override:$t}=ir(N),V=w.vectorIndexes.length>0,he=w.tables.some(L=>L.shardMode==="global"),_e=w.tables.some(L=>L.shardMode==="global"&&L.globalBackend==="hyperdrive"),We=w.tables.some(L=>L.shardMode==="global"&&L.globalBackend!=="hyperdrive"),G=w.tables.some(L=>L.externalSource!==void 0);if(We&&_e)throw new Z("INTERNAL",'lunora codegen: mixing `.global()` (D1) and `.global({ backend: "hyperdrive" })` tables in one app is not supported yet — use a single global backend.');const Pe=w.tables.length>0,St=Fn(w),Rt=qn(w),Nt=jn(w),Ot=Mn(w),Ue=Bn(w),Ke=cr(V,B.length>0,N.length>0,p);A&&Ke.push("WhereInput");const Qe=Wn(he),Tt=A?`
1267
1276
  protected override resolveShape(name: string, args: Record<string, unknown>, identity?: { identity?: Record<string, unknown>; userId?: string }): { columns?: readonly string[]; effectiveWhere?: WhereInput; global?: boolean; table: string } | undefined {
1268
1277
  const shape = LUNORA_SHAPES[name];
1269
1278
 
@@ -1316,15 +1325,15 @@ const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.st
1316
1325
 
1317
1326
  return { columns: shape.columns, effectiveWhere, global: isGlobal, table: shape.table };
1318
1327
  }
1319
- `:"",Rt=z?`
1328
+ `:"",At=z?`
1320
1329
  protected override isCustomMutator(functionPath: string): boolean {
1321
1330
  return LUNORA_MUTATOR_PATHS.has(functionPath);
1322
1331
  }
1323
- `:"",Nt=L?"\n/** Per-table RLS read policies (hoisted from `.use(rls(...))` chains) the shape resolver AND-merges into each `defineShape` predicate so partial replication honours read policies. */\nconst LUNORA_RLS_READ_REGISTRY = buildRlsReadRegistry(Object.values(LUNORA_FUNCTIONS));\n":"",Ot=L?"assertShapeShardable, ":"",ge=[`import type { ${Ue.join(", ")} } from "${T.do}";`,`import { applyCdcChanges, ${Ot}createShardCtxDb, ${G?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}runDataMigration, runShardMigrations, ${Ke.importFragment}ShardDO as ShardDOBase } from "${T.do}";`,...G?[`import type { ExternalSourceLike, SourceClientLike } from "${T.do}";`]:[],L?`import { asBucketStorage, buildRlsReadRegistry, composeShapeReadWhere, createSecrets, LunoraError } from "${T.server}";`:`import { asBucketStorage, createSecrets, LunoraError } from "${T.server}";`];Pe&&ge.push(`import { bindOrm, bindTableFacade } from "${T.server}";`),J&&ge.push('import type { SchemaLike as VectorSchemaLike, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";','import { createContextVectors, createVectors, createVectorSyncHook } from "@lunora/bindings/vectors";'),i&&ge.push('import type { AiBindingLike, LunoraAi } from "@lunora/ai";','import { createAi } from "@lunora/ai";'),ge.push(...oe.importLines,...K.importLines,...P.importLines,...X.importLines,...ie.importLines,...V.importLines,...j.importLines,...W.importLines,...U.importLines,...q.importLines,...Y.importLines,...ye,...we,...be,...ce,...pe,...lt,"",'import schema from "../schema.js";',`import { ${["LUNORA_FUNCTIONS","LUNORA_LIFECYCLE_HOOKS","LUNORA_MIGRATIONS",...z?["LUNORA_MUTATOR_PATHS"]:[],...L?["LUNORA_SHAPES"]:[]].join(", ")} } from "./functions.js";`);const At=J?`
1324
- vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",Tt=je?`
1325
- d1?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",Lt=Ie?`
1326
- hyperdriveGlobal?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",Ct=G?`
1327
- sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",Dt=he?'\nconst globalDbStub: DatabaseWriterLike = {\n aggregate: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n count: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n delete: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findFirst: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findFirstOrThrow: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findMany: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n get: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n groupBy: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n insert: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n normalizeId: () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n patch: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n query: () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n rank: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n rankPage: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n replace: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n};\n':"",_t=J?`
1332
+ `:"",Lt=A?"\n/** Per-table RLS read policies (hoisted from `.use(rls(...))` chains) the shape resolver AND-merges into each `defineShape` predicate so partial replication honours read policies. */\nconst LUNORA_RLS_READ_REGISTRY = buildRlsReadRegistry(Object.values(LUNORA_FUNCTIONS));\n":"",Ct=A?"assertShapeShardable, ":"",ge=[`import type { ${Ke.join(", ")} } from "${T.do}";`,`import { applyCdcChanges, ${Ct}createReadFootprint, createShardCtxDb, exportShardRows, importShardRows, ${G?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}runDataMigration, runShardMigrations, ${Qe.importFragment}ShardDO as ShardDOBase } from "${T.do}";`,...G?[`import type { ExternalSourceLike, SourceClientLike } from "${T.do}";`]:[],A?`import { asBucketStorage, buildRlsReadRegistry, composeShapeReadWhere, createSecrets, LunoraError } from "${T.server}";`:`import { asBucketStorage, createSecrets, LunoraError } from "${T.server}";`];Pe&&ge.push(`import { bindOrm, bindTableFacade } from "${T.server}";`),V&&ge.push('import type { SchemaLike as VectorSchemaLike, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";','import { createContextVectors, createVectors, createVectorSyncHook } from "@lunora/bindings/vectors";'),s&&ge.push('import type { AiBindingLike, LunoraAi } from "@lunora/ai";','import { createAi } from "@lunora/ai";'),ge.push(...oe.importLines,...K.importLines,...P.importLines,...X.importLines,...se.importLines,...J.importLines,...j.importLines,...W.importLines,...U.importLines,...q.importLines,...Y.importLines,...ye,...we,...be,...ce,...pe,...pt,"",'import schema from "../schema.js";',`import { ${["LUNORA_FUNCTIONS","LUNORA_LIFECYCLE_HOOKS","LUNORA_MIGRATIONS",...z?["LUNORA_MUTATOR_PATHS"]:[],...A?["LUNORA_SHAPES"]:[]].join(", ")} } from "./functions.js";`);const It=V?`
1333
+ vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",Dt=We?`
1334
+ d1?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",_t=_e?`
1335
+ hyperdriveGlobal?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",Pt=G?`
1336
+ sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",Et=he?'\nconst globalDbStub: DatabaseWriterLike = {\n aggregate: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n count: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n delete: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findFirst: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findFirstOrThrow: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findMany: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n get: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n groupBy: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n insert: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n normalizeId: () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n patch: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n query: () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n rank: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n rankPage: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n replace: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n};\n':"",Ft=V?`
1328
1337
  const vectorsStub: VectorSearchLike = {
1329
1338
  deleteByIds: async () => {
1330
1339
  throw new Error("ctx.vectors: no vectors configured. Pass \`vectors\` to createShardDO().");
@@ -1342,7 +1351,7 @@ const vectorsStub: VectorSearchLike = {
1342
1351
  throw new Error("ctx.vectors: no vectors configured. Pass \`vectors\` to createShardDO().");
1343
1352
  },
1344
1353
  };
1345
- `:"",It=J?`
1354
+ `:"",Mt=V?`
1346
1355
  let vectors: VectorSearchLike;
1347
1356
  let onWrite: WriteHook | undefined;
1348
1357
 
@@ -1355,40 +1364,44 @@ const vectorsStub: VectorSearchLike = {
1355
1364
  vectors = vectorsStub;
1356
1365
  onWrite = undefined;
1357
1366
  }
1358
- `:"",Qe=he?`
1367
+ `:"",Je=he?`
1359
1368
  globalDb,`:"",Ve=`
1360
- auth: { identity: identity ?? null, userId: userId ?? null },`,Pt=J?`{${Ve}
1369
+ auth: { identity: identity ?? null, userId: userId ?? null },`,qt=V?`{${Ve}
1361
1370
  broadcast: (delta) => {
1362
- this.recordChangedTable(delta.table);
1371
+ this.recordChangedTable(delta.table, delta.indexKeys);
1363
1372
  },
1364
1373
  cdc: config.cdc ?? false,
1365
1374
  enforceRls: true,
1375
+ headroom: options.headroom ?? this.transactionHeadroom(),
1366
1376
  onIndexUse: this.getCtxDbIndexUseHook(),
1367
1377
  onRead: options.onRead ?? this.getCtxDbReadHook(),
1378
+ onReadRange: options.onReadRange,
1368
1379
  onWrite,
1369
1380
  scheduler,
1370
1381
  schema: schema as unknown as SchemaLike,
1371
1382
  sql: this.sql as SqlExec,
1372
- storage,${Qe}
1383
+ storage,${Je}
1373
1384
  }`:`{${Ve}
1374
1385
  broadcast: (delta) => {
1375
- this.recordChangedTable(delta.table);
1386
+ this.recordChangedTable(delta.table, delta.indexKeys);
1376
1387
  },
1377
1388
  cdc: config.cdc ?? false,
1378
1389
  enforceRls: true,
1390
+ headroom: options.headroom ?? this.transactionHeadroom(),
1379
1391
  onIndexUse: this.getCtxDbIndexUseHook(),
1380
1392
  onRead: options.onRead ?? this.getCtxDbReadHook(),
1393
+ onReadRange: options.onReadRange,
1381
1394
  scheduler,
1382
1395
  schema: schema as unknown as SchemaLike,
1383
1396
  sql: this.sql as SqlExec,
1384
- storage,${Qe}
1385
- }`,Et=J?`
1386
- vectors,`:"",Ft=Pe?`
1387
- orm: bindOrm(facade),`:"",Mt="",Je=Ie?"config.hyperdriveGlobal":"config.d1",qt=he?` const globalDb: DatabaseWriterLike = ${Je}?.(env, { identity, userId }) ?? globalDbStub;
1388
- `:"",Bt=L&&he?`
1397
+ storage,${Je}
1398
+ }`,Bt=V?`
1399
+ vectors,`:"",jt=Pe?`
1400
+ orm: bindOrm(facade),`:"",Wt="",Ge=_e?"config.hyperdriveGlobal":"config.d1",Ut=he?` const globalDb: DatabaseWriterLike = ${Ge}?.(env, { identity, userId }) ?? globalDbStub;
1401
+ `:"",Kt=A&&he?`
1389
1402
  protected override async readGlobalShapeRows(resolved: { columns?: readonly string[]; effectiveWhere?: WhereInput; global?: boolean; table: string }, identity?: { identity?: Record<string, unknown>; userId?: string }): Promise<Array<{ doc: Record<string, unknown>; id: string }>> {
1390
1403
  const env = this.env as Record<string, unknown>;
1391
- const globalDb: DatabaseWriterLike = ${Je}?.(env, identity) ?? globalDbStub;
1404
+ const globalDb: DatabaseWriterLike = ${Ge}?.(env, identity) ?? globalDbStub;
1392
1405
  const rows: Array<{ doc: Record<string, unknown>; id: string }> = [];
1393
1406
 
1394
1407
  let cursor: null | string = null;
@@ -1415,10 +1428,10 @@ const vectorsStub: VectorSearchLike = {
1415
1428
 
1416
1429
  return rows;
1417
1430
  }
1418
- `:"",jt=G?`
1431
+ `:"",Qt=G?`
1419
1432
  const sourceClientCache = new WeakMap<object, Map<string, SourceClientLike>>();
1420
1433
  const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
1421
- `:"",Wt=G?`
1434
+ `:"",Jt=G?`
1422
1435
  protected override async pollExternalSources(): Promise<number | undefined> {
1423
1436
  const env = (this.env ?? {}) as Record<string, unknown>;
1424
1437
  const sourced = Object.entries((schema as unknown as SchemaLike).tables)
@@ -1433,7 +1446,7 @@ const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
1433
1446
  const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
1434
1447
  const writer = createShardCtxDb({
1435
1448
  broadcast: (delta) => {
1436
- this.recordChangedTable(delta.table);
1449
+ this.recordChangedTable(delta.table, delta.indexKeys);
1437
1450
  },
1438
1451
  cdc: config.cdc ?? false,
1439
1452
  scheduler,
@@ -1519,7 +1532,7 @@ const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
1519
1532
 
1520
1533
  return nextDueAt;
1521
1534
  }
1522
- `:"",Ge=We.length>0,Ut=G||Ge?`
1535
+ `:"",He=Ue.length>0,Vt=G||He?`
1523
1536
  public constructor(state: ShardDOState, env: unknown) {
1524
1537
  super(state, env);
1525
1538
  ${G?`
@@ -1532,26 +1545,26 @@ ${G?`
1532
1545
  if (autoSourced) {
1533
1546
  void this.scheduleSourcePoll();
1534
1547
  }
1535
- `:""}${Ge?`
1548
+ `:""}${He?`
1536
1549
  if (LUNORA_TTL_SWEEPS.length > 0) {
1537
1550
  void this.scheduleTtlSweep();
1538
1551
  }
1539
1552
  `:""} }
1540
- `:"",Kt=Pe?`
1553
+ `:"",Gt=Pe?`
1541
1554
  const facade = db as unknown as Record<string, ReturnType<typeof bindTableFacade>>;
1542
- ${w.tables.map(C=>` facade[${JSON.stringify(C.name)}] = bindTableFacade(db, ${JSON.stringify(C.name)});`).join(`
1555
+ ${w.tables.map(L=>` facade[${JSON.stringify(L.name)}] = bindTableFacade(db, ${JSON.stringify(L.name)});`).join(`
1543
1556
  `)}
1544
- `:"",Qt=`${oe.build}${K.build}${P.build}${V.build}${ie.build}
1557
+ `:"",Ht=`${oe.build}${K.build}${P.build}${J.build}${se.build}
1545
1558
  const secrets = createSecrets(env);
1546
- `,Vt=`${oe.contextField}${K.contextField}${P.contextField}${X.contextField}${V.contextField}${ie.contextField}
1547
- secrets,`,Jt=X.build,He=y||f||u||b||g||x,Gt=He?`
1559
+ `,zt=`${oe.contextField}${K.contextField}${P.contextField}${X.contextField}${J.contextField}${se.contextField}
1560
+ secrets,`,Xt=X.build,ze=y||f||u||b||g||x,Yt=ze?`
1548
1561
  // ActionCtx-only helpers (external, non-deterministic I/O): constructed
1549
1562
  // and attached only for an \`action\` so query/mutation ctx never carry them.
1550
1563
  if (isAction) {
1551
- ${j.build}${W.build}${U.build}${q.build}${Y.build}${_e}${[...y?[" ctx.images = images;"]:[],...f?[" ctx.sql = sql;"]:[],...u?[" ctx.browser = browser;"]:[],...b?[" ctx.r2sql = r2sql;"]:[],...g?[" ctx.pipelines = pipelines;"]:[],...x?[" ctx.x402 = x402;"]:[]].join(`
1564
+ ${j.build}${W.build}${U.build}${q.build}${Y.build}${De}${[...y?[" ctx.images = images;"]:[],...f?[" ctx.sql = sql;"]:[],...u?[" ctx.browser = browser;"]:[],...b?[" ctx.r2sql = r2sql;"]:[],...g?[" ctx.pipelines = pipelines;"]:[],...x?[" ctx.x402 = x402;"]:[]].join(`
1552
1565
  `)}
1553
1566
  }
1554
- `:"",Ht=He?` const isAction = LUNORA_FUNCTIONS[options.functionPath ?? ""]?.kind === "action";
1567
+ `:"",Zt=ze?` const isAction = LUNORA_FUNCTIONS[options.functionPath ?? ""]?.kind === "action";
1555
1568
  `:"";return`${k}${ge.join(`
1556
1569
  `)}
1557
1570
 
@@ -1562,45 +1575,45 @@ interface FunctionReference {
1562
1575
  }
1563
1576
 
1564
1577
  /** Foreign-key columns per table (\`v.id("target")\` fields) for the data browser. */
1565
- const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(xt,void 0,4)};
1578
+ const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(St,void 0,4)};
1566
1579
 
1567
1580
  /** Declared indexes per table (secondary, search, geo, rank, vector) for the schema viewer. */
1568
- const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(kt,void 0,4)};
1581
+ const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(Rt,void 0,4)};
1569
1582
 
1570
1583
  /** Columns per table (typed, with PK/FK markers) for the studio's schema diagram, served via \`__lunora_admin__:describeTable\`. */
1571
- const LUNORA_TABLE_COLUMNS: Record<string, Array<{ isStorage?: boolean; name: string; optional: boolean; pk?: boolean; ref?: string; type: string }>> = ${JSON.stringify(vt,void 0,4)};
1584
+ const LUNORA_TABLE_COLUMNS: Record<string, Array<{ isStorage?: boolean; name: string; optional: boolean; pk?: boolean; ref?: string; type: string }>> = ${JSON.stringify(Nt,void 0,4)};
1572
1585
 
1573
1586
  /** Storage-key columns per table (\`v.storage(...)\` fields) for the file browser's records↔files join. */
1574
- const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify($t,void 0,4)};
1587
+ const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify(Ot,void 0,4)};
1575
1588
 
1576
1589
  /** Declarative TTL policies (\`.ttl(field, { after? })\`) the DO alarm sweep auto-expires rows for. */
1577
- const LUNORA_TTL_SWEEPS: Array<{ after?: number; field: string; softDeleteField?: string; table: string }> = ${JSON.stringify(We,void 0,4)};
1590
+ const LUNORA_TTL_SWEEPS: Array<{ after?: number; field: string; softDeleteField?: string; table: string }> = ${JSON.stringify(Ue,void 0,4)};
1578
1591
 
1579
1592
  /** Static schema advisories (computed by @lunora/advisor at codegen time) served via \`__lunora_admin__:getAdvisories\`. */
1580
- const LUNORA_ADVISORIES: AdvisoryFinding[] = ${JSON.stringify(ct,void 0,4)};
1593
+ const LUNORA_ADVISORIES: AdvisoryFinding[] = ${JSON.stringify(gt,void 0,4)};
1581
1594
 
1582
1595
  /** Every declared procedure (discovered by @lunora/codegen) served via \`__lunora_admin__:getAdvisorProcedures\` — the health map's denominator. */
1583
- const LUNORA_ADVISOR_PROCEDURES: AdvisorProcedure[] = ${JSON.stringify(ut,void 0,4)};
1596
+ const LUNORA_ADVISOR_PROCEDURES: AdvisorProcedure[] = ${JSON.stringify(mt,void 0,4)};
1584
1597
 
1585
1598
  /** Read-only RLS metadata (policies + roles discovered from \`.use(rls(...))\` chains) served via \`__lunora_admin__:rlsPolicies\` for the studio's RLS inspector. */
1586
- const LUNORA_RLS_METADATA: RlsPoliciesResult = ${JSON.stringify(pt,void 0,4)};
1599
+ const LUNORA_RLS_METADATA: RlsPoliciesResult = ${JSON.stringify(ft,void 0,4)};
1587
1600
 
1588
1601
  /** Read-only masking metadata (table + column + strategy discovered from \`.use(mask(...))\` chains) served via \`__lunora_admin__:maskPolicies\` for the studio's data-browser mask preview. */
1589
- const LUNORA_MASK_METADATA: MaskPoliciesResult = ${JSON.stringify(ht,void 0,4)};
1602
+ const LUNORA_MASK_METADATA: MaskPoliciesResult = ${JSON.stringify(bt,void 0,4)};
1590
1603
 
1591
1604
  /** Read-only storage access-rule metadata (discovered from \`.use(storageRules(...))\` chains) served via \`__lunora_admin__:storageRules\` for the studio's access-rules view. */
1592
- const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(gt,void 0,4)};
1605
+ const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(yt,void 0,4)};
1593
1606
 
1594
1607
  /** Which optional package-backed features this app wires up (discovered from imports / \`ctx.*\` reads / schema signals) served via \`__lunora_admin__:studioFeatures\` so the studio hides nav pages whose package isn't enabled. */
1595
- const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(mt,void 0,4)};
1596
- ${M}${Q.constant}${Nt}${ft}${yt}${le}${Ae}${se}${Le}
1608
+ const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(wt,void 0,4)};
1609
+ ${M}${Q.constant}${Lt}${xt}${vt}${le}${Te}${ie}${Le}
1597
1610
  export interface ShardDOConfig {
1598
1611
  /** Opt into change-data-capture: records a post-image to \`__cdc_log\` on every write (backs streaming export + replay-PITR). */
1599
1612
  cdc?: boolean;
1600
1613
  /** Optional telemetry sink. When supplied, each \`ctx.log.*\` call is forwarded to \`sink.onLog\`. Pass the SAME sink you give \`createWorker({ observability })\` (which drives \`onRpc\`) to route both RPC and log events. */
1601
1614
  observability?: (env: Record<string, unknown>) => TelemetrySink | undefined;
1602
1615
  scheduler?: (env: Record<string, unknown>) => unknown;
1603
- storage?: (env: Record<string, unknown>) => unknown;${At}${xe}${K.configField}${P.configField}${V.configField}${j.configField}${W.configField}${U.configField}${q.configField}${Y.configField}${De}${st}${Tt}${Lt}${Ct}
1616
+ storage?: (env: Record<string, unknown>) => unknown;${It}${xe}${K.configField}${P.configField}${J.configField}${j.configField}${W.configField}${U.configField}${q.configField}${Y.configField}${Ie}${ut}${Dt}${_t}${Pt}
1604
1617
  }
1605
1618
 
1606
1619
  const schedulerStub = {
@@ -1638,7 +1651,7 @@ const storageStub = {
1638
1651
  throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
1639
1652
  },
1640
1653
  };
1641
- ${Dt}${jt}${_t}${ve}${K.stub}${P.stub}${V.stub}${j.stub}${W.stub}${U.stub}${q.stub}${Y.stub}${h}${dt}${Mt}
1654
+ ${Et}${Qt}${Ft}${ve}${K.stub}${P.stub}${J.stub}${j.stub}${W.stub}${U.stub}${q.stub}${Y.stub}${h}${ht}${Wt}
1642
1655
  // Bound in-process \`ctx.run*\` composition depth so a self- or cyclically-
1643
1656
  // referencing call fails loudly with a clear error instead of overflowing the
1644
1657
  // stack. Tracked across the awaited handler chain (one DO invocation is
@@ -1675,7 +1688,7 @@ const dispatchRun = async (expected: FunctionKind, functionPath: string, args: R
1675
1688
  * from the worker entry so wrangler binds it by name.
1676
1689
  */
1677
1690
  export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOState, env: unknown) => ShardDOBase =>
1678
- class extends ShardDOBase {${Ut}
1691
+ class extends ShardDOBase {${Vt}
1679
1692
  private migrated = false;
1680
1693
 
1681
1694
  public override async handleRpc(functionPath: string, args: Record<string, unknown>): Promise<unknown> {
@@ -1718,8 +1731,8 @@ export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOSt
1718
1731
 
1719
1732
  return registered.handler(ctx, args);
1720
1733
  }
1721
- ${Ke.override}
1722
- protected override async executeSubscription(functionPath: string, args: Record<string, unknown>, identity?: { identity?: Record<string, unknown>; userId?: string }): Promise<{ result: unknown; tables: Set<string> } | null> {
1734
+ ${Qe.override}
1735
+ protected override async executeSubscription(functionPath: string, args: Record<string, unknown>, identity?: { identity?: Record<string, unknown>; userId?: string }): Promise<{ ranges?: Map<string, KeyRange[]>; result: unknown; tables: Set<string> } | null> {
1723
1736
  const registered = LUNORA_FUNCTIONS[functionPath];
1724
1737
 
1725
1738
  if (!registered || registered.kind !== "query" || registered.visibility === "internal") {
@@ -1728,14 +1741,16 @@ ${Ke.override}
1728
1741
 
1729
1742
  this.ensureMigrated();
1730
1743
 
1731
- const tables = new Set<string>();
1744
+ const footprint = createReadFootprint();
1732
1745
  // Identity is threaded EXPLICITLY from the (deferred/interleaved)
1733
1746
  // subscription caller — never read from the shared per-request field
1734
1747
  // here — so a concurrent RPC can't leak its identity into this re-run.
1735
- const ctx = this.buildCtx({ functionPath, identity, onRead: (table) => tables.add(table) });
1748
+ const ctx = this.buildCtx({ functionPath, headroom: this.subscriptionHeadroom(), identity, onRead: footprint.onRead, onReadRange: footprint.onReadRange });
1736
1749
  const result = await registered.handler(ctx, args);
1737
1750
 
1738
- return { result, tables };
1751
+ // Ranges come from THIS run's reads, never a shared field on the DO:
1752
+ // a deferred re-run interleaves with unrelated dispatches.
1753
+ return { ranges: footprint.ranges(), result, tables: footprint.tables };
1739
1754
  }
1740
1755
 
1741
1756
  protected override executeStream(functionPath: string, args: Record<string, unknown>): null | { iterator: (signal: AbortSignal) => AsyncIterable<unknown> } {
@@ -1751,7 +1766,7 @@ ${Ke.override}
1751
1766
  iterator: (signal) => (registered.handler as (context: unknown, args: Record<string, unknown>, signal: AbortSignal) => AsyncIterable<unknown>)(this.buildCtx({ functionPath }), args, signal),
1752
1767
  };
1753
1768
  }
1754
- ${Rt}${St}${Bt}${Wt}
1769
+ ${At}${Tt}${Kt}${Jt}
1755
1770
  protected override lifecycleHookPaths(event: "connect" | "disconnect"): readonly string[] {
1756
1771
  return LUNORA_LIFECYCLE_HOOKS[event];
1757
1772
  }
@@ -1791,7 +1806,7 @@ ${Rt}${St}${Bt}${Wt}
1791
1806
  protected override studioFeatures(): StudioFeaturesResult {
1792
1807
  return LUNORA_STUDIO_FEATURES;
1793
1808
  }
1794
- ${Q.evaluateOverride}${Q.subscriptionOverride}${bt}${wt}
1809
+ ${Q.evaluateOverride}${Q.subscriptionOverride}${kt}${$t}
1795
1810
  protected override advisories(): AdvisoryFinding[] {
1796
1811
  return LUNORA_ADVISORIES;
1797
1812
  }
@@ -1813,7 +1828,7 @@ ${Q.evaluateOverride}${Q.subscriptionOverride}${bt}${wt}
1813
1828
  const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
1814
1829
  const writer = createShardCtxDb({
1815
1830
  broadcast: (delta) => {
1816
- this.recordChangedTable(delta.table);
1831
+ this.recordChangedTable(delta.table, delta.indexKeys);
1817
1832
  },
1818
1833
  cdc: config.cdc ?? false,
1819
1834
  scheduler,
@@ -1856,7 +1871,7 @@ ${Q.evaluateOverride}${Q.subscriptionOverride}${bt}${wt}
1856
1871
  const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
1857
1872
  const writer = createShardCtxDb({
1858
1873
  broadcast: (delta) => {
1859
- this.recordChangedTable(delta.table);
1874
+ this.recordChangedTable(delta.table, delta.indexKeys);
1860
1875
  },
1861
1876
  cdc: config.cdc ?? false,
1862
1877
  scheduler,
@@ -1887,6 +1902,70 @@ ${Q.evaluateOverride}${Q.subscriptionOverride}${bt}${wt}
1887
1902
  return { id: args.id ?? null, op: "patch" };
1888
1903
  }
1889
1904
 
1905
+ // The base \`ShardDO\` cannot build a schema-aware writer, so its
1906
+ // \`runShardExport\`/\`runShardImport\` return \`[]\` and \`{inserted:{}}\`.
1907
+ // Those are success-shaped: an empty export is what a correct export of
1908
+ // an empty shard looks like, so a backup of a populated sharded schema
1909
+ // reported success and wrote nothing, and an import reported success and
1910
+ // dropped every row. Overriding both here is what makes the two admin
1911
+ // RPCs real for a \`.shardBy()\` table.
1912
+ //
1913
+ // NOTE: the admin export RPC is not paginated — \`parseExportShardArgs\`
1914
+ // takes \`tables\`/\`batchSize\` but no cursor, and the coordinator issues
1915
+ // one call per shard — so the rows are collected into a single response.
1916
+ // \`batchSize\` bounds the SQLite scan page, not the reply. A shard holding
1917
+ // more rows than fit in the DO's memory budget will therefore fail the
1918
+ // export rather than stream it. That is a loud failure where the bug this
1919
+ // replaces was a silent empty one, but a cursor on the RPC is what makes
1920
+ // this a complete backup path for large shards.
1921
+ protected override async runShardExport(args: RunShardExportArgs): Promise<ExportRow[]> {
1922
+ this.ensureMigrated();
1923
+
1924
+ const env = (this.env ?? {}) as Record<string, unknown>;
1925
+ const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
1926
+ const writer = createShardCtxDb({
1927
+ broadcast: (delta) => {
1928
+ this.recordChangedTable(delta.table, delta.indexKeys);
1929
+ },
1930
+ cdc: config.cdc ?? false,
1931
+ scheduler,
1932
+ schema: schema as unknown as SchemaLike,
1933
+ sql: this.sql as SqlExec,
1934
+ });
1935
+
1936
+ const rows: ExportRow[] = [];
1937
+
1938
+ // \`exportShardRows\` walks in keyset batches so a large table does not
1939
+ // materialize at once inside the generator; the admin RPC's response
1940
+ // is a single array, so it is collected here rather than streamed.
1941
+ for await (const row of exportShardRows(writer, schema as unknown as SchemaLike, { batchSize: args.batchSize, tables: args.tables })) {
1942
+ rows.push(row);
1943
+ }
1944
+
1945
+ return rows;
1946
+ }
1947
+
1948
+ protected override async runShardImport(args: RunShardImportArgs): Promise<ImportShardResult> {
1949
+ this.ensureMigrated();
1950
+
1951
+ const env = (this.env ?? {}) as Record<string, unknown>;
1952
+ const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
1953
+ const writer = createShardCtxDb({
1954
+ broadcast: (delta) => {
1955
+ this.recordChangedTable(delta.table, delta.indexKeys);
1956
+ },
1957
+ cdc: config.cdc ?? false,
1958
+ scheduler,
1959
+ schema: schema as unknown as SchemaLike,
1960
+ sql: this.sql as SqlExec,
1961
+ });
1962
+
1963
+ // \`importShardRows\` inserts with \`allowExplicitId\`, so a source
1964
+ // database's \`_id\`s carry across verbatim and every foreign key
1965
+ // referencing them stays valid without a second remapping pass.
1966
+ return importShardRows(writer, schema as unknown as SchemaLike, { rows: args.rows, startLine: args.startLine });
1967
+ }
1968
+
1890
1969
  protected override async deleteRowThroughWriter(table: string, id: string): Promise<void> {
1891
1970
  const definition = (schema as unknown as SchemaLike).tables[table];
1892
1971
 
@@ -1906,7 +1985,7 @@ ${Q.evaluateOverride}${Q.subscriptionOverride}${bt}${wt}
1906
1985
  const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
1907
1986
  const writer = createShardCtxDb({
1908
1987
  broadcast: (delta) => {
1909
- this.recordChangedTable(delta.table);
1988
+ this.recordChangedTable(delta.table, delta.indexKeys);
1910
1989
  },
1911
1990
  cdc: config.cdc ?? false,
1912
1991
  scheduler,
@@ -1927,7 +2006,7 @@ ${Q.evaluateOverride}${Q.subscriptionOverride}${bt}${wt}
1927
2006
  const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
1928
2007
  const writer = createShardCtxDb({
1929
2008
  broadcast: (delta) => {
1930
- this.recordChangedTable(delta.table);
2009
+ this.recordChangedTable(delta.table, delta.indexKeys);
1931
2010
  },
1932
2011
  cdc: config.cdc ?? false,
1933
2012
  scheduler,
@@ -1955,7 +2034,7 @@ ${Q.evaluateOverride}${Q.subscriptionOverride}${bt}${wt}
1955
2034
  const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
1956
2035
  const writer = createShardCtxDb({
1957
2036
  broadcast: (delta) => {
1958
- this.recordChangedTable(delta.table);
2037
+ this.recordChangedTable(delta.table, delta.indexKeys);
1959
2038
  },
1960
2039
  cdc: config.cdc ?? false,
1961
2040
  scheduler,
@@ -1986,7 +2065,7 @@ ${Q.evaluateOverride}${Q.subscriptionOverride}${bt}${wt}
1986
2065
  const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
1987
2066
  const writer = createShardCtxDb({
1988
2067
  broadcast: (delta) => {
1989
- this.recordChangedTable(delta.table);
2068
+ this.recordChangedTable(delta.table, delta.indexKeys);
1990
2069
  },
1991
2070
  cdc: config.cdc ?? false,
1992
2071
  scheduler,
@@ -2008,7 +2087,7 @@ ${Q.evaluateOverride}${Q.subscriptionOverride}${bt}${wt}
2008
2087
  this.migrated = true;
2009
2088
  }
2010
2089
 
2011
- private buildCtx(options: { functionPath?: string; identity?: { identity?: Record<string, unknown>; userId?: string }; onRead?: (table: string) => void } = {}): unknown {
2090
+ private buildCtx(options: { functionPath?: string; headroom?: TransactionHeadroomTracker; identity?: { identity?: Record<string, unknown>; userId?: string }; onRead?: (table: string, idOrScan?: string) => void; onReadRange?: (range: KeyRange) => void } = {}): unknown {
2012
2091
  const env = (this.env ?? {}) as Record<string, unknown>;
2013
2092
  // When the caller threads an explicit identity (subscription seed /
2014
2093
  // refresh — both run in deferred/interleaved contexts), use it by
@@ -2017,7 +2096,7 @@ ${Q.evaluateOverride}${Q.subscriptionOverride}${bt}${wt}
2017
2096
  // dispatch path) fall back to the per-request fields as before.
2018
2097
  const userId = options.identity ? options.identity.userId : this.getCurrentUserId();
2019
2098
  const identity = options.identity ? options.identity.identity : this.getCurrentIdentity();
2020
- ${It}${ae}${Qt}${Se}${Ne}${$e}${Te}
2099
+ ${Mt}${ae}${Ht}${Se}${Ne}${$e}${Ae}
2021
2100
  const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
2022
2101
  // Build the storage adapter once and share it between \`ctx.storage\`
2023
2102
  // and \`ctx.db.system._storage\` so both read the same R2 binding. The
@@ -2044,13 +2123,13 @@ ${It}${ae}${Qt}${Se}${Ne}${$e}${Te}
2044
2123
  // so both write to the same trace.
2045
2124
  const span = this.makeDispatchSpan(traceAnchor, observability);
2046
2125
 
2047
- ${qt} // \`ctx.db\`, wrapped in automatic instrumentation: by default this
2126
+ ${Ut} // \`ctx.db\`, wrapped in automatic instrumentation: by default this
2048
2127
  // adds aggregate counters (call count, total time, per-operation
2049
2128
  // breakdown) to the wide event rather than a span per call, so a
2050
2129
  // handler making hundreds of queries stays readable. See
2051
2130
  // \`instrumentDatabase\` for the \`"spans"\` / \`"off"\` levels.
2052
- const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${Pt}), logFunctionPath, traceAnchor, observability);
2053
- ${Kt}${Ce}
2131
+ const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${qt}), logFunctionPath, traceAnchor, observability);
2132
+ ${Gt}${Ce}
2054
2133
 
2055
2134
  // \`ctx.trace\` / \`ctx.metrics\`: spans and measurements to the same sink.
2056
2135
  // The trace anchor is threaded explicitly for the same reason \`identity\`
@@ -2058,7 +2137,7 @@ ${Kt}${Ce}
2058
2137
  // writing mutation's trace from the shared per-request field.
2059
2138
  const trace = this.makeTracer(logFunctionPath, observability, traceAnchor);
2060
2139
  const metrics = this.makeMetrics(logFunctionPath, observability);
2061
- ${Jt}
2140
+ ${Xt}
2062
2141
  // \`ctx.now\`: the wall-clock instant (epoch ms) this function began,
2063
2142
  // captured ONCE so the whole handler body sees a single stable value.
2064
2143
  // Query/mutation handlers must be deterministic (they may be re-run on
@@ -2081,13 +2160,13 @@ ${Jt}
2081
2160
  ip: this.getCurrentIp(),
2082
2161
  log,
2083
2162
  metrics,
2084
- now,${Ft}
2163
+ now,${jt}
2085
2164
  scheduler,
2086
2165
  span,
2087
2166
  storage,
2088
- trace,${Et}${ke}${Vt}${ue}${Re}${Oe}${fe}${de}
2167
+ trace,${Bt}${ke}${zt}${ue}${Re}${Oe}${fe}${de}
2089
2168
  };
2090
- ${Ht}${Gt}
2169
+ ${Zt}${Yt}
2091
2170
  ctx.runAction = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("action", reference.__lunoraRef, fnArgs, ctx);
2092
2171
  ctx.runMutation = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("mutation", reference.__lunoraRef, fnArgs, ctx);
2093
2172
  ctx.runQuery = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("query", reference.__lunoraRef, fnArgs, ctx);
@@ -2095,28 +2174,28 @@ ${Ht}${Gt}
2095
2174
  return ctx;
2096
2175
  }
2097
2176
  };
2098
- `},Be=e=>{switch(e.kind){case"array":case"object":case"record":case"union":return{builder:"text",mode:"json",notNull:!0,typeAnnotation:O(e)};case"bigint":return{builder:"blob",mode:"bigint",notNull:!0};case"boolean":return{builder:"integer",mode:"boolean",notNull:!0};case"bytes":return{builder:"blob",mode:"buffer",notNull:!0};case"date":case"timestamp":return{builder:"integer",notNull:!0};case"id":return{builder:"text",notNull:!0};case"literal":{const t=e.literalValue??"";return t.startsWith('"')||t.startsWith("'")?{builder:"text",notNull:!0}:t==="true"||t==="false"?{builder:"integer",mode:"boolean",notNull:!0}:t==="null"?{builder:"text",notNull:!0}:{builder:"real",notNull:!0}}case"null":return{builder:"text",notNull:!0};case"number":return{builder:"real",notNull:!0};case"optional":return{...e.inner?Be(e.inner):{builder:"text",notNull:!1},notNull:!1};case"storage":case"string":return{builder:"text",notNull:!0};default:return{builder:"text",notNull:!0}}},it=(e,t)=>{const n=e.kind==="optional"&&e.inner?e.inner:e;return n.kind==="id"&&n.tableName!==void 0&&t.has(n.tableName)?n.tableName:void 0},ir=(e,t,n)=>{m(e,"drizzle column name");const r=Be(t),a=r.mode?`, { mode: "${r.mode}" }`:"";let o=`${r.builder}("${e}"${a})`;r.typeAnnotation&&(o+=`.$type<${r.typeAnnotation}>()`);const s=it(t,n);return s!==void 0&&(o+=`.references((): AnySQLiteColumn => ${s}._id)`),r.notNull&&(o+=".notNull()"),o},sr=e=>{m(e.name,"drizzle index name");const t=e.unique?"uniqueIndex":"index",n=e.fields.map(r=>(m(r,"drizzle index field"),`t.${r}`)).join(", ");return` ${e.name}: ${t}("${e.name}").on(${n}),`},lr=(e,t)=>{m(e.name,"table name");const n=[' _id: text("_id").primaryKey(),',' _creationTime: integer("_creationTime").notNull(),',...Object.entries(e.shape).map(([a,o])=>` ${a}: ${ir(a,o,t)},`)].join(`
2177
+ `},je=e=>{switch(e.kind){case"array":case"object":case"record":case"union":return{builder:"text",mode:"json",notNull:!0,typeAnnotation:C(e)};case"bigint":return{builder:"blob",mode:"bigint",notNull:!0};case"boolean":return{builder:"integer",mode:"boolean",notNull:!0};case"bytes":return{builder:"blob",mode:"buffer",notNull:!0};case"date":case"timestamp":return{builder:"integer",notNull:!0};case"id":return{builder:"text",notNull:!0};case"literal":{const t=e.literalValue??"";return t.startsWith('"')||t.startsWith("'")?{builder:"text",notNull:!0}:t==="true"||t==="false"?{builder:"integer",mode:"boolean",notNull:!0}:t==="null"?{builder:"text",notNull:!0}:{builder:"real",notNull:!0}}case"null":return{builder:"text",notNull:!0};case"number":return{builder:"real",notNull:!0};case"optional":return{...e.inner?je(e.inner):{builder:"text",notNull:!1},notNull:!1};case"storage":case"string":return{builder:"text",notNull:!0};default:return{builder:"text",notNull:!0}}},ct=(e,t)=>{const n=e.kind==="optional"&&e.inner?e.inner:e;return n.kind==="id"&&n.tableName!==void 0&&t.has(n.tableName)?n.tableName:void 0},ur=(e,t,n)=>{m(e,"drizzle column name");const r=je(t),a=r.mode?`, { mode: "${r.mode}" }`:"";let o=`${r.builder}("${e}"${a})`;r.typeAnnotation&&(o+=`.$type<${r.typeAnnotation}>()`);const i=ct(t,n);return i!==void 0&&(o+=`.references((): AnySQLiteColumn => ${i}._id)`),r.notNull&&(o+=".notNull()"),o},pr=e=>{m(e.name,"drizzle index name");const t=e.unique?"uniqueIndex":"index",n=e.fields.map(r=>(m(r,"drizzle index field"),`t.${r}`)).join(", ");return` ${e.name}: ${t}("${e.name}").on(${n}),`},hr=(e,t)=>{m(e.name,"table name");const n=[' _id: text("_id").primaryKey(),',' _creationTime: integer("_creationTime").notNull(),',...Object.entries(e.shape).map(([a,o])=>` ${a}: ${ur(a,o,t)},`)].join(`
2099
2178
  `),r=e.indexes.length>0?`, (t) => ({
2100
- ${e.indexes.map(a=>sr(a)).join(`
2179
+ ${e.indexes.map(a=>pr(a)).join(`
2101
2180
  `)}
2102
2181
  })`:"";return`export const ${e.name} = sqliteTable("${e.name}", {
2103
2182
  ${n}
2104
- }${r});`},dr=e=>e.typeAnnotation?.includes('Id<"')??!1,cr=(e,t)=>{const n=new Set(["integer","sqliteTable","text"]),r=new Set;let a=!1,o=!1;for(const s of e){for(const i of Object.values(s.shape)){const l=Be(i);n.add(l.builder),o=o||dr(l),a=a||it(i,t)!==void 0}for(const i of s.indexes)r.add(i.unique?"uniqueIndex":"index")}return{columns:[...n].toSorted((s,i)=>s.localeCompare(i)),indexes:[...r].toSorted((s,i)=>s.localeCompare(i)),needsAnyColumn:a,needsId:o}},Xe=(e,t=!1)=>{if(e.length===0)return`${k}export {};
2105
- `;const n=H(t),r=new Set(e.map(f=>f.name)),{columns:a,indexes:o,needsAnyColumn:s,needsId:i}=cr(e,r),l=[...o,...a].toSorted((f,y)=>f.localeCompare(y)),u=e.map(f=>lr(f,r)).join(`
2183
+ }${r});`},gr=e=>e.typeAnnotation?.includes('Id<"')??!1,mr=(e,t)=>{const n=new Set(["integer","sqliteTable","text"]),r=new Set;let a=!1,o=!1;for(const i of e){for(const s of Object.values(i.shape)){const l=je(s);n.add(l.builder),o=o||gr(l),a=a||ct(s,t)!==void 0}for(const s of i.indexes)r.add(s.unique?"uniqueIndex":"index")}return{columns:[...n].toSorted((i,s)=>i.localeCompare(s)),indexes:[...r].toSorted((i,s)=>i.localeCompare(s)),needsAnyColumn:a,needsId:o}},Ye=(e,t=!1)=>{if(e.length===0)return`${k}export {};
2184
+ `;const n=H(t),r=new Set(e.map(f=>f.name)),{columns:a,indexes:o,needsAnyColumn:i,needsId:s}=mr(e,r),l=[...o,...a].toSorted((f,y)=>f.localeCompare(y)),u=e.map(f=>hr(f,r)).join(`
2106
2185
 
2107
- `),p=[s?`import type { AnySQLiteColumn } from "${n.serverDrizzle}";
2108
- `:"",i?`import type { Id } from "./dataModel.js";
2186
+ `),p=[i?`import type { AnySQLiteColumn } from "${n.serverDrizzle}";
2187
+ `:"",s?`import type { Id } from "./dataModel.js";
2109
2188
  `:""].join("");return`${k}import { ${l.join(", ")} } from "${n.serverDrizzle}";
2110
2189
  ${p}
2111
2190
  ${u}
2112
- `},Or=(e,t=!1)=>{const n=e.tables.filter(a=>a.shardMode==="global"),r=e.tables.filter(a=>a.shardMode!=="global");return{global:Xe(n,t),shard:Xe(r,t)}},Ar=e=>{const t=[],n=new Map;for(const i of e){const l=n.get(i.cron);l?l.push(i):(n.set(i.cron,[i]),t.push(i.cron))}const r=t.map(i=>` ${JSON.stringify(i)},`).join(`
2191
+ `},Ir=(e,t=!1)=>{const n=e.tables.filter(a=>a.shardMode==="global"),r=e.tables.filter(a=>a.shardMode!=="global");return{global:Ye(n,t),shard:Ye(r,t)}},Dr=e=>{const t=[],n=new Map;for(const s of e){const l=n.get(s.cron);l?l.push(s):(n.set(s.cron,[s]),t.push(s.cron))}const r=t.map(s=>` ${JSON.stringify(s)},`).join(`
2113
2192
  `),a=r.length>0?`
2114
2193
  ${r}
2115
- `:"",o=[...n.entries()].map(([i,l])=>{const u=l.map(p=>{const f=p.workflow?`workflow: ${JSON.stringify(p.workflow.binding)}`:`functionPath: ${JSON.stringify(p.functionPath)}`;return` { name: ${JSON.stringify(p.name)}, ${f}, args: ${JSON.stringify(p.args)} },`}).join(`
2116
- `);return` ${JSON.stringify(i)}: [
2194
+ `:"",o=[...n.entries()].map(([s,l])=>{const u=l.map(p=>{const f=p.workflow?`workflow: ${JSON.stringify(p.workflow.binding)}`:`functionPath: ${JSON.stringify(p.functionPath)}`;return` { name: ${JSON.stringify(p.name)}, ${f}, args: ${JSON.stringify(p.args)} },`}).join(`
2195
+ `);return` ${JSON.stringify(s)}: [
2117
2196
  ${u}
2118
2197
  ],`}).join(`
2119
- `),s=o.length>0?`
2198
+ `),i=o.length>0?`
2120
2199
  ${o}
2121
2200
  `:"";return`${k}/**
2122
2201
  * One scheduled cron invocation. Exactly one target is set: \`functionPath\` is
@@ -2142,8 +2221,8 @@ export const LUNORA_CRON_TRIGGERS: ReadonlyArray<string> = [${a}];
2142
2221
  * Dispatcher map keyed by cron expression. The Worker's \`scheduled()\` handler
2143
2222
  * looks up \`event.cron\` here and dispatches every job in the list.
2144
2223
  */
2145
- export const LUNORA_CRONS: Record<string, ReadonlyArray<LunoraCronJob>> = {${s}};
2146
- `},Tr=e=>{const t=[...e].toSorted((r,a)=>r.name.localeCompare(a.name)).map(r=>{const a=[`name: ${JSON.stringify(r.name)}`,`table: ${JSON.stringify(r.table)}`];return r.field!==void 0&&a.push(`field: ${JSON.stringify(r.field)}`),r.dimensions!==void 0&&a.push(`dimensions: ${JSON.stringify(r.dimensions)}`),r.metric!==void 0&&a.push(`metric: ${JSON.stringify(r.metric)}`),r.metadata!==void 0&&a.push(`metadata: ${JSON.stringify(r.metadata)}`),` { ${a.join(", ")} },`}).join(`
2224
+ export const LUNORA_CRONS: Record<string, ReadonlyArray<LunoraCronJob>> = {${i}};
2225
+ `},_r=e=>{const t=[...e].toSorted((r,a)=>r.name.localeCompare(a.name)).map(r=>{const a=[`name: ${JSON.stringify(r.name)}`,`table: ${JSON.stringify(r.table)}`];return r.field!==void 0&&a.push(`field: ${JSON.stringify(r.field)}`),r.dimensions!==void 0&&a.push(`dimensions: ${JSON.stringify(r.dimensions)}`),r.metric!==void 0&&a.push(`metric: ${JSON.stringify(r.metric)}`),r.metadata!==void 0&&a.push(`metadata: ${JSON.stringify(r.metadata)}`),` { ${a.join(", ")} },`}).join(`
2147
2226
  `),n=t.length>0?`
2148
2227
  ${t}
2149
2228
  `:"";return`${k}/**
@@ -2167,4 +2246,4 @@ export interface LunoraVectorIndex {
2167
2246
  * \`createWorker({ vectorIntrospector })\` to back the studio's vector browser.
2168
2247
  */
2169
2248
  export const LUNORA_VECTOR_INDEXES: ReadonlyArray<LunoraVectorIndex> = [${n}];
2170
- `},Lr=e=>{const t=new Set,n=[];for(const r of e)t.has(r.cron)||(t.add(r.cron),n.push(r.cron));return n};export{$r as G,Sr as J,vr as K,kr as N,xr as S,Nr as a,br as b,_n as c,mr as d,Tr as g,Lr as m,fr as n,Ar as p,Yt as r,Or as u,k as w,wr as x,yr as y,Rr as z};
2249
+ `},Pr=e=>{const t=new Set,n=[];for(const r of e)t.has(r.cron)||(t.add(r.cron),n.push(r.cron));return n};export{Nr as L,Rr as O,Sr as S,Or as X,Tr as Z,Mn as a,Dr as b,Cr as d,Ar as e,Ir as f,vr as k,xr as n,nn as r,kr as s,Lr as t,$r as v,k as w,Pr as x,_r as y};