@lunora/codegen 1.0.0-alpha.142 → 1.0.0-alpha.144

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.
Files changed (24) hide show
  1. package/dist/index.d.mts +52 -32
  2. package/dist/index.d.ts +52 -32
  3. package/dist/index.mjs +1 -1
  4. package/dist/packem_shared/DEFAULT_TARGET-CwB3hjFH.mjs +1 -0
  5. package/dist/packem_shared/{GENERATED_HEADER-BgmuZY9e.mjs → GENERATED_HEADER-F2VhjmJG.mjs} +1 -1
  6. package/dist/packem_shared/{MUTATORS_FILENAME-DJvAhDlD.mjs → MUTATORS_FILENAME-BKSzaCkq.mjs} +1 -1
  7. package/dist/packem_shared/{OPENRPC_VERSION-B9ZC0SrC.mjs → OPENRPC_VERSION-C30LtXay.mjs} +1 -1
  8. package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-D7qF6qrd.mjs +9 -0
  9. package/dist/packem_shared/{SHAPES_FILENAME-BTdasTq2.mjs → SHAPES_FILENAME-D3N7xcEk.mjs} +1 -1
  10. package/dist/packem_shared/{buildOpenApiDocument-DLEWgA5Y.mjs → buildOpenApiDocument-CmLfuJpW.mjs} +1 -1
  11. package/dist/packem_shared/context-property-calls-DXH-4MTZ.mjs +1 -0
  12. package/dist/packem_shared/{discoverFunctions-BBDziFXy.mjs → discoverFunctions-DglkHRlt.mjs} +1 -1
  13. package/dist/packem_shared/{discoverHttpRoutes-Dmow2gql.mjs → discoverHttpRoutes-B60GWv_I.mjs} +1 -1
  14. package/dist/packem_shared/discoverHyperdriveCalls-De_QiFIl.mjs +1 -0
  15. package/dist/packem_shared/discoverR2sqlCalls-BdkZw-D2.mjs +1 -0
  16. package/dist/packem_shared/{discoverSchema-Bp8DcNq7.mjs → discoverSchema-CubSTjtY.mjs} +1 -1
  17. package/dist/packem_shared/{emit-s6mHBmXu.mjs → emit-EJw8shd_.mjs} +188 -134
  18. package/dist/packem_shared/{emitApp-D1qxNeh1.mjs → emitApp-DftAzAA2.mjs} +52 -39
  19. package/dist/packem_shared/parse-validator-Q58kladC.mjs +1 -0
  20. package/package.json +8 -8
  21. package/dist/packem_shared/DEFAULT_TARGET-CrhWLUK7.mjs +0 -1
  22. package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-iOZaWN69.mjs +0 -9
  23. package/dist/packem_shared/discoverR2sqlCalls-BbfOpwE4.mjs +0 -1
  24. package/dist/packem_shared/parse-validator-BFTp87yz.mjs +0 -1
@@ -1,4 +1,4 @@
1
- import{agentComponent as dt}from"@lunora/agent/component";import{LunoraError as Z}from"@lunora/errors";import{serializeSchemaSnapshot as kn,hashSchemaSnapshot as xn}from"./SCHEMA_SNAPSHOT_VERSION-DLXXalg2.mjs";import{s as N}from"./paths-C-9fwEgQ.mjs";const ut=[{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 ct}from"@lunora/agent/component";import{LunoraError as X}from"@lunora/errors";import{serializeSchemaSnapshot as kn,hashSchemaSnapshot as xn}from"./SCHEMA_SNAPSHOT_VERSION-DLXXalg2.mjs";import{s as T}from"./paths-C-9fwEgQ.mjs";const dt=[{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,40 +15,40 @@ import{agentComponent as dt}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"}],vn=ut,Rn=new Map(vn.flatMap(e=>e.serverCtxField?[[e.key,e.serverCtxField]]:[])),Xr=ut.flatMap(e=>"appMethod"in e?[{appMethod:e.appMethod,key:e.key}]:[]),pt=/^(?:"(?:[^"\\]|\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4}))*"|'[^'\\]*'|-?\d+(?:\.\d+)?|true|false|null)$/u,Sn=new Set(["any","bigint","boolean","date","id","null","number","storage","string","timestamp"]),ht=e=>e.column!==void 0,$n=(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"}],vn=dt,Rn=new Map(vn.flatMap(e=>e.serverCtxField?[[e.key,e.serverCtxField]]:[])),Xr=dt.flatMap(e=>"appMethod"in e?[{appMethod:e.appMethod,key:e.key}]:[]),ut=/^(?:"(?:[^"\\]|\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4}))*"|'[^'\\]*'|-?\d+(?:\.\d+)?|true|false|null)$/u,Sn=new Set(["any","bigint","boolean","date","id","null","number","storage","string","timestamp"]),pt=e=>e.column!==void 0,$n=(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||!pt.test(n)))return{out:t,pre:`if (${t} !== ${n}) return DEFER;
24
- `}},He=(e,t,n)=>{if(!ht(e)&&!(e.hasRefinement||e.sourceText!==void 0)){if(Sn.has(e.kind))return e.kind==="any"?{out:t,pre:""}:{out:t,pre:$n(e.kind,t)};switch(e.kind){case"array":return Tn(e,t,n);case"literal":return Nn(e,t);case"object":return In(e,t,n);default:return}}},Tn=(e,t,n)=>{const{inner:r}=e;if(!r)return;const o=n.next(),s=`__arr${String(o)}`,i=`__i${String(o)}`,a=`__e${String(o)}`,c=He(r,a,n);if(!c)return;const d=`if (!Array.isArray(${t})) return DEFER;
23
+ `}},Tn=(e,t)=>{const n=e.literalValue?.trim();if(!(n===void 0||!ut.test(n)))return{out:t,pre:`if (${t} !== ${n}) return DEFER;
24
+ `}},He=(e,t,n)=>{if(!pt(e)&&!(e.hasRefinement||e.sourceText!==void 0)){if(Sn.has(e.kind))return e.kind==="any"?{out:t,pre:""}:{out:t,pre:$n(e.kind,t)};switch(e.kind){case"array":return Nn(e,t,n);case"literal":return Tn(e,t);case"object":return In(e,t,n);default:return}}},Nn=(e,t,n)=>{const{inner:r}=e;if(!r)return;const o=n.next(),s=`__arr${String(o)}`,i=`__i${String(o)}`,a=`__e${String(o)}`,c=He(r,a,n);if(!c)return;const d=`if (!Array.isArray(${t})) return DEFER;
25
25
  const ${s} = new Array(${t}.length);
26
26
  for (let ${i} = 0; ${i} < ${t}.length; ${i}++) {
27
27
  const ${a} = ${t}[${i}];
28
28
  ${c.pre}${s}[${i}] = ${c.out};
29
29
  }
30
- `;return{out:s,pre:d}},An=(e,t,n,r)=>{const o=JSON.stringify(e);if(t.kind==="optional"){if(t.hasRefinement||t.sourceText!==void 0||ht(t))return;const{inner:i}=t;if(!i)return;const a=He(i,n,r);if(!a)return;const c=r.next(),d=`__has${String(c)}`,p=`__val${String(c)}`,m=`let ${d} = false;
30
+ `;return{out:s,pre:d}},An=(e,t,n,r)=>{const o=JSON.stringify(e);if(t.kind==="optional"){if(t.hasRefinement||t.sourceText!==void 0||pt(t))return;const{inner:i}=t;if(!i)return;const a=He(i,n,r);if(!a)return;const c=r.next(),d=`__has${String(c)}`,p=`__val${String(c)}`,m=`let ${d} = false;
31
31
  let ${p};
32
32
  if (${n} !== undefined) {
33
33
  ${a.pre}${p} = ${a.out};
34
34
  ${d} = true;
35
35
  }
36
- `;return{entry:`...(${d} ? { ${o}: ${p} } : {})`,pre:m}}const s=He(t,n,r);if(s)return{entry:`${o}: ${s.out}`,pre:s.pre}},On=new Set(Object.getOwnPropertyNames(Object.prototype)),mt=(e,t,n)=>{let r="";const o=[];for(const s of Object.keys(e)){const i=e[s];if(!i)return;const a=JSON.stringify(s);let c=`${t}[${a}]`;if(On.has(s)){const p=`__f${String(n.next())}`;r+=`const ${p} = Object.hasOwn(${t}, ${a}) ? ${t}[${a}] : undefined;
37
- `,c=p}const d=An(s,i,c,n);if(!d)return;r+=d.pre,o.push(d.entry)}return{entries:o.join(", "),pre:r}},gt=e=>{const t=`Object.getPrototypeOf(${e})`;return`if (${t} !== Object.prototype && ${t} !== null) return DEFER;
38
- `},In=(e,t,n)=>{const r=e.shape??{},o=mt(r,t,n);if(!o)return;const s=n.next(),i=`__obj${String(s)}`,a=`if (typeof ${t} !== "object" || ${t} === null || Array.isArray(${t})) return DEFER;
39
- ${gt(t)}${o.pre}const ${i} = { ${o.entries} };
40
- `;return{out:i,pre:a}},Cn=e=>{let t=0;const r=mt(e,"source",{next:()=>(t+=1,t)});if(r)return`(source) => {
36
+ `;return{entry:`...(${d} ? { ${o}: ${p} } : {})`,pre:m}}const s=He(t,n,r);if(s)return{entry:`${o}: ${s.out}`,pre:s.pre}},On=new Set(Object.getOwnPropertyNames(Object.prototype)),ht=(e,t,n)=>{let r="";const o=[];for(const s of Object.keys(e)){const i=e[s];if(!i)return;const a=JSON.stringify(s);let c=`${t}[${a}]`;if(On.has(s)){const p=`__f${String(n.next())}`;r+=`const ${p} = Object.hasOwn(${t}, ${a}) ? ${t}[${a}] : undefined;
37
+ `,c=p}const d=An(s,i,c,n);if(!d)return;r+=d.pre,o.push(d.entry)}return{entries:o.join(", "),pre:r}},mt=e=>{const t=`Object.getPrototypeOf(${e})`;return`if (${t} !== Object.prototype && ${t} !== null) return DEFER;
38
+ `},In=(e,t,n)=>{const r=e.shape??{},o=ht(r,t,n);if(!o)return;const s=n.next(),i=`__obj${String(s)}`,a=`if (typeof ${t} !== "object" || ${t} === null || Array.isArray(${t})) return DEFER;
39
+ ${mt(t)}${o.pre}const ${i} = { ${o.entries} };
40
+ `;return{out:i,pre:a}},Cn=e=>{let t=0;const r=ht(e,"source",{next:()=>(t+=1,t)});if(r)return`(source) => {
41
41
  if (typeof source !== "object" || source === null || Array.isArray(source)) return DEFER;
42
- ${gt("source")}${r.pre}return { ${r.entries} };
42
+ ${mt("source")}${r.pre}return { ${r.entries} };
43
43
  }`},$=`// GENERATED by @lunora/codegen — do not edit.
44
44
  // Run \`lunora codegen\` to regenerate.
45
45
 
46
- `,oe=(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"},ft=/^[A-Za-z_$][\w$]*$/u,Ln=/^[\w./-]+$/u,g=(e,t)=>{if(!ft.test(e))throw new Z("INTERNAL",`@lunora/codegen: ${t} is not a valid JS identifier: ${JSON.stringify(e)}`)},Ve=e=>e.charAt(0).toUpperCase()+e.slice(1),q=e=>ft.test(e)?e:JSON.stringify(e),X=e=>e==="__proto__"?`[${JSON.stringify(e)}]`:q(e),_n={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"},En=e=>{if(e===void 0)return"unknown";if(!pt.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},A=e=>{const t=_n[e.kind];if(t!==void 0)return t;switch(e.kind){case"array":return`Array<${e.inner?A(e.inner):"unknown"}>`;case"from":return e.tsType??"unknown";case"id":{const n=e.tableName??"_unknown_";return g(n,"v.id() table name"),`Id<"${n}">`}case"literal":return En(e.literalValue);case"object":return e.shape?`{ ${Object.entries(e.shape).map(([r,o])=>bt(r,o)).join("; ")} }`:"Record<string, unknown>";case"optional":return`${e.inner?A(e.inner):"unknown"} | undefined`;case"record":{const n=e.keyType?A(e.keyType):"string",r=e.valueType?A(e.valueType):"unknown";return`Record<${n}, ${r}>`}case"union":return e.members&&e.members.length>0?e.members.map(n=>A(n)).join(" | "):"never";default:return"unknown"}},bt=(e,t)=>{const n=q(e);if(t.kind==="optional"){const r=t.inner?A(t.inner):"unknown";return`${n}?: ${r}`}return`${n}: ${A(t)}`},xe=e=>{const t=Object.entries(e);return t.length===0?"{}":`{ ${t.map(([n,r])=>bt(n,r)).join("; ")} }`},yt=e=>e.kind==="optional"||!!e.column?.hasDefault,ae=e=>e.kind==="optional"&&e.inner?e.inner:e,Dn=e=>{g(e.name,"table name");const t=Object.entries(e.shape).map(([r,o])=>{const s=ae(o),i=A(s),a=q(r);return yt(o)?` ${a}?: ${i};`:` ${a}: ${i};`}).join(`
46
+ `,oe=(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"},gt=/^[A-Za-z_$][\w$]*$/u,Ln=/^[\w./-]+$/u,g=(e,t)=>{if(!gt.test(e))throw new X("INTERNAL",`@lunora/codegen: ${t} is not a valid JS identifier: ${JSON.stringify(e)}`)},Ve=e=>e.charAt(0).toUpperCase()+e.slice(1),j=e=>gt.test(e)?e:JSON.stringify(e),Y=e=>e==="__proto__"?`[${JSON.stringify(e)}]`:j(e),_n={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"},En=e=>{if(e===void 0)return"unknown";if(!ut.test(e))throw new X("INTERNAL",`@lunora/codegen: v.literal() argument is not a parseable string/number/boolean/null literal: ${JSON.stringify(e)}`);return e},A=e=>{const t=_n[e.kind];if(t!==void 0)return t;switch(e.kind){case"array":return`Array<${e.inner?A(e.inner):"unknown"}>`;case"from":return e.tsType??"unknown";case"id":{const n=e.tableName??"_unknown_";return g(n,"v.id() table name"),`Id<"${n}">`}case"literal":return En(e.literalValue);case"object":return e.shape?`{ ${Object.entries(e.shape).map(([r,o])=>ft(r,o)).join("; ")} }`:"Record<string, unknown>";case"optional":return`${e.inner?A(e.inner):"unknown"} | undefined`;case"record":{const n=e.keyType?A(e.keyType):"string",r=e.valueType?A(e.valueType):"unknown";return`Record<${n}, ${r}>`}case"union":return e.members&&e.members.length>0?e.members.map(n=>A(n)).join(" | "):"never";default:return"unknown"}},ft=(e,t)=>{const n=j(e);if(t.kind==="optional"){const r=t.inner?A(t.inner):"unknown";return`${n}?: ${r}`}return`${n}: ${A(t)}`},xe=e=>{const t=Object.entries(e);return t.length===0?"{}":`{ ${t.map(([n,r])=>ft(n,r)).join("; ")} }`},bt=e=>e.kind==="optional"||!!e.column?.hasDefault,ae=e=>e.kind==="optional"&&e.inner?e.inner:e,Dn=e=>{g(e.name,"table name");const t=Object.entries(e.shape).map(([r,o])=>{const s=ae(o),i=A(s),a=j(r);return bt(o)?` ${a}?: ${i};`:` ${a}: ${i};`}).join(`
47
47
  `),n=t?`
48
48
  ${t}
49
49
  `:"";return`export interface Insert_${e.name} {
50
50
  _id?: Id<"${e.name}">;
51
- _creationTime?: number;${n}}`},Ge="schema",Zr=e=>{for(const u of e.tables)g(u.name,"table name");const t=e.tables.map(u=>`"${u.name}"`).join(" | ")||"never",n=e.tables.filter(u=>u.extensionKey===void 0).map(u=>`"${u.name}"`).join(" | ")||"never",r=e.tables.map(u=>{const l=Object.entries(u.shape).map(([R,x])=>{const I=q(R);if(x.kind==="optional"){const T=x.inner?A(x.inner):"unknown";return` ${I}?: ${T};`}return` ${I}: ${A(x)};`}).join(`
51
+ _creationTime?: number;${n}}`},Ge="schema",Zr=e=>{for(const u of e.tables)g(u.name,"table name");const t=e.tables.map(u=>`"${u.name}"`).join(" | ")||"never",n=e.tables.filter(u=>u.extensionKey===void 0).map(u=>`"${u.name}"`).join(" | ")||"never",r=e.tables.map(u=>{const l=Object.entries(u.shape).map(([R,x])=>{const I=j(R);if(x.kind==="optional"){const N=x.inner?A(x.inner):"unknown";return` ${I}?: ${N};`}return` ${I}: ${A(x)};`}).join(`
52
52
  `),f=l?`
53
53
  ${l}
54
54
  `:"",k=u.commitOrdered===!0?`
@@ -64,7 +64,7 @@ ${l}
64
64
  `),d=e.vectorIndexes.map(u=>JSON.stringify(u.name)).join(" | ")||"never",p=e.tables.map(u=>Dn(u)).join(`
65
65
 
66
66
  `),m=e.tables.map(u=>` ${u.name}: Insert_${u.name};`).join(`
67
- `),y=e.tables.map(u=>{const l=u.relations.map(f=>(g(f.table,"relation target table"),` ${q(f.name)}: ${f.kind==="one"?"OneRelation":"ManyRelation"}<"${f.table}">;`)).join(`
67
+ `),y=e.tables.map(u=>{const l=u.relations.map(f=>(g(f.table,"relation target table"),` ${j(f.name)}: ${f.kind==="one"?"OneRelation":"ManyRelation"}<"${f.table}">;`)).join(`
68
68
  `);return l?` ${u.name}: {
69
69
  ${l}
70
70
  };`:` ${u.name}: {};`}).join(`
@@ -160,8 +160,8 @@ export interface Relations {
160
160
  ${y}
161
161
  }
162
162
 
163
- `,Ge)},Pn=/import\("(?<spec>(?:\.\.?\/)*_generated\/[^"]+)"\)/gu,wt=/^(?:\.\.?\/)*_generated\//u,kt=/\.[A-Za-z]\w*$/u,Fn=e=>e.replaceAll(Pn,(t,n)=>{const r=n.replace(wt,"./");return`import("${kt.test(r)?r:`${r}.js`}")`}),Mn=/import\("(?<spec>[^"]+)"\)/gu,it="node_modules/",Bn=/^@types\//u,jn=e=>e.replaceAll(Mn,(t,n)=>{const r=n.lastIndexOf(it);if(r===-1||r>0&&n[r-1]!=="/")return t;const o=n.slice(r+it.length);return o===""||Bn.test(o)?t:`import("${o}")`}),qn=/import\("(?<spec>\.\.?\/[^"]+)"\)/gu,Wn=/^(?:\.\.?\/)+/u,Un=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("/")},Kn=(e,t)=>e.replaceAll(qn,(n,r)=>{if(wt.test(r.replace(Wn,"")))return n;const o=t.includes("/")?t.slice(0,t.lastIndexOf("/")):"",i=`../${Un(`${o}/${r}`)}`;return`import("${kt.test(i)?i:`${i}.js`}")`}),E=(e,t)=>Fn(Kn(jn(e),t)),Qn=["client","do","errors","flags","observability","platform","ratelimit","runtime","server","values"],Vn=new RegExp(String.raw`import\("@lunora/(?<pkg>${Qn.join("|")})(?<subpath>/[^"]*)?"\)`,"gu"),Hn={flags:new Set(["/web"]),platform:new Set},xt=(e,t)=>t?e.replaceAll(Vn,(n,r,o)=>{const s=Hn[r];return o&&s&&!s.has(o)?n:`import("lunorash/${r}${o??""}")`}):e,Je=e=>["Doc","Id"].filter(t=>new RegExp(String.raw`(?<![.$\w])${t}<`,"u").test(e)),vt=e=>e.output===void 0||e.output.kind==="any"||e.kind==="stream"?e.returnType:A(e.output),ze=e=>{const t=new Map;for(const n of e){const r=t.get(n.filePath)??[];r.push(n),t.set(n.filePath,r)}return[...t.entries()].toSorted(([n],[r])=>n.localeCompare(r))},lt=e=>{const t=([n,r])=>{const o=r.toSorted((s,i)=>s.exportName.localeCompare(i.exportName)).map(s=>{const i=E(xe(s.args),s.filePath),a=E(vt(s),s.filePath);return` ${s.exportName}: FunctionReference<"${s.kind}", ${i}, ${a}>;`}).join(`
164
- `);return` ${q(N(n))}: {
163
+ `,Ge)},Pn=/import\("(?<spec>(?:\.\.?\/)*_generated\/[^"]+)"\)/gu,yt=/^(?:\.\.?\/)*_generated\//u,wt=/\.[A-Za-z]\w*$/u,Fn=e=>e.replaceAll(Pn,(t,n)=>{const r=n.replace(yt,"./");return`import("${wt.test(r)?r:`${r}.js`}")`}),Mn=/import\("(?<spec>[^"]+)"\)/gu,st="node_modules/",Bn=/^@types\//u,qn=e=>e.replaceAll(Mn,(t,n)=>{const r=n.lastIndexOf(st);if(r===-1||r>0&&n[r-1]!=="/")return t;const o=n.slice(r+st.length);return o===""||Bn.test(o)?t:`import("${o}")`}),jn=/import\("(?<spec>\.\.?\/[^"]+)"\)/gu,Wn=/^(?:\.\.?\/)+/u,Un=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("/")},Kn=(e,t)=>e.replaceAll(jn,(n,r)=>{if(yt.test(r.replace(Wn,"")))return n;const o=t.includes("/")?t.slice(0,t.lastIndexOf("/")):"",i=`../${Un(`${o}/${r}`)}`;return`import("${wt.test(i)?i:`${i}.js`}")`}),E=(e,t)=>Fn(Kn(qn(e),t)),Qn=["client","do","errors","flags","observability","platform","ratelimit","runtime","server","values"],Vn=new RegExp(String.raw`import\("@lunora/(?<pkg>${Qn.join("|")})(?<subpath>/[^"]*)?"\)`,"gu"),Hn={flags:new Set(["/web"]),platform:new Set},kt=(e,t)=>t?e.replaceAll(Vn,(n,r,o)=>{const s=Hn[r];return o&&s&&!s.has(o)?n:`import("lunorash/${r}${o??""}")`}):e,Je=e=>["Doc","Id"].filter(t=>new RegExp(String.raw`(?<![.$\w])${t}<`,"u").test(e)),xt=e=>e.output===void 0||e.output.kind==="any"||e.kind==="stream"?e.returnType:A(e.output),ze=e=>{const t=new Map;for(const n of e){const r=t.get(n.filePath)??[];r.push(n),t.set(n.filePath,r)}return[...t.entries()].toSorted(([n],[r])=>n.localeCompare(r))},it=e=>{const t=([n,r])=>{const o=r.toSorted((s,i)=>s.exportName.localeCompare(i.exportName)).map(s=>{const i=E(xe(s.args),s.filePath),a=E(xt(s),s.filePath);return` ${s.exportName}: FunctionReference<"${s.kind}", ${i}, ${a}>;`}).join(`
164
+ `);return` ${j(T(n))}: {
165
165
  ${o}
166
166
  };`};return ze(e).map(n=>t(n)).join(`
167
167
  `)},Gn=(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+=`
@@ -173,7 +173,7 @@ export interface WorkflowReference<Params = Record<string, unknown>> {
173
173
  readonly name: string;
174
174
  }
175
175
  `,e.length>0){const o=[...e].toSorted((a,c)=>a.exportName.localeCompare(c.exportName)),s=o.map(a=>` ${a.exportName}: WorkflowReference<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${a.exportName}>>;`).join(`
176
- `),i=o.map(a=>` ${X(a.exportName)}: { isLunoraWorkflow: true, binding: ${JSON.stringify(a.bindingName)}, name: ${JSON.stringify(a.exportName)} },`).join(`
176
+ `),i=o.map(a=>` ${Y(a.exportName)}: { isLunoraWorkflow: true, binding: ${JSON.stringify(a.bindingName)}, name: ${JSON.stringify(a.exportName)} },`).join(`
177
177
  `);r+=`
178
178
  /** This project's durable workflows, addressable as typed references (e.g. \`crons.daily("digest", …, workflows.digestPipeline, params)\`). */
179
179
  export interface WorkflowsRef {
@@ -185,7 +185,7 @@ ${i}
185
185
  };
186
186
  `,n.push(`import type * as lunoraWorkflowDefinitions from "../workflows.js";
187
187
  `)}if(t.length>0){const o=[...t].toSorted((a,c)=>a.exportName.localeCompare(c.exportName)),s=o.map(a=>` ${a.exportName}: WorkflowReference<AgentRunInput>;`).join(`
188
- `),i=o.map(a=>` ${X(a.exportName)}: { isLunoraWorkflow: true, binding: ${JSON.stringify(a.bindingName)}, name: ${JSON.stringify(a.name)} },`).join(`
188
+ `),i=o.map(a=>` ${Y(a.exportName)}: { isLunoraWorkflow: true, binding: ${JSON.stringify(a.bindingName)}, name: ${JSON.stringify(a.name)} },`).join(`
189
189
  `);r+=`
190
190
  /** 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 })\`). */
191
191
  export interface AgentsRef {
@@ -196,7 +196,7 @@ export const agents: AgentsRef = {
196
196
  ${i}
197
197
  };
198
198
  `,n.push(`import type { AgentRunInput } from "@lunora/agent";
199
- `)}return{block:r,importLine:n.join("")}},Jn=()=>Object.keys(dt().functions).toSorted((e,t)=>e.localeCompare(t)),Rt=e=>new Set(e.filter(t=>N(t.filePath)==="agents").map(t=>t.exportName)),zn=()=>new Set(Object.entries(dt().functions).filter(([,e])=>e.visibility==="internal").map(([e])=>e)),Yn=(e,t)=>{const n={importLine:"",lines:"",prelude:""};if(e.length===0)return n;const r=Rt(t),o=zn(),s=t.find(a=>N(a.filePath)==="agents"&&o.has(a.exportName));if(s)throw new Z("INTERNAL",`@lunora/codegen: "agents:${s.exportName}" is reserved for the durable agent loop's internal dispatch — rename the "${s.exportName}" export in ${s.filePath}`);const i=Jn().filter(a=>!r.has(a));return i.length===0?n:{importLine:`import { agentComponent } from "@lunora/agent/component";
199
+ `)}return{block:r,importLine:n.join("")}},Jn=()=>Object.keys(ct().functions).toSorted((e,t)=>e.localeCompare(t)),vt=e=>new Set(e.filter(t=>T(t.filePath)==="agents").map(t=>t.exportName)),zn=()=>new Set(Object.entries(ct().functions).filter(([,e])=>e.visibility==="internal").map(([e])=>e)),Yn=(e,t)=>{const n={importLine:"",lines:"",prelude:""};if(e.length===0)return n;const r=vt(t),o=zn(),s=t.find(a=>T(a.filePath)==="agents"&&o.has(a.exportName));if(s)throw new X("INTERNAL",`@lunora/codegen: "agents:${s.exportName}" is reserved for the durable agent loop's internal dispatch — rename the "${s.exportName}" export in ${s.filePath}`);const i=Jn().filter(a=>!r.has(a));return i.length===0?n:{importLine:`import { agentComponent } from "@lunora/agent/component";
200
200
  `,lines:i.map(a=>` "agents:${a}": lunoraAgentRuntimeFunctions.${a} as unknown as RegisteredLunoraFunction,`).join(`
201
201
  `),prelude:`
202
202
  /**
@@ -205,13 +205,13 @@ ${i}
205
205
  * subscribe to the public queries (\`agents:agentMessages\` is the live thread view).
206
206
  */
207
207
  const lunoraAgentRuntimeFunctions = agentComponent().functions;
208
- `}},Xn=(e,t)=>{if(!e)return{importLine:"",lines:"",prelude:""};const n=t.find(r=>N(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";
209
- `,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"}},Zn=(e,t)=>{if(e.length===0)return[];const n=Rt(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 o of e)o.voice&&r.push({args:{threadKey:{kind:"string"}},exportName:`${o.exportName}Voice`,filePath:"agents",kind:"stream",returnType:"Record<string, unknown>"});return r.filter(o=>!n.has(o.exportName))},er=(e,t)=>{if(e.length===0)return[];const n=new Set(t.filter(r=>N(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}))},tr=e=>{const t=e.filter(i=>i.stream);if(t.length===0)return{block:"",body:""};const n=ze(t),r=n.map(([i,a])=>{const c=a.map(d=>{const p=E(d.chunkType??"unknown",d.filePath),m=E(xe(d.searchParams),d.filePath),y=E(xe(d.params),d.filePath);return` ${q(d.exportName)}: HttpStreamRef<${p}, ${m}, ${y}>;`}).join(`
210
- `);return` ${q(N(i))}: {
208
+ `}},Xn=(e,t)=>{if(!e)return{importLine:"",lines:"",prelude:""};const n=t.find(r=>T(r.filePath)==="sandbox"&&r.exportName==="invoke");if(n)throw new X("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";
209
+ `,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"}},Zn=(e,t)=>{if(e.length===0)return[];const n=vt(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 o of e)o.voice&&r.push({args:{threadKey:{kind:"string"}},exportName:`${o.exportName}Voice`,filePath:"agents",kind:"stream",returnType:"Record<string, unknown>"});return r.filter(o=>!n.has(o.exportName))},er=(e,t)=>{if(e.length===0)return[];const n=new Set(t.filter(r=>T(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}))},tr=e=>{const t=e.filter(i=>i.stream);if(t.length===0)return{block:"",body:""};const n=ze(t),r=n.map(([i,a])=>{const c=a.map(d=>{const p=E(d.chunkType??"unknown",d.filePath),m=E(xe(d.searchParams),d.filePath),y=E(xe(d.params),d.filePath);return` ${j(d.exportName)}: HttpStreamRef<${p}, ${m}, ${y}>;`}).join(`
210
+ `);return` ${j(T(i))}: {
211
211
  ${c}
212
212
  };`}).join(`
213
- `),o=n.map(([i,a])=>{const c=a.map(d=>` ${X(d.exportName)}: { method: ${JSON.stringify(d.method)}, path: ${JSON.stringify(d.path)} },`).join(`
214
- `);return` ${X(N(i))}: {
213
+ `),o=n.map(([i,a])=>{const c=a.map(d=>` ${Y(d.exportName)}: { method: ${JSON.stringify(d.method)}, path: ${JSON.stringify(d.path)} },`).join(`
214
+ `);return` ${Y(T(i))}: {
215
215
  ${c}
216
216
  },`}).join(`
217
217
  `);return{block:`
@@ -223,7 +223,7 @@ ${r}
223
223
  export const httpStreams: HttpStreamsRef = {
224
224
  ${o}
225
225
  };
226
- `,body:r}},eo=e=>{const{agents:t=[],functions:n,httpRoutes:r=[],mutators:o=[],useUmbrella:s=!1,workflows:i=[]}=e,a=oe(s),c=[...n.filter(v=>v.visibility!=="internal"),...Zn(t,n),...er(o,n)],d=n.filter(v=>v.visibility==="internal"),p=lt(c),m=lt(d),y=tr(r),u=`${p}
226
+ `,body:r}},eo=e=>{const{agents:t=[],functions:n,httpRoutes:r=[],mutators:o=[],useUmbrella:s=!1,workflows:i=[]}=e,a=oe(s),c=[...n.filter(v=>v.visibility!=="internal"),...Zn(t,n),...er(o,n)],d=n.filter(v=>v.visibility==="internal"),p=it(c),m=it(d),y=tr(r),u=`${p}
227
227
  ${m}
228
228
  ${y.body}`,l=Je(u),f=l.length>0?`
229
229
  import type { ${l.join(", ")} } from "./dataModel.js";
@@ -239,8 +239,8 @@ export const api = anyApi as unknown as ApiTypes;
239
239
  export interface InternalApiTypes {${R}}
240
240
 
241
241
  export const internal = anyApi as unknown as InternalApiTypes;
242
- ${x.block}${y.block}`,T=[...I.includes("FunctionReference<")?["FunctionReference"]:[],...y.block===""?[]:["HttpStreamRef"]],_=T.length>0?`import type { ${T.join(", ")} } from "${a.client}";
243
- `:"";return xt(`${$}import { anyApi } from "${a.client}";
242
+ ${x.block}${y.block}`,N=[...I.includes("FunctionReference<")?["FunctionReference"]:[],...y.block===""?[]:["HttpStreamRef"]],_=N.length>0?`import type { ${N.join(", ")} } from "${a.client}";
243
+ `:"";return kt(`${$}import { anyApi } from "${a.client}";
244
244
  ${_}${x.importLine}${f}
245
245
  ${I}`,s)},to=e=>e?`${$}import { createSeedClient as createSeedClientBase } from "@lunora/seed";
246
246
  import type { SeedClient, SeedClientOptions } from "@lunora/seed";
@@ -313,7 +313,7 @@ import type { Collection } from "@tanstack/db";
313
313
  import { createCollection } from "@tanstack/db";
314
314
  ${a}
315
315
  ${s}
316
- `},nr=(e,t)=>`lunora_${N(e)}_${String(t)}`,rr=`const callRegistered = async <R>(context: CallerCtx, functionPath: string, args: Record<string, unknown> | undefined): Promise<R> => {
316
+ `},nr=(e,t)=>`lunora_${T(e)}_${String(t)}`,rr=`const callRegistered = async <R>(context: CallerCtx, functionPath: string, args: Record<string, unknown> | undefined): Promise<R> => {
317
317
  const registered = LUNORA_FUNCTIONS[functionPath];
318
318
 
319
319
  if (!registered) {
@@ -321,12 +321,12 @@ ${s}
321
321
  }
322
322
 
323
323
  return (await registered.handler(context, args ?? {})) as R;
324
- };`,or=(e,t,n=[],r=[])=>{const o=new Map,s=l=>{o.has(l)||o.set(l,nr(l,o.size))};for(const l of e)s(l.filePath);for(const l of t)s(l.filePath);for(const l of n)s(l.filePath);for(const l of r)s(l.filePath);const i=[...o.entries()].map(([l,f])=>{if(!Ln.test(l))throw new Z("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(l)}`);return`import * as ${f} from "../${l}.js";`}).join(`
325
- `),a=e.map(l=>` "${N(l.filePath)}:${l.exportName}": ${o.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredLunoraFunction,`).join(`
324
+ };`,or=(e,t,n=[],r=[])=>{const o=new Map,s=l=>{o.has(l)||o.set(l,nr(l,o.size))};for(const l of e)s(l.filePath);for(const l of t)s(l.filePath);for(const l of n)s(l.filePath);for(const l of r)s(l.filePath);const i=[...o.entries()].map(([l,f])=>{if(!Ln.test(l))throw new X("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(l)}`);return`import * as ${f} from "../${l}.js";`}).join(`
325
+ `),a=e.map(l=>` "${T(l.filePath)}:${l.exportName}": ${o.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredLunoraFunction,`).join(`
326
326
  `),c=t.map(l=>` ${JSON.stringify(l.id)}: ${o.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredDataMigration,`).join(`
327
- `),d=n.map(l=>` "${N(l.filePath)}:${l.exportName}": ${o.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredLunoraFunction,`).join(`
327
+ `),d=n.map(l=>` "${T(l.filePath)}:${l.exportName}": ${o.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredLunoraFunction,`).join(`
328
328
  `),p=r.map(l=>` "${l.exportName}": ${o.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredShape,`).join(`
329
- `),m=n.map(l=>`${N(l.filePath)}:${l.exportName}`),y=[a,d].filter(l=>l.length>0).join(`
329
+ `),m=n.map(l=>`${T(l.filePath)}:${l.exportName}`),y=[a,d].filter(l=>l.length>0).join(`
330
330
  `),u=e.map(l=>{if(l.lifecycle||Object.keys(l.args).length===0)return;const f=Cn(l.args);return f===void 0?void 0:`installCompiledValidatorMap(${o.get(l.filePath)??""}.${l.exportName}.args, ${f});`}).filter(l=>l!==void 0).join(`
331
331
  `);return{dispatchBody:y.length>0?`
332
332
  ${y}
@@ -336,22 +336,22 @@ ${y}
336
336
  ${c}
337
337
  `:"",mutatorPaths:m,shapeBody:p.length>0?`
338
338
  ${p}
339
- `:""}},ar=e=>{const t=ze(e),n=t.map(([o,s])=>{const i=s.map(a=>{const c=E(xe(a.args),a.filePath),d=c==="{}"?"?":"",p=E(vt(a),a.filePath);return a.kind==="stream"?` ${a.exportName}: (args${d}: ${c}) => Promise<AsyncIterable<${p}>>;`:` ${a.exportName}: (args${d}: ${c}) => Promise<${p}>;`}).join(`
340
- `);return` ${q(N(o))}: {
339
+ `:""}},ar=e=>{const t=ze(e),n=t.map(([o,s])=>{const i=s.map(a=>{const c=E(xe(a.args),a.filePath),d=c==="{}"?"?":"",p=E(xt(a),a.filePath);return a.kind==="stream"?` ${a.exportName}: (args${d}: ${c}) => Promise<AsyncIterable<${p}>>;`:` ${a.exportName}: (args${d}: ${c}) => Promise<${p}>;`}).join(`
340
+ `);return` ${j(T(o))}: {
341
341
  ${i}
342
342
  };`}).join(`
343
- `);return{implementation:t.map(([o,s])=>{const i=N(o),a=s.map(c=>` ${X(c.exportName)}: (args) => callRegistered(context, "${i}:${c.exportName}", args),`).join(`
344
- `);return` ${X(i)}: {
343
+ `);return{implementation:t.map(([o,s])=>{const i=T(o),a=s.map(c=>` ${Y(c.exportName)}: (args) => callRegistered(context, "${i}:${c.exportName}", args),`).join(`
344
+ `);return` ${Y(i)}: {
345
345
  ${a}
346
346
  },`}).join(`
347
- `),types:n}},sr=(e,t=[])=>{const n=new Set;for(const r of e.tables)for(const o of Object.values(r.shape)){const s=ae(o);s.kind==="storage"&&typeof s.bucket=="string"&&s.bucket!==""&&n.add(s.bucket)}for(const r of t)r!==""&&r!=="default"&&n.add(r);return["default",...[...n].toSorted((r,o)=>r.localeCompare(o))]},ro=({agents:e=[],containers:t=[],env:n,hasAccessFacade:r=!1,hasAi:o=!1,hasAnalytics:s=!1,hasBrowser:i=!1,hasFlags:a=!1,hasHyperdrive:c=!1,hasImages:d=!1,hasKv:p=!1,hasNotify:m=!1,hasPayments:y=!1,hasPipelines:u=!1,hasR2sql:l=!1,hasX402:f=!1,identity:k,queues:R=[],schema:x,storageRuleBuckets:I=[],useUmbrella:T=!1,workflows:_=[]}={})=>{const v=oe(T),w=sr(x??{tables:[]},I).map(h=>JSON.stringify(h)).join(" | "),F=o?`import type { LunoraAi } from "@lunora/ai";
347
+ `),types:n}},sr=(e,t=[])=>{const n=new Set;for(const r of e.tables)for(const o of Object.values(r.shape)){const s=ae(o);s.kind==="storage"&&typeof s.bucket=="string"&&s.bucket!==""&&n.add(s.bucket)}for(const r of t)r!==""&&r!=="default"&&n.add(r);return["default",...[...n].toSorted((r,o)=>r.localeCompare(o))]},ro=({agents:e=[],containers:t=[],env:n,hasAccessFacade:r=!1,hasAi:o=!1,hasAnalytics:s=!1,hasBrowser:i=!1,hasFlags:a=!1,hasHyperdrive:c=!1,hasImages:d=!1,hasKv:p=!1,hasNotify:m=!1,hasPayments:y=!1,hasPipelines:u=!1,hasR2sql:l=!1,hasX402:f=!1,identity:k,queues:R=[],schema:x,storageRuleBuckets:I=[],useUmbrella:N=!1,workflows:_=[]}={})=>{const v=oe(N),w=sr(x??{tables:[]},I).map(h=>JSON.stringify(h)).join(" | "),F=o?`import type { LunoraAi } from "@lunora/ai";
348
348
  `:"",se=o?`
349
349
  readonly ai: LunoraAi;`:"",M=y?`import type { LunoraPayment } from "@lunora/payment";
350
350
  `:"",ie=y?`
351
351
  readonly payments: LunoraPayment;`:"",le=f?`import type { X402Pay } from "@lunora/x402/pay";
352
352
  `:"",W=f?`
353
353
  readonly x402: X402Pay;`:"",C=t.length>0?`import type { ContainerAccessor } from "@lunora/container";
354
- `:"",ee=t.length>0?`
354
+ `:"",Z=t.length>0?`
355
355
  readonly containers: {${t.map(h=>`
356
356
  readonly ${h.exportName}: ContainerAccessor;`).join("")}
357
357
  };`:"",L=[...o?[" /** Workers AI binding (the conventional `env.AI`), narrowing `ctx.ai`. */\n readonly AI?: unknown;"]:[],...t.map(h=>(g(h.bindingName,`container binding "${h.bindingName}"`),` /** Durable Object namespace for the \`${h.exportName}\` container. */
@@ -377,7 +377,7 @@ ${L}`:""}
377
377
  }
378
378
 
379
379
  /** Alias for {@link CloudflareBindings} — the typed shape of \`env\`. */
380
- export type Env = CloudflareBindings;`,B=(h,qe,Ne)=>{const re=Rn.get(h);if(re!==void 0&&re.tier!==Ne)throw new Z("INTERNAL",`@lunora/codegen: capability "${h}" declares tier "${re.tier}" in SERVER_CTX_FIELDS but is emitted onto the "${Ne}" context — update whichever is wrong.`);return qe?re?.field??"":""},ce=B("kv",p,"every"),de=B("analytics",s,"every"),Ae=B("hyperdrive",c,"action"),Oe=B("browser",i,"action"),Ie=B("images",d,"action"),ue=B("pipelines",u,"action"),V=B("r2sql",l,"action"),P=(x?.vectorIndexes.length??0)>0,H=P?' | "vectors"':"",te=P?`
380
+ export type Env = CloudflareBindings;`,B=(h,je,Te)=>{const ne=Rn.get(h);if(ne!==void 0&&ne.tier!==Te)throw new X("INTERNAL",`@lunora/codegen: capability "${h}" declares tier "${ne.tier}" in SERVER_CTX_FIELDS but is emitted onto the "${Te}" context — update whichever is wrong.`);return je?ne?.field??"":""},ce=B("kv",p,"every"),de=B("analytics",s,"every"),Ae=B("hyperdrive",c,"action"),Oe=B("browser",i,"action"),Ie=B("images",d,"action"),ue=B("pipelines",u,"action"),V=B("r2sql",l,"action"),P=(x?.vectorIndexes.length??0)>0,H=P?' | "vectors"':"",ee=P?`
381
381
  readonly vectors: VectorSearch<VectorIndexName>;`:"",pe=P?`
382
382
  readonly vectors: VectorSearchReader<VectorIndexName>;`:"",G=P?`import type { VectorSearch, VectorSearchReader } from "${v.server}";
383
383
  import type { VectorIndexName } from "./dataModel.js";
@@ -389,9 +389,9 @@ import type { VectorIndexName } from "./dataModel.js";
389
389
  /** 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. */
390
390
  readonly notify: import("@lunora/notify").LunoraNotify;
391
391
  /** Device push sub-facade — the same object as ctx.notify.push (register / send / broadcast). Sends belong in action handlers. */
392
- readonly push: import("@lunora/notify").LunoraPush;`:"",j=_.length>0,ne=j?`import type { WorkflowHandle } from "@lunora/workflow";
392
+ readonly push: import("@lunora/notify").LunoraPush;`:"",q=_.length>0,te=q?`import type { WorkflowHandle } from "@lunora/workflow";
393
393
  import type * as lunoraWorkflowDefinitions from "../workflows.js";
394
- `:"",Ce=j?`
394
+ `:"",Ce=q?`
395
395
 
396
396
  /** Params type carried by a \`defineWorkflow\` definition (its phantom \`__params\`). */
397
397
  type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params }
@@ -404,7 +404,7 @@ type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params
404
404
  export interface LunoraWorkflows {
405
405
  ${_.map(h=>` get(name: ${JSON.stringify(h.exportName)}): WorkflowHandle<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${h.exportName}>>;`).join(`
406
406
  `)}
407
- }`:"",ve=j?' | "workflows"':"",Re=j?`
407
+ }`:"",ve=q?' | "workflows"':"",Re=q?`
408
408
  readonly workflows: LunoraWorkflows;`:"",he=R.length>0,Le=he?`import type { QueueProducer } from "@lunora/queue";
409
409
  import type * as lunoraQueueDefinitions from "../queues.js";
410
410
  `:"",_e=he?`
@@ -435,7 +435,7 @@ export type Identity = InferIdentity<typeof lunoraIdentityContract.${k.exportNam
435
435
  /** \`ctx.auth\` narrowed so \`getIdentity()\` resolves the declared {@link Identity} contract instead of the untyped claim bag. */
436
436
  type NarrowedAuth = Omit<QueryCtxBase["auth"], "getIdentity"> & { getIdentity: () => Promise<Identity | null> };`:"",ge=k?' | "auth"':"",fe=k?`
437
437
  readonly auth: NarrowedAuth;`:"",Me=k?", Identity":"",Be=n?`import type * as lunoraEnvContract from "../env.js";
438
- `:"",je=n?`
438
+ `:"",qe=n?`
439
439
 
440
440
  /** This app's declared env contract (\`defineEnv\` in \`lunora/env.ts\`) — the validated, coercion-aware shape of \`ctx.env\`. */
441
441
  export type LunoraEnv = ReturnType<typeof lunoraEnvContract.${n.exportName}>;`:"",be=n?' | "env"':"",ye=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`${$}import { createPolicyDsl, defineMutator as defineMutatorBase, initLunora, v as vBase } from "${v.server}";
@@ -495,7 +495,7 @@ export type {
495
495
  } from "${v.serverDataModel}";
496
496
 
497
497
  import type { DataModel, Doc, GeoIndexNamesByTable, Id as IdOfTable, IndexNamesByTable, Insert, InsertModel, RankIndexNamesByTable, Relations, SearchIndexNamesByTable, TableName } from "./dataModel.js";
498
- ${G}${F}${M}${le}${C}${ne}${Le}${Ee}${Pe}${Be}
498
+ ${G}${F}${M}${le}${C}${te}${Le}${Ee}${Pe}${Be}
499
499
  export type { AppTableName, DataModel, Doc, Id, TableName } from "./dataModel.js";
500
500
 
501
501
  /**
@@ -555,7 +555,7 @@ export interface OrmWriter extends OrmReader {
555
555
  }
556
556
 
557
557
  /** Storage buckets this schema declares (\`v.storage("name")\`), narrowing \`ctx.storage.bucket(name)\`. */
558
- export type StorageBucketName = ${w};${S}${Ce}${_e}${De}${Fe}${je}
558
+ export type StorageBucketName = ${w};${S}${Ce}${_e}${De}${Fe}${qe}
559
559
 
560
560
  /**
561
561
  * Project-typed contexts. The base contexts from \`@lunora/server\` are
@@ -627,13 +627,13 @@ export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"${H}${ge}${
627
627
  export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${H}${ve}${ge}${be}> {
628
628
  readonly db: Omit<DatabaseWriter, "asId" | "query" | "get"> & DatabaseWriterFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
629
629
  readonly orm: OrmWriter;
630
- readonly storage: MutationStorage<StorageBucketName>;${te}${U}${ce}${K}${Q}${de}${ye}${Re}${Se}${$e}${fe}
630
+ readonly storage: MutationStorage<StorageBucketName>;${ee}${U}${ce}${K}${Q}${de}${ye}${Re}${Se}${$e}${fe}
631
631
  }
632
632
 
633
633
  export interface ActionCtx extends Omit<ActionCtxBase, "db" | "storage"${H}${ve}${ge}${be}> {
634
634
  readonly db: Omit<DatabaseWriter, "asId" | "query" | "get"> & DatabaseWriterFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
635
635
  readonly orm: OrmWriter;
636
- readonly storage: StorageBase<StorageBucketName>;${te}${U}${se}${ie}${W}${ee}${ce}${K}${Q}${Ae}${Oe}${Ie}${de}${ue}${V}${ye}${Re}${Se}${$e}${fe}
636
+ readonly storage: StorageBase<StorageBucketName>;${ee}${U}${se}${ie}${W}${Z}${ce}${K}${Q}${Ae}${Oe}${Ie}${de}${ue}${V}${ye}${Re}${Se}${$e}${fe}
637
637
  }
638
638
 
639
639
  /**
@@ -708,12 +708,12 @@ export const definePolicy = createPolicyDsl<DataModel, Relations${Me}>();
708
708
  export const v = vBase as unknown as Omit<typeof vBase, "id"> & {
709
709
  id: <T extends TableName>(table: T) => ColumnValidator<IdOfTable<T>, IdOfTable<T>>;
710
710
  };
711
- `},ir=e=>{const t={connect:[],disconnect:[],init:[],reactor:[]};for(const n of e)n.lifecycle&&t[n.lifecycle].push(`${N(n.filePath)}:${n.exportName}`);return t},oo=e=>{const{agents:t=[],functions:n,migrations:r=[],mutators:o=[],shapes:s=[],useUmbrella:i=!1,usesSandbox:a=!1}=e,c=n.length>0,d=oe(i),{dispatchBody:p,importBlock:m,installBlock:y,migrationBody:u,mutatorPaths:l,shapeBody:f}=or(n,r,o,s),k=Yn(t,n),R=Xn(a,n),x=[k.lines,R.lines].filter(S=>S.length>0).join(`
711
+ `},ir=e=>{const t={connect:[],disconnect:[],init:[],reactor:[]};for(const n of e)n.lifecycle&&t[n.lifecycle].push(`${T(n.filePath)}:${n.exportName}`);return t},oo=e=>{const{agents:t=[],functions:n,migrations:r=[],mutators:o=[],shapes:s=[],useUmbrella:i=!1,usesSandbox:a=!1}=e,c=n.length>0,d=oe(i),{dispatchBody:p,importBlock:m,installBlock:y,migrationBody:u,mutatorPaths:l,shapeBody:f}=or(n,r,o,s),k=Yn(t,n),R=Xn(a,n),x=[k.lines,R.lines].filter(S=>S.length>0).join(`
712
712
  `);let I=p;x.length>0&&(I=p.length>0?`${p.trimEnd()}
713
713
  ${x}
714
714
  `:`
715
715
  ${x}
716
- `);const T=ir(n),_=s.length>0?`import type { RegisteredShape } from "${d.server}";
716
+ `);const N=ir(n),_=s.length>0?`import type { RegisteredShape } from "${d.server}";
717
717
  `:"",v=s.length>0?`
718
718
  /**
719
719
  * Replication-shape registry — one entry per \`defineShape\` in \`lunora/shapes.ts\`.
@@ -742,9 +742,9 @@ ${M.types}
742
742
  `:"",le=M.implementation?`
743
743
  ${M.implementation}
744
744
  `:"",W=Je(M.types),C=W.length>0?`import type { ${W.join(", ")} } from "./dataModel.js";
745
- `:"",ee=c?"context":"_context",L=c?`${rr}
745
+ `:"",Z=c?"context":"_context",L=c?`${rr}
746
746
 
747
- `:"";return xt(`${$}${m}${k.importLine}${R.importLine}${F}${_}import { LunoraError } from "${d.server}";
747
+ `:"";return kt(`${$}${m}${k.importLine}${R.importLine}${F}${_}import { LunoraError } from "${d.server}";
748
748
  import type { ActionCtx, MutationCtx, QueryCtx } from "./server.js";
749
749
  ${C}
750
750
  /**
@@ -795,10 +795,10 @@ ${se}${v}${w}
795
795
  * anonymous — all via system dispatch.
796
796
  */
797
797
  export const LUNORA_LIFECYCLE_HOOKS: { connect: readonly string[]; disconnect: readonly string[]; init: readonly string[]; reactor: readonly string[] } = {
798
- connect: [${T.connect.map(S=>JSON.stringify(S)).join(", ")}],
799
- disconnect: [${T.disconnect.map(S=>JSON.stringify(S)).join(", ")}],
800
- init: [${T.init.map(S=>JSON.stringify(S)).join(", ")}],
801
- reactor: [${T.reactor.map(S=>JSON.stringify(S)).join(", ")}],
798
+ connect: [${N.connect.map(S=>JSON.stringify(S)).join(", ")}],
799
+ disconnect: [${N.disconnect.map(S=>JSON.stringify(S)).join(", ")}],
800
+ init: [${N.init.map(S=>JSON.stringify(S)).join(", ")}],
801
+ reactor: [${N.reactor.map(S=>JSON.stringify(S)).join(", ")}],
802
802
  };
803
803
 
804
804
  /**
@@ -832,7 +832,7 @@ export type CallerCtx = ActionCtx | MutationCtx | QueryCtx;
832
832
  export interface Caller {${ie}}
833
833
 
834
834
  ${L}/** Build a {@link Caller} bound to \`context\` (typically a handler's \`ctx\`). */
835
- export const createCaller = (${ee}: CallerCtx): Caller => ({${le}});
835
+ export const createCaller = (${Z}: CallerCtx): Caller => ({${le}});
836
836
 
837
837
  /**
838
838
  * Single registered data migration, narrowed to the shape the per-shard runner
@@ -852,7 +852,7 @@ export interface RegisteredDataMigration {
852
852
  * shard DO's admin RPC and the CLI resolve migrations to run through this map.
853
853
  */
854
854
  export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${u}};
855
- `,i)},lr=e=>{const t={};for(const n of e.tables){const r={};for(const[o,s]of Object.entries(n.shape)){const i=ae(s);i.kind==="id"&&i.tableName!==void 0&&(r[o]=i.tableName)}Object.keys(r).length>0&&(t[n.name]=r)}return t},cr=e=>{const t={};for(const n of e.tables){const r=[];for(const[o,s]of Object.entries(n.shape))ae(s).kind==="storage"&&r.push(o);r.length>0&&(t[n.name]=r)}return t},dr=e=>{const t={};for(const n of e.tables){const r=[...n.indexes.map(o=>({fields:[...o.fields],name:o.name,type:"index",...o.unique===!0?{unique:!0}:{}})),...n.searchIndexes.map(o=>({fields:[o.field,...o.filterFields??[]],name:o.name,type:"search"})),...(n.geoIndexes??[]).map(o=>({fields:[o.field],name:o.name,type:"geo"})),...n.rankIndexes.map(o=>({fields:o.sortBy.map(s=>s.field),name:o.name,type:"rank"})),...n.vectorIndexes.map(o=>({fields:o.field===void 0?[]:[o.field],name:o.name,type:"vector"}))];r.length>0&&(t[n.name]=r)}return t},ur=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},pr=e=>{if(e.kind!=="union"||e.members===void 0||e.members.length===0)return;const t=[];for(const n of e.members){if(n.kind!=="literal"||n.literalValue===void 0)return;try{const r=JSON.parse(n.literalValue);if(typeof r!="string")return;t.push(r)}catch{return}}return t},hr=(e,t)=>{const n=ae(t),r={name:e,optional:yt(t),type:n.kind};n.kind==="id"&&n.tableName!==void 0&&(r.ref=n.tableName),n.kind==="storage"&&(r.isStorage=!0,n.bucket!==void 0&&(r.bucket=n.bucket));const o=pr(n);return o!==void 0&&(r.enumValues=o),n.column?.notNull===!1&&(r.nullable=!0),r},mr=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"},...n.commitOrdered===!0?[{name:"_commitSeq",optional:!1,type:"number"}]:[]];for(const[o,s]of Object.entries(n.shape))r.push(hr(o,s));t[n.name]=r}return t},gr=e=>e?{importFragment:"serveRelationFanout, ",override:`
855
+ `,i)},lr=e=>{const t={};for(const n of e.tables){const r={};for(const[o,s]of Object.entries(n.shape)){const i=ae(s);i.kind==="id"&&i.tableName!==void 0&&(r[o]=i.tableName)}Object.keys(r).length>0&&(t[n.name]=r)}return t},cr=e=>{const t={};for(const n of e.tables){const r=[];for(const[o,s]of Object.entries(n.shape))ae(s).kind==="storage"&&r.push(o);r.length>0&&(t[n.name]=r)}return t},dr=e=>{const t={};for(const n of e.tables){const r=[...n.indexes.map(o=>({fields:[...o.fields],name:o.name,type:"index",...o.unique===!0?{unique:!0}:{}})),...n.searchIndexes.map(o=>({fields:[o.field,...o.filterFields??[]],name:o.name,type:"search"})),...(n.geoIndexes??[]).map(o=>({fields:[o.field],name:o.name,type:"geo"})),...n.rankIndexes.map(o=>({fields:o.sortBy.map(s=>s.field),name:o.name,type:"rank"})),...n.vectorIndexes.map(o=>({fields:o.field===void 0?[]:[o.field],name:o.name,type:"vector"}))];r.length>0&&(t[n.name]=r)}return t},ur=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},pr=e=>{if(e.kind!=="union"||e.members===void 0||e.members.length===0)return;const t=[];for(const n of e.members){if(n.kind!=="literal"||n.literalValue===void 0)return;try{const r=JSON.parse(n.literalValue);if(typeof r!="string")return;t.push(r)}catch{return}}return t},hr=(e,t)=>{const n=ae(t),r={name:e,optional:bt(t),type:n.kind};n.kind==="id"&&n.tableName!==void 0&&(r.ref=n.tableName),n.kind==="storage"&&(r.isStorage=!0,n.bucket!==void 0&&(r.bucket=n.bucket));const o=pr(n);return o!==void 0&&(r.enumValues=o),n.column?.notNull===!1&&(r.nullable=!0),r},mr=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"},...n.commitOrdered===!0?[{name:"_commitSeq",optional:!1,type:"number"}]:[]];for(const[o,s]of Object.entries(n.shape))r.push(hr(o,s));t[n.name]=r}return t},gr=e=>e?{importFragment:"serveRelationFanout, ",override:`
856
856
  protected override async runRelationFanoutRead(functionPath: string, args: Record<string, unknown>): Promise<unknown> {
857
857
  this.ensureMigrated();
858
858
 
@@ -1005,11 +1005,11 @@ const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number"
1005
1005
  const sql: SqlClient = config.sql ? config.sql(env) : sqlStub;
1006
1006
  `,configField:`
1007
1007
  sql?: (env: Record<string, unknown>) => SqlClient;`,contextField:`
1008
- sql,`,importLines:['import type { SqlClient } from "@lunora/hyperdrive";'],stub:O("sqlStub: SqlClient",'throw new Error("ctx.sql: provide a \\`sql\\` config thunk that builds a SqlClient from your driver, e.g. \\`sql: (env) => fromPostgresJs(postgres(env.HYPERDRIVE.connectionString))\\`.");',["query"])}:D,Nr=e=>e?{build:`
1008
+ sql,`,importLines:['import type { SqlClient } from "@lunora/hyperdrive";'],stub:O("sqlStub: SqlClient",'throw new Error("ctx.sql: provide a \\`sql\\` config thunk that builds a SqlClient from your driver, e.g. \\`sql: (env) => fromPostgresJs(postgres(env.HYPERDRIVE.connectionString))\\`.");',["query"])}:D,Tr=e=>e?{build:`
1009
1009
  const browser: Browser = config.browser ? config.browser(env) : browserStub;
1010
1010
  `,configField:`
1011
1011
  browser?: (env: Record<string, unknown>) => Browser;`,contextField:`
1012
- browser,`,importLines:['import type { Browser } from "@lunora/browser";'],stub:O("browserStub: Browser","throw new Error(\"ctx.browser: provide a \\`browser\\` config thunk, e.g. \\`browser: (env) => createBrowser({ binding: env.BROWSER, launch })\\` with \\`import { launch } from '@cloudflare/playwright'\\`. Session reuse (connect/sessions) additionally needs those two exports passed the same way.\");",["connect","content","launch","pdf","scrape","screenshot","sessions"])}:D,Tr=e=>e?{build:`
1012
+ browser,`,importLines:['import type { Browser } from "@lunora/browser";'],stub:O("browserStub: Browser","throw new Error(\"ctx.browser: provide a \\`browser\\` config thunk, e.g. \\`browser: (env) => createBrowser({ binding: env.BROWSER, launch })\\` with \\`import { launch } from '@cloudflare/playwright'\\`. Session reuse (connect/sessions) additionally needs those two exports passed the same way.\");",["connect","content","launch","pdf","scrape","screenshot","sessions"])}:D,Nr=e=>e?{build:`
1013
1013
  const r2sqlEnv = env as Record<string, unknown>;
1014
1014
  const r2sqlAccountId = (r2sqlEnv.R2_SQL_ACCOUNT_ID ?? r2sqlEnv.CLOUDFLARE_ACCOUNT_ID) as string | undefined;
1015
1015
  const r2sqlToken = r2sqlEnv.R2_SQL_TOKEN as string | undefined;
@@ -1156,14 +1156,14 @@ ${t}
1156
1156
  const LUNORA_AGENTS: ReadonlyArray<AgentBindingSpec> = [
1157
1157
  ${t}
1158
1158
  ];
1159
- `}},St=(e,t,n,r,o)=>({constant:`
1159
+ `}},Rt=(e,t,n,r,o)=>({constant:`
1160
1160
  ${o}
1161
1161
  const ${e}: ${t} = ${JSON.stringify(r,void 0,4)};
1162
1162
  `,override:`
1163
1163
  protected override ${n}(): ${t} {
1164
1164
  return ${e};
1165
1165
  }
1166
- `}),_r=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 St("LUNORA_WORKFLOWS_INFO","WorkflowsResult","workflowsMetadata",t,"/** Read-only declared-workflow metadata (discovered from `lunora/workflows.ts`) served via `__lunora_admin__:listWorkflows` for the studio's workflows view. */")},Er=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 St("LUNORA_QUEUES_INFO","QueuesResult","queuesMetadata",t,"/** Read-only declared-queue metadata (discovered from `lunora/queues.ts`) served via `__lunora_admin__:listQueues` for the studio's queues view. */")},Dr=e=>e?{imports:['import type { LunoraDatabaseLike as LunoraPaymentDbLike, LunoraPayment, PaymentsFromContextOptions } from "@lunora/payment";','import { paymentsFromContext } from "@lunora/payment";'],build:`
1166
+ `}),_r=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 Rt("LUNORA_WORKFLOWS_INFO","WorkflowsResult","workflowsMetadata",t,"/** Read-only declared-workflow metadata (discovered from `lunora/workflows.ts`) served via `__lunora_admin__:listWorkflows` for the studio's workflows view. */")},Er=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 Rt("LUNORA_QUEUES_INFO","QueuesResult","queuesMetadata",t,"/** Read-only declared-queue metadata (discovered from `lunora/queues.ts`) served via `__lunora_admin__:listQueues` for the studio's queues view. */")},Dr=e=>e?{imports:['import type { LunoraDatabaseLike as LunoraPaymentDbLike, LunoraPayment, PaymentsFromContextOptions } from "@lunora/payment";','import { paymentsFromContext } from "@lunora/payment";'],build:`
1167
1167
  const payments: LunoraPayment = config.payment
1168
1168
  ? paymentsFromContext({ auth: { userId: userId ?? null }, db: db as unknown as LunoraPaymentDbLike }, config.payment(env))
1169
1169
  : paymentStub;
@@ -1174,10 +1174,10 @@ const ${e}: ${t} = ${JSON.stringify(r,void 0,4)};
1174
1174
  ? lazyX402Pay(config.x402(env), { getSecret: (name: string) => secrets.get(name) })
1175
1175
  : x402Stub;
1176
1176
  `,configField:`
1177
- x402?: (env: Record<string, unknown>) => X402PayConfig;`,stub:O("x402Stub: X402Pay",'throw new Error("ctx.x402: no pay rail configured. Pass \\`x402\\` to createShardDO().");',["fetch"],{cast:" as unknown as X402Pay",sync:["fetch"]})}:{build:"",configField:"",imports:[],stub:""},Fr=(e,t,n,r,o)=>["AdvisorProcedure","AdvisoryFinding","DatabaseWriterLike","DataMigrationLike","ExportRow",...r?["FlagsResult"]:[],"ImportShardResult","KeyRange","MaskPoliciesResult","MigrationRunResult",...n?["QueuesResult"]:[],"RunShardApplyCdcArgs","RunShardExportArgs","RunShardImportArgs","RunShardMigrationArgs","RlsPoliciesResult","RunShardRankBeforeArgs","RunShardRankPageArgs","RunShardWriteArgs","RunShardWriteResult","SchedulerLike",...o?["SearchBackfillProgress"]:[],"TransactionHeadroomTracker","SchemaLike","ShardDOState","ShardRankPageResult","SqlExec","StorageRulesResult","StudioFeaturesResult","SystemReaderStorageLike","TelemetrySink",...t?["WorkflowsResult"]:[],...e?["WriteHook"]:[]],co=({advisories:e=[],advisorProcedures:t=[],agents:n=[],containers:r=[],env:o,flagKeys:s=[],hasAccessFacade:i=!1,hasAi:a=!1,hasAnalytics:c=!1,hasBrowser:d=!1,hasFlags:p=!1,hasHyperdrive:m=!1,hasImages:y=!1,hasKv:u=!1,hasNotify:l=!1,hasPayments:f=!1,hasPipelines:k=!1,hasR2sql:R=!1,hasX402:x=!1,maskMetadata:I,mutators:T=[],queues:_=[],rlsMetadata:v,schema:w,schemaSnapshot:F,shapes:se=[],storageRules:M,studioFeatures:ie,useUmbrella:le=!1,workflows:W=[]})=>{const C=oe(le),ee=T.length>0,L=se.length>0,S=F===void 0?"":kn(F),B=F===void 0?"":`
1177
+ x402?: (env: Record<string, unknown>) => X402PayConfig;`,stub:O("x402Stub: X402Pay",'throw new Error("ctx.x402: no pay rail configured. Pass \\`x402\\` to createShardDO().");',["fetch"],{cast:" as unknown as X402Pay",sync:["fetch"]})}:{build:"",configField:"",imports:[],stub:""},Fr=(e,t,n,r,o)=>["AdvisorProcedure","AdvisoryFinding","DatabaseWriterLike","DataMigrationLike","ExportRow",...r?["FlagsResult"]:[],"ImportShardResult","KeyRange","MaskPoliciesResult","MigrationRunResult","QueryReadScope",...n?["QueuesResult"]:[],"RunShardApplyCdcArgs","RunShardExportArgs","RunShardImportArgs","RunShardMigrationArgs","RlsPoliciesResult","RunShardRankBeforeArgs","RunShardRankPageArgs","RunShardWriteArgs","RunShardWriteResult","SchedulerLike",...o?["SearchBackfillProgress"]:[],"TransactionHeadroomTracker","SchemaLike","ShardDOState","ShardRankPageResult","SqlExec","StorageRulesResult","StudioFeaturesResult","SystemReaderStorageLike","TelemetrySink",...t?["WorkflowsResult"]:[],...e?["WriteHook"]:[]],co=({advisories:e=[],advisorProcedures:t=[],agents:n=[],containers:r=[],env:o,flagKeys:s=[],hasAccessFacade:i=!1,hasAi:a=!1,hasAnalytics:c=!1,hasBrowser:d=!1,hasFlags:p=!1,hasHyperdrive:m=!1,hasImages:y=!1,hasKv:u=!1,hasNotify:l=!1,hasPayments:f=!1,hasPipelines:k=!1,hasR2sql:R=!1,hasX402:x=!1,maskMetadata:I,mutators:N=[],queues:_=[],rlsMetadata:v,schema:w,schemaSnapshot:F,shapes:se=[],storageRules:M,studioFeatures:ie,useUmbrella:le=!1,workflows:W=[]})=>{const C=oe(le),Z=N.length>0,L=se.length>0,S=F===void 0?"":kn(F),B=F===void 0?"":`
1178
1178
  /** 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. */
1179
1179
  const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(xn(F))}, json: ${JSON.stringify(S)} };
1180
- `,ce=F===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",{build:de,configField:Ae,contextField:Oe,stub:Ie}=fr(a),ue=xr(i),V=br(u),P=yr(p,C.flags),H=vr(s,p,C.flags),te=wr(l),pe=kr(o),G=Rr(c),U=Sr(y),K=$r(m),Q=Nr(d),j=Tr(R),ne=Ar(k),{build:Ce,contextField:ve,importLines:Re,specs:he}=Cr(_),{build:Le,contextField:_e,importLines:Se,specs:me}=Or(r,w.jurisdiction),{build:Ee,contextField:De,importLines:$e,specs:Pe}=Ir(W),{build:Fe,contextField:ge,importLines:fe,specs:Me}=Lr(n),{build:Be,configField:je,contextField:be,imports:ye,stub:Xe}=Dr(f),{build:h,configField:qe,imports:Ne,stub:re}=Pr(x),Nt=e,Tt=t,At=v??{policies:[],roles:[]},Ot=I??{columns:[]},It=M??{rules:[]},Ct=ie??{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:Lt,override:_t}=_r(W),{constant:Et,override:Dt}=Er(_),J=w.vectorIndexes.length>0,Ze=new Set(w.tables.filter(b=>typeof b.shardMode=="object"&&b.shardMode.kind==="shardBy").map(b=>b.name)),Te=w.vectorIndexes.some(b=>Ze.has(b.table)),we=w.tables.some(b=>b.shardMode==="global"),We=w.tables.some(b=>b.shardMode==="global"&&b.globalBackend==="hyperdrive"),et=w.tables.some(b=>b.shardMode==="global"&&b.globalBackend!=="hyperdrive"),z=w.tables.some(b=>b.externalSource!==void 0),tt=w.tables.some(b=>b.memory===!0),Ue=w.tables.some(b=>b.shardMode!=="global"&&b.searchIndexes.length>0);if(et&&We)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 Ke=w.tables.length>0,Pt=lr(w),Ft=dr(w),Mt=mr(w),Bt=cr(w),nt=ur(w),rt=Fr(J,W.length>0,_.length>0,p,Ue);L&&rt.push("WhereInput");const ot=gr(we),jt=L?`
1180
+ `,ce=F===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",{build:de,configField:Ae,contextField:Oe,stub:Ie}=fr(a),ue=xr(i),V=br(u),P=yr(p,C.flags),H=vr(s,p,C.flags),ee=wr(l),pe=kr(o),G=Rr(c),U=Sr(y),K=$r(m),Q=Tr(d),q=Nr(R),te=Ar(k),{build:Ce,contextField:ve,importLines:Re,specs:he}=Cr(_),{build:Le,contextField:_e,importLines:Se,specs:me}=Or(r,w.jurisdiction),{build:Ee,contextField:De,importLines:$e,specs:Pe}=Ir(W),{build:Fe,contextField:ge,importLines:fe,specs:Me}=Lr(n),{build:Be,configField:qe,contextField:be,imports:ye,stub:Xe}=Dr(f),{build:h,configField:je,imports:Te,stub:ne}=Pr(x),$t=e,Tt=t,Nt=v??{policies:[],roles:[]},At=I??{columns:[]},Ot=M??{rules:[]},It=ie??{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:Ct,override:Lt}=_r(W),{constant:_t,override:Et}=Er(_),J=w.vectorIndexes.length>0,Ze=new Set(w.tables.filter(b=>typeof b.shardMode=="object"&&b.shardMode.kind==="shardBy").map(b=>b.name)),Ne=w.vectorIndexes.some(b=>Ze.has(b.table)),we=w.tables.some(b=>b.shardMode==="global"),We=w.tables.some(b=>b.shardMode==="global"&&b.globalBackend==="hyperdrive"),et=w.tables.some(b=>b.shardMode==="global"&&b.globalBackend!=="hyperdrive"),re=w.tables.some(b=>b.externalSource!==void 0),tt=w.tables.some(b=>b.memory===!0),Ue=w.tables.some(b=>b.shardMode!=="global"&&b.searchIndexes.length>0);if(et&&We)throw new X("INTERNAL",'lunora codegen: mixing `.global()` (D1) and `.global({ backend: "hyperdrive" })` tables in one app is not supported yet — use a single global backend.');const Ke=w.tables.length>0,Dt=lr(w),Pt=dr(w),Ft=mr(w),Mt=cr(w),nt=ur(w),rt=Fr(J,W.length>0,_.length>0,p,Ue);L&&rt.push("WhereInput");const ot=gr(we),Bt=L?`
1181
1181
  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 {
1182
1182
  const shape = LUNORA_SHAPES[name];
1183
1183
 
@@ -1230,25 +1230,25 @@ const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.st
1230
1230
 
1231
1231
  return { columns: shape.columns, effectiveWhere, global: isGlobal, table: shape.table };
1232
1232
  }
1233
- `:"",qt=ee?`
1233
+ `:"",qt=Z?`
1234
1234
  protected override isCustomMutator(functionPath: string): boolean {
1235
1235
  return LUNORA_MUTATOR_PATHS.has(functionPath);
1236
1236
  }
1237
- `:"",Wt=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":"",Ut=L?"assertShapeShardable, ":"",ke=[`import type { ${rt.join(", ")} } from "${C.do}";`,`import { applyCdcChanges, ${Ue?"backfillSearchIndexes, ":""}buildReprojectionMigration, ${tt?"clearMemoryTables, ":""}${Ut}createReadFootprint, createShardCtxDb, exportShardRows, importShardRows, ${z?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}markUnvouchableReads, ${Te?"ROOT_SHARD_NAME, ":""}runDataMigration, runShardMigrations, ${ot.importFragment}ShardDO as ShardDOBase } from "${C.do}";`,...z?[`import type { ExternalSourceLike, SourceClientLike, TraceRefLike } from "${C.do}";`]:[],L?`import { asBucketStorage, buildRlsReadRegistry, composeShapeReadWhere, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes } from "${C.server}";`:`import { asBucketStorage, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes } from "${C.server}";`];Ke&&ke.push(`import { bindOrm, bindTableFacade } from "${C.server}";`),J&&ke.push('import type { SchemaLike as VectorSchemaLike, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";','import { createContextVectors, createVectors, createVectorSyncHook } from "@lunora/bindings/vectors";'),a&&ke.push('import type { AiBindingLike, LunoraAi } from "@lunora/ai";','import { createAi } from "@lunora/ai";'),ke.push(...ue.importLines,...V.importLines,...P.importLines,...te.importLines,...pe.importLines,...G.importLines,...U.importLines,...K.importLines,...Q.importLines,...j.importLines,...ne.importLines,...Se,...$e,...Re,...fe,...ye,...Ne,"",'import schema from "../schema.js";',`import { ${["LUNORA_FUNCTIONS","LUNORA_LIFECYCLE_HOOKS","LUNORA_MIGRATIONS",...ee?["LUNORA_MUTATOR_PATHS"]:[],...L?["LUNORA_SHAPES"]:[]].join(", ")} } from "./functions.js";`);const Kt=J?`
1238
- vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",Qt=et?`
1239
- d1?: (env: Record<string, unknown>, request?: { bookmark?: string; cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; onBookmark?: (bookmark: string | undefined) => void; userId?: string }) => DatabaseWriterLike | undefined;`:"",Vt=We?`
1240
- hyperdriveGlobal?: (env: Record<string, unknown>, request?: { cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",Ht=z?`
1241
- sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",Gt='throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");',Jt='throw new Error("ctx.vectors: no vectors configured. Pass `vectors` to createShardDO().");',zt='throw new Error("ctx.scheduler: no scheduler configured. Pass `scheduler` to createShardDO().");',Yt='throw new Error("ctx.storage: no storage configured. Pass `storage` to createShardDO().");',Xt=we?O("globalDbStub: DatabaseWriterLike",Gt,["aggregate","count","delete","findFirst","findFirstOrThrow","findMany","get","groupBy","insert","normalizeId","patch","query","rank","rankPage","replace"],{sync:["normalizeId","query"]}):"",Zt=J?O("vectorsStub: VectorSearchLike",Jt,["deleteByIds","getByIds","query","upsert","upsertNow"]):"",en=Te?`
1237
+ `:"",jt=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":"",Wt=L?"assertShapeShardable, ":"",ke=[`import type { ${rt.join(", ")} } from "${C.do}";`,`import { applyCdcChanges, ${Ue?"backfillSearchIndexes, ":""}buildReprojectionMigration, ${tt?"clearMemoryTables, ":""}${Wt}createReadFootprint, createShardCtxDb, exportShardRows, importShardRows, ${re?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}markUnvouchableReads, ${Ne?"ROOT_SHARD_NAME, ":""}runDataMigration, runShardMigrations, ${ot.importFragment}ShardDO as ShardDOBase } from "${C.do}";`,...re?[`import type { ExternalSourceLike, SourceClientLike, TraceRefLike } from "${C.do}";`]:[],L?`import { asBucketStorage, buildRlsReadRegistry, composeShapeReadWhere, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes } from "${C.server}";`:`import { asBucketStorage, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes } from "${C.server}";`];Ke&&ke.push(`import { bindOrm, bindTableFacade } from "${C.server}";`),J&&ke.push('import type { SchemaLike as VectorSchemaLike, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";','import { createContextVectors, createVectors, createVectorSyncHook } from "@lunora/bindings/vectors";'),a&&ke.push('import type { AiBindingLike, LunoraAi } from "@lunora/ai";','import { createAi } from "@lunora/ai";'),ke.push(...ue.importLines,...V.importLines,...P.importLines,...ee.importLines,...pe.importLines,...G.importLines,...U.importLines,...K.importLines,...Q.importLines,...q.importLines,...te.importLines,...Se,...$e,...Re,...fe,...ye,...Te,"",'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 Ut=J?`
1238
+ vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",Kt=et?`
1239
+ d1?: (env: Record<string, unknown>, request?: { bookmark?: string; cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; onBookmark?: (bookmark: string | undefined) => void; userId?: string }) => DatabaseWriterLike | undefined;`:"",Qt=We?`
1240
+ hyperdriveGlobal?: (env: Record<string, unknown>, request?: { cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",Vt=re?`
1241
+ sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",Ht='throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");',Gt='throw new Error("ctx.vectors: no vectors configured. Pass `vectors` to createShardDO().");',Jt='throw new Error("ctx.scheduler: no scheduler configured. Pass `scheduler` to createShardDO().");',zt='throw new Error("ctx.storage: no storage configured. Pass `storage` to createShardDO().");',Yt=we?O("globalDbStub: DatabaseWriterLike",Ht,["aggregate","count","delete","findFirst","findFirstOrThrow","findMany","get","groupBy","insert","normalizeId","patch","query","rank","rankPage","replace"],{sync:["normalizeId","query"]}):"",Xt=J?O("vectorsStub: VectorSearchLike",Gt,["deleteByIds","getByIds","query","upsert","upsertNow"]):"",Zt=Ne?`
1242
1242
  const vectorShardKey = this.currentShardKey();
1243
- `:"",tn=Te?"namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, ":"",nn=Te?`, { namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, shardedIndexNames: [${w.vectorIndexes.filter(b=>Ze.has(b.table)).map(b=>JSON.stringify(b.name)).join(", ")}] }`:"",rn=J?`
1243
+ `:"",en=Ne?"namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, ":"",tn=Ne?`, { namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, shardedIndexNames: [${w.vectorIndexes.filter(b=>Ze.has(b.table)).map(b=>JSON.stringify(b.name)).join(", ")}] }`:"",nn=J?`
1244
1244
  let vectors: VectorSearchLike;
1245
1245
  let onWrite: WriteHook | undefined;
1246
1246
 
1247
1247
  if (config.vectors) {
1248
1248
  const lunora = createVectors({ indexes: config.vectors(env) });
1249
- ${en}
1250
- vectors = createContextVectors(lunora${nn});
1251
- onWrite = createVectorSyncHook({ ${tn}schema: schema as unknown as VectorSchemaLike, vectors });
1249
+ ${Zt}
1250
+ vectors = createContextVectors(lunora${tn});
1251
+ onWrite = createVectorSyncHook({ ${en}schema: schema as unknown as VectorSchemaLike, vectors });
1252
1252
  } else {
1253
1253
  vectors = vectorsStub;
1254
1254
  onWrite = undefined;
@@ -1260,7 +1260,8 @@ ${en}
1260
1260
  // \`__cdc_log\`. Wrapped AFTER \`onWrite\` is built so the write-through
1261
1261
  // vector-sync hook keeps calling the bare facade.
1262
1262
  vectors = markUnvouchableReads(vectors, options.onRead, ["getByIds", "query"]);
1263
- `:"",on=`{
1263
+ `:"",rn=`{
1264
+ ...this.ctxDbTuning(),
1264
1265
  auth: { identity: identity ?? null, userId: userId ?? null },
1265
1266
  broadcast: (delta) => {
1266
1267
  this.recordChangedTable(delta.table, delta.indexKeys);
@@ -1281,17 +1282,30 @@ ${en}
1281
1282
  // each of its writes allocates its own.
1282
1283
  inTransaction: () => this.isInTransaction(),
1283
1284
  onIndexUse: this.getCtxDbIndexUseHook(),
1284
- onRead: options.onRead ?? this.getCtxDbReadHook(),
1285
- onReadRange: options.onReadRange,${J?`
1285
+ // Bound to THIS dispatch's reactive-cache read scope (\`handleRpc\`
1286
+ // threads it in), so two concurrent queries never stamp each
1287
+ // other's dep sets. \`executeSubscription\` overrides both with its
1288
+ // own \`ReadFootprint\` pair instead, and a dispatch with neither
1289
+ // gets an unbound hook that stamps no deps.
1290
+ onRead: options.onRead ?? this.getCtxDbReadHook(options.scope),
1291
+ // Left \`undefined\` when there is no scope so \`createShardCtxDb\`
1292
+ // keeps its own "degrade a provable slice to a whole-table dep"
1293
+ // fallback rather than reporting into a no-op.
1294
+ onReadRange: options.onReadRange ?? (options.scope === undefined ? undefined : this.getCtxDbReadRangeHook(options.scope)),${J?`
1286
1295
  onWrite,`:""}
1287
1296
  scheduler,
1288
1297
  schema: schema as unknown as SchemaLike,
1289
1298
  sql: this.sql as SqlExec,
1290
1299
  storage,${we?`
1291
1300
  globalDb,`:""}
1292
- }`,Y=` const env = (this.env ?? {}) as Record<string, unknown>;
1301
+ }`,z=` const env = (this.env ?? {}) as Record<string, unknown>;
1293
1302
  const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
1294
1303
  const writer = createShardCtxDb({
1304
+ // Admin and maintenance writes go through the SAME reactive-cache hooks as
1305
+ // a user mutation. Without this, a studio row edit, a TTL sweep, an admin
1306
+ // import, a CDC apply or a data-migration backfill writes without
1307
+ // invalidating, and the next query answers from the pre-write snapshot.
1308
+ ...this.ctxDbTuning(),
1295
1309
  broadcast: (delta) => {
1296
1310
  this.recordChangedTable(delta.table, delta.indexKeys);
1297
1311
  },
@@ -1301,11 +1315,11 @@ ${en}
1301
1315
  scheduler,
1302
1316
  schema: schema as unknown as SchemaLike,
1303
1317
  sql: this.sql as SqlExec,
1304
- });`,an=J?`
1305
- vectors,`:"",sn=Ke?`
1306
- orm: bindOrm(facade),`:"",Qe=We?"config.hyperdriveGlobal":"config.d1",ln=we?` const globalRequest = { ...this.globalCdcOptions(config.cdc ?? false), bookmark: this.getInboundBookmark(), identity, onBookmark: (bookmarkValue: string | undefined) => { this.setOutboundBookmark(bookmarkValue); }, userId };
1318
+ });`,on=J?`
1319
+ vectors,`:"",an=Ke?`
1320
+ orm: bindOrm(facade),`:"",Qe=We?"config.hyperdriveGlobal":"config.d1",sn=we?` const globalRequest = { ...this.globalCdcOptions(config.cdc ?? false), bookmark: this.getInboundBookmark(), identity, onBookmark: (bookmarkValue: string | undefined) => { this.setOutboundBookmark(bookmarkValue); }, userId };
1307
1321
  const globalDb: DatabaseWriterLike = ${Qe}?.(env, globalRequest) ?? globalDbStub;
1308
- `:"",cn=L&&we?`
1322
+ `:"",ln=L&&we?`
1309
1323
  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 }>> {
1310
1324
  const env = this.env as Record<string, unknown>;
1311
1325
  // A shape read performs no writes, so the widened request only needs
@@ -1350,17 +1364,17 @@ ${en}
1350
1364
 
1351
1365
  return globalDb.cdcChangedTables?.(sinceSeq, { cursorOnly });
1352
1366
  }
1353
- `:"",dn=z?`
1367
+ `:"",cn=re?`
1354
1368
  const sourceClientCache = new WeakMap<object, Map<string, SourceClientLike>>();
1355
1369
  const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
1356
- `:"",un=`
1370
+ `:"",dn=`
1357
1371
  protected override async runShardInit(): Promise<void> {
1358
1372
  this.ensureMigrated();
1359
1373
  ${tt?` clearMemoryTables(this.sql as SqlExec, schema as unknown as SchemaLike);
1360
1374
  `:""}
1361
1375
  await this.dispatchShardInit();
1362
1376
  }
1363
- `,pn=z?`
1377
+ `,un=re?`
1364
1378
  protected override async pollExternalSources(trace?: TraceRefLike): Promise<number | undefined> {
1365
1379
  const env = (this.env ?? {}) as Record<string, unknown>;
1366
1380
  const sourced = Object.entries((schema as unknown as SchemaLike).tables)
@@ -1425,6 +1439,11 @@ ${tt?` clearMemoryTables(this.sql as SqlExec, schema as unknown as Sc
1425
1439
  // sibling table needs, and a limit hit here must not block
1426
1440
  // that sibling from getting its own full budget this tick.
1427
1441
  const writer = createShardCtxDb({
1442
+ // Admin and maintenance writes go through the SAME reactive-cache hooks as
1443
+ // a user mutation. Without this, a studio row edit, a TTL sweep, an admin
1444
+ // import, a CDC apply or a data-migration backfill writes without
1445
+ // invalidating, and the next query answers from the pre-write snapshot.
1446
+ ...this.ctxDbTuning(),
1428
1447
  broadcast: (delta) => {
1429
1448
  this.recordChangedTable(delta.table, delta.indexKeys);
1430
1449
  },
@@ -1495,10 +1514,20 @@ ${tt?` clearMemoryTables(this.sql as SqlExec, schema as unknown as Sc
1495
1514
 
1496
1515
  return nextDueAt;
1497
1516
  }
1498
- `:"",at=nt.length>0,hn=z||at?`
1517
+ `:"",pn=nt.length>0,hn=`
1499
1518
  public constructor(state: ShardDOState, env: unknown) {
1500
- super(state, env);
1501
- ${z?`
1519
+ super(state, env, {
1520
+ // Every writer this file builds spreads the ctxDbTuning() slice —
1521
+ // the user-facing ctx and all three admin/maintenance writers — so
1522
+ // the base class can drop its coarse invalidation backstop. Only the
1523
+ // emitter can know that; a hand-written subclass leaves this unset
1524
+ // and keeps the backstop.
1525
+ ctxDbCacheWired: true,
1526
+ ...(config.maxRelationKeys === undefined ? {} : { maxRelationKeys: config.maxRelationKeys }),
1527
+ ...(config.reactiveCache ? { reactiveCache: config.reactiveCache === true ? {} : config.reactiveCache } : {}),
1528
+ ...(config.relationExistsPushDown === undefined ? {} : { relationExistsPushDown: config.relationExistsPushDown }),
1529
+ });
1530
+ ${re?`
1502
1531
  const autoSourced = Object.values((schema as unknown as SchemaLike).tables).some((definition) => {
1503
1532
  const source = (definition as { externalSource?: ExternalSourceLike }).externalSource;
1504
1533
 
@@ -1508,26 +1537,30 @@ ${z?`
1508
1537
  if (autoSourced) {
1509
1538
  void this.scheduleSourcePoll();
1510
1539
  }
1511
- `:""}${at?`
1540
+ `:""}${pn?`
1512
1541
  if (LUNORA_TTL_SWEEPS.length > 0) {
1513
1542
  void this.scheduleTtlSweep();
1514
1543
  }
1515
1544
  `:""} }
1516
- `:"",mn=Ke?`
1545
+
1546
+ protected override isQueryFunction(functionPath: string): boolean {
1547
+ return LUNORA_FUNCTIONS[functionPath]?.kind === "query";
1548
+ }
1549
+ `,mn=Ke?`
1517
1550
  const facade = db as unknown as Record<string, ReturnType<typeof bindTableFacade>>;
1518
1551
  ${w.tables.map(b=>` facade[${JSON.stringify(b.name)}] = bindTableFacade(db, ${JSON.stringify(b.name)});`).join(`
1519
1552
  `)}
1520
1553
  `:"",gn=`${ue.build}${V.build}${P.build}${G.build}${pe.build}
1521
1554
  const secrets = createSecrets(env);
1522
- `,fn=`${ue.contextField}${V.contextField}${P.contextField}${te.contextField}${G.contextField}${pe.contextField}
1523
- secrets,`,bn=te.build,st=y||m||d||R||k||x,yn=st?`
1555
+ `,fn=`${ue.contextField}${V.contextField}${P.contextField}${ee.contextField}${G.contextField}${pe.contextField}
1556
+ secrets,`,bn=ee.build,at=y||m||d||R||k||x,yn=at?`
1524
1557
  // ActionCtx-only helpers (external, non-deterministic I/O): constructed
1525
1558
  // and attached only for an \`action\` so query/mutation ctx never carry them.
1526
1559
  if (isAction) {
1527
- ${U.build}${K.build}${Q.build}${j.build}${ne.build}${h}${[...y?[" ctx.images = images;"]:[],...m?[" ctx.sql = sql;"]:[],...d?[" ctx.browser = browser;"]:[],...R?[" ctx.r2sql = r2sql;"]:[],...k?[" ctx.pipelines = pipelines;"]:[],...x?[" ctx.x402 = x402;"]:[]].join(`
1560
+ ${U.build}${K.build}${Q.build}${q.build}${te.build}${h}${[...y?[" ctx.images = images;"]:[],...m?[" ctx.sql = sql;"]:[],...d?[" ctx.browser = browser;"]:[],...R?[" ctx.r2sql = r2sql;"]:[],...k?[" ctx.pipelines = pipelines;"]:[],...x?[" ctx.x402 = x402;"]:[]].join(`
1528
1561
  `)}
1529
1562
  }
1530
- `:"",wn=st?` const isAction = LUNORA_FUNCTIONS[options.functionPath ?? ""]?.kind === "action";
1563
+ `:"",wn=at?` const isAction = LUNORA_FUNCTIONS[options.functionPath ?? ""]?.kind === "action";
1531
1564
  `:"";return`${$}${ke.join(`
1532
1565
  `)}
1533
1566
 
@@ -1538,50 +1571,56 @@ interface FunctionReference {
1538
1571
  }
1539
1572
 
1540
1573
  /** Foreign-key columns per table (\`v.id("target")\` fields) for the data browser. */
1541
- const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(Pt,void 0,4)};
1574
+ const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(Dt,void 0,4)};
1542
1575
 
1543
1576
  /** Declared indexes per table (secondary, search, geo, rank, vector) for the schema viewer. */
1544
- const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(Ft,void 0,4)};
1577
+ const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(Pt,void 0,4)};
1545
1578
 
1546
1579
  /** Columns per table (typed, with PK/FK markers) for the studio's schema diagram, served via \`__lunora_admin__:describeTable\`. */
1547
1580
  const LUNORA_TABLE_COLUMNS: Record<
1548
1581
  string,
1549
1582
  Array<{ bucket?: string; enumValues?: string[]; isStorage?: boolean; name: string; nullable?: boolean; optional: boolean; pk?: boolean; ref?: string; type: string }>
1550
- > = ${JSON.stringify(Mt,void 0,4)};
1583
+ > = ${JSON.stringify(Ft,void 0,4)};
1551
1584
 
1552
1585
  /** Storage-key columns per table (\`v.storage(...)\` fields) for the file browser's records↔files join. */
1553
- const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify(Bt,void 0,4)};
1586
+ const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify(Mt,void 0,4)};
1554
1587
 
1555
1588
  /** Declarative TTL policies (\`.ttl(field, { after? })\`) the DO alarm sweep auto-expires rows for. */
1556
1589
  const LUNORA_TTL_SWEEPS: Array<{ after?: number; field: string; softDeleteField?: string; table: string }> = ${JSON.stringify(nt,void 0,4)};
1557
1590
 
1558
1591
  /** Static schema advisories (computed by @lunora/advisor at codegen time) served via \`__lunora_admin__:getAdvisories\`. */
1559
- const LUNORA_ADVISORIES: AdvisoryFinding[] = ${JSON.stringify(Nt,void 0,4)};
1592
+ const LUNORA_ADVISORIES: AdvisoryFinding[] = ${JSON.stringify($t,void 0,4)};
1560
1593
 
1561
1594
  /** Every declared procedure (discovered by @lunora/codegen) served via \`__lunora_admin__:getAdvisorProcedures\` — the health map's denominator. */
1562
1595
  const LUNORA_ADVISOR_PROCEDURES: AdvisorProcedure[] = ${JSON.stringify(Tt,void 0,4)};
1563
1596
 
1564
1597
  /** Read-only RLS metadata (policies + roles discovered from \`.use(rls(...))\` chains) served via \`__lunora_admin__:rlsPolicies\` for the studio's RLS inspector. */
1565
- const LUNORA_RLS_METADATA: RlsPoliciesResult = ${JSON.stringify(At,void 0,4)};
1598
+ const LUNORA_RLS_METADATA: RlsPoliciesResult = ${JSON.stringify(Nt,void 0,4)};
1566
1599
 
1567
1600
  /** 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. */
1568
- const LUNORA_MASK_METADATA: MaskPoliciesResult = ${JSON.stringify(Ot,void 0,4)};
1601
+ const LUNORA_MASK_METADATA: MaskPoliciesResult = ${JSON.stringify(At,void 0,4)};
1569
1602
 
1570
1603
  /** Read-only storage access-rule metadata (discovered from \`.use(storageRules(...))\` chains) served via \`__lunora_admin__:storageRules\` for the studio's access-rules view. */
1571
- const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(It,void 0,4)};
1604
+ const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(Ot,void 0,4)};
1572
1605
 
1573
1606
  /** 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. */
1574
- const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(Ct,void 0,4)};
1575
- ${B}${H.constant}${Wt}${Lt}${Et}${me}${Pe}${he}${Me}
1607
+ const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(It,void 0,4)};
1608
+ ${B}${H.constant}${jt}${Ct}${_t}${me}${Pe}${he}${Me}
1576
1609
  export interface ShardDOConfig {
1577
1610
  /** Opt into change-data-capture: records a post-image to \`__cdc_log\` on every write (backs streaming export + replay-PITR). */
1578
1611
  cdc?: boolean;
1612
+ /** Ceiling on the join keys one relation-crossing \`where\` predicate may pre-resolve via semijoin before failing closed. Omit for the engine default. */
1613
+ maxRelationKeys?: number;
1614
+ /** Enable the per-shard reactive query cache: \`true\` for the defaults, or an options object to tune the caps. Query results are memoized by \`(functionPath, args, identity)\` and invalidated by the ctx-db write hooks before the subscription broadcast, so subscribers never observe a pre-write value. Omitted (or \`false\`) keeps every dispatch re-running its handler. */
1615
+ reactiveCache?: boolean | { maxBytes?: number; maxEntries?: number };
1616
+ /** Resolution policy for a relation-crossing \`where\` whose child is co-located in this shard: \`"auto"\` (cost-based, the engine default), \`"always"\` (inline correlated EXISTS) or \`"never"\` (universal semijoin). All three return identical rows. */
1617
+ relationExistsPushDown?: "always" | "auto" | "never";
1579
1618
  /** 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. */
1580
1619
  observability?: (env: Record<string, unknown>) => TelemetrySink | undefined;
1581
1620
  scheduler?: (env: Record<string, unknown>) => unknown;
1582
- storage?: (env: Record<string, unknown>) => unknown;${Kt}${Ae}${V.configField}${P.configField}${G.configField}${U.configField}${K.configField}${Q.configField}${j.configField}${ne.configField}${je}${qe}${Qt}${Vt}${Ht}
1621
+ storage?: (env: Record<string, unknown>) => unknown;${Ut}${Ae}${V.configField}${P.configField}${G.configField}${U.configField}${K.configField}${Q.configField}${q.configField}${te.configField}${qe}${je}${Kt}${Qt}${Vt}
1583
1622
  }
1584
- ${O("schedulerStub",zt,["cancel","runAfter","runAt"])}${O("storageStub",Yt,["delete","download","getMetadata","getSignedUrl","getUrl","head","list","upload"],{sync:["getUrl"]})}${Xt}${dn}${Zt}${Ie}${V.stub}${P.stub}${G.stub}${U.stub}${K.stub}${Q.stub}${j.stub}${ne.stub}${Xe}${re}
1623
+ ${O("schedulerStub",Jt,["cancel","runAfter","runAt"])}${O("storageStub",zt,["delete","download","getMetadata","getSignedUrl","getUrl","head","list","upload"],{sync:["getUrl"]})}${Yt}${cn}${Xt}${Ie}${V.stub}${P.stub}${G.stub}${U.stub}${K.stub}${Q.stub}${q.stub}${te.stub}${Xe}${ne}
1585
1624
  // Bound in-process \`ctx.run*\` composition depth so a self- or cyclically-
1586
1625
  // referencing call fails loudly with a clear error instead of overflowing the
1587
1626
  // stack. Tracked across the awaited handler chain (one DO invocation is
@@ -1621,7 +1660,7 @@ export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOSt
1621
1660
  class extends ShardDOBase {${hn}
1622
1661
  private migrated = false;
1623
1662
 
1624
- public override async handleRpc(functionPath: string, args: Record<string, unknown>, headroom?: TransactionHeadroomTracker): Promise<unknown> {
1663
+ public override async handleRpc(functionPath: string, args: Record<string, unknown>, headroom?: TransactionHeadroomTracker, scope?: QueryReadScope): Promise<unknown> {
1625
1664
  const registered = LUNORA_FUNCTIONS[functionPath];
1626
1665
 
1627
1666
  // Internal functions are reachable server-side only: via \`ctx.run*\`
@@ -1640,7 +1679,15 @@ export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOSt
1640
1679
  // The main \`/rpc\` path always supplies one; \`dispatchLifecycle\` /
1641
1680
  // \`handleRunAs\` don't mint their own and omit it, so they keep the
1642
1681
  // prior fallback behavior unchanged.
1643
- const ctx = this.buildCtx({ functionPath, headroom, trusted: registered.lifecycle === "init" });
1682
+ //
1683
+ // \`scope\` is the reactive cache's per-dispatch read capture, threaded
1684
+ // the same way and for the same reason: the ctx-db read hooks resolve
1685
+ // their tracker at READ time, so binding them to the scope THIS
1686
+ // dispatch was handed is what keeps a concurrent query's reads out of
1687
+ // our dep set — and ours out of theirs. A dispatch with no scope (a
1688
+ // mutation, an action, a cache-less shard) builds unbound hooks that
1689
+ // stamp no deps.
1690
+ const ctx = this.buildCtx({ functionPath, headroom, scope, trusted: registered.lifecycle === "init" });
1644
1691
 
1645
1692
  // A mutation's writes must commit all-or-nothing: wrap its dispatch in
1646
1693
  // the DO's BEGIN/COMMIT span so any throw (a validator, an RLS denial,
@@ -1734,11 +1781,11 @@ ${ot.override}
1734
1781
  iterator: (signal) => (registered.handler as (context: unknown, args: Record<string, unknown>, signal: AbortSignal) => AsyncIterable<unknown>)(this.buildCtx({ functionPath }), args, signal),
1735
1782
  };
1736
1783
  }
1737
- ${qt}${jt}${cn}${pn}
1784
+ ${qt}${Bt}${ln}${un}
1738
1785
  protected override lifecycleHookPaths(event: "connect" | "disconnect" | "init" | "reactor"): readonly string[] {
1739
1786
  return LUNORA_LIFECYCLE_HOOKS[event];
1740
1787
  }
1741
- ${un}
1788
+ ${dn}
1742
1789
  // One \`onQueryChange\` dispatch. Mirrors \`executeSubscription\` — the
1743
1790
  // socket-terminated half of the same reactivity — and differs only in who
1744
1791
  // consumes the result: the base's \`dispatchReactors\` stores the digest as
@@ -1820,7 +1867,7 @@ ${un}
1820
1867
  protected override studioFeatures(): StudioFeaturesResult {
1821
1868
  return LUNORA_STUDIO_FEATURES;
1822
1869
  }
1823
- ${H.evaluateOverride}${H.subscriptionOverride}${_t}${Dt}
1870
+ ${H.evaluateOverride}${H.subscriptionOverride}${Lt}${Et}
1824
1871
  protected override advisories(): AdvisoryFinding[] {
1825
1872
  return LUNORA_ADVISORIES;
1826
1873
  }
@@ -1844,7 +1891,7 @@ ${H.evaluateOverride}${H.subscriptionOverride}${_t}${Dt}
1844
1891
  throw new LunoraError("MIGRATION_NOT_FOUND", \`data migration "\${args.id}" is not registered\`, { status: 404 });
1845
1892
  }
1846
1893
 
1847
- ${Y}
1894
+ ${z}
1848
1895
 
1849
1896
  return runDataMigration({
1850
1897
  batchSize: args.batchSize,
@@ -1877,7 +1924,7 @@ ${Y}
1877
1924
 
1878
1925
  this.ensureMigrated();
1879
1926
 
1880
- ${Y}
1927
+ ${z}
1881
1928
 
1882
1929
  if (args.op === "insert") {
1883
1930
  const id = await writer.insert(args.table, args.doc ?? {});
@@ -1921,7 +1968,7 @@ ${Y}
1921
1968
  protected override async runShardExport(args: RunShardExportArgs): Promise<ExportRow[]> {
1922
1969
  this.ensureMigrated();
1923
1970
 
1924
- ${Y}
1971
+ ${z}
1925
1972
 
1926
1973
  const rows: ExportRow[] = [];
1927
1974
 
@@ -1938,7 +1985,7 @@ ${Y}
1938
1985
  protected override async runShardImport(args: RunShardImportArgs): Promise<ImportShardResult> {
1939
1986
  this.ensureMigrated();
1940
1987
 
1941
- ${Y}
1988
+ ${z}
1942
1989
 
1943
1990
  // \`importShardRows\` inserts with \`allowExplicitId\`, so a source
1944
1991
  // database's \`_id\`s carry across verbatim and every foreign key
@@ -1964,6 +2011,11 @@ ${Y}
1964
2011
  const env = (this.env ?? {}) as Record<string, unknown>;
1965
2012
  const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
1966
2013
  const writer = createShardCtxDb({
2014
+ // Admin and maintenance writes go through the SAME reactive-cache hooks as
2015
+ // a user mutation. Without this, a studio row edit, a TTL sweep, an admin
2016
+ // import, a CDC apply or a data-migration backfill writes without
2017
+ // invalidating, and the next query answers from the pre-write snapshot.
2018
+ ...this.ctxDbTuning(),
1967
2019
  broadcast: (delta) => {
1968
2020
  this.recordChangedTable(delta.table, delta.indexKeys);
1969
2021
  },
@@ -1989,7 +2041,7 @@ ${Y}
1989
2041
  protected override async runShardRankBefore(args: RunShardRankBeforeArgs): Promise<{ before: number; total: number }> {
1990
2042
  this.ensureMigrated();
1991
2043
 
1992
- ${Y}
2044
+ ${z}
1993
2045
 
1994
2046
  // \`rankBefore\` is optional on \`DatabaseWriterLike\` (the D1 twin omits it),
1995
2047
  // but the shard writer from \`createShardCtxDb\` always defines it.
@@ -2007,7 +2059,7 @@ ${Y}
2007
2059
  protected override async runShardRankPage(args: RunShardRankPageArgs): Promise<ShardRankPageResult> {
2008
2060
  this.ensureMigrated();
2009
2061
 
2010
- ${Y}
2062
+ ${z}
2011
2063
 
2012
2064
  // \`rankPageRows\` is optional on \`DatabaseWriterLike\` (the D1 twin omits it),
2013
2065
  // but the shard writer from \`createShardCtxDb\` always defines it. The sort
@@ -2028,7 +2080,7 @@ ${Y}
2028
2080
  protected override async runShardApplyCdc(args: RunShardApplyCdcArgs): Promise<{ applied: number }> {
2029
2081
  this.ensureMigrated();
2030
2082
 
2031
- ${Y}
2083
+ ${z}
2032
2084
 
2033
2085
  await applyCdcChanges(writer, args.changes);
2034
2086
 
@@ -2053,7 +2105,7 @@ ${Ue?`
2053
2105
  return backfillSearchIndexes(this.sql as SqlExec, schema as unknown as SchemaLike, options);
2054
2106
  }
2055
2107
  `:""}
2056
- private buildCtx(options: { functionPath?: string; headroom?: TransactionHeadroomTracker; identity?: { identity?: Record<string, unknown>; userId?: string }; onRead?: (table: string, idOrScan?: string) => void; onReadRange?: (range: KeyRange) => void; trusted?: boolean } = {}): unknown {
2108
+ private buildCtx(options: { functionPath?: string; headroom?: TransactionHeadroomTracker; identity?: { identity?: Record<string, unknown>; userId?: string }; onRead?: (table: string, idOrScan?: string) => void; onReadRange?: (range: KeyRange) => void; scope?: QueryReadScope; trusted?: boolean } = {}): unknown {
2057
2109
  const env = (this.env ?? {}) as Record<string, unknown>;
2058
2110
  // When the caller threads an explicit identity (subscription seed /
2059
2111
  // refresh — both run in deferred/interleaved contexts), use it by
@@ -2062,7 +2114,7 @@ ${Ue?`
2062
2114
  // dispatch path) fall back to the per-request fields as before.
2063
2115
  const userId = options.identity ? options.identity.userId : this.getCurrentUserId();
2064
2116
  const identity = options.identity ? options.identity.identity : this.getCurrentIdentity();
2065
- ${rn}${de}${gn}${Le}${Ee}${Ce}${Fe}
2117
+ ${nn}${de}${gn}${Le}${Ee}${Ce}${Fe}
2066
2118
  // \`list\`/\`get\` are the two methods \`ctx.db.system.query("_scheduled_functions")\`
2067
2119
  // reaches through, and pending jobs live in the SchedulerDO — nothing the
2068
2120
  // CDC changelog records — so reading them must forfeit a delta resume.
@@ -2124,12 +2176,12 @@ ${rn}${de}${gn}${Le}${Ee}${Ce}${Fe}
2124
2176
  // so both write to the same trace.
2125
2177
  const span = this.makeDispatchSpan(traceAnchor, observability);
2126
2178
 
2127
- ${ln} // \`ctx.db\`, wrapped in automatic instrumentation: by default this
2179
+ ${sn} // \`ctx.db\`, wrapped in automatic instrumentation: by default this
2128
2180
  // adds aggregate counters (call count, total time, per-operation
2129
2181
  // breakdown) to the wide event rather than a span per call, so a
2130
2182
  // handler making hundreds of queries stays readable. See
2131
2183
  // \`instrumentDatabase\` for the \`"spans"\` / \`"off"\` levels.
2132
- const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${on}), logFunctionPath, traceAnchor, observability);
2184
+ const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${rn}), logFunctionPath, traceAnchor, observability);
2133
2185
  ${mn}${Be}
2134
2186
 
2135
2187
  // \`ctx.trace\` / \`ctx.metrics\`: spans and measurements to the same sink.
@@ -2161,22 +2213,24 @@ ${bn}
2161
2213
  ip: this.getCurrentIp(),
2162
2214
  log,
2163
2215
  metrics,
2164
- now,${sn}
2216
+ now,${an}
2165
2217
  scheduler,
2166
2218
  span,
2167
2219
  storage: contextStorage,
2168
- trace,${an}${Oe}${fn}${be}${_e}${De}${ve}${ge}
2220
+ trace,${on}${Oe}${fn}${be}${_e}${De}${ve}${ge}
2169
2221
  };
2170
2222
  ${wn}${yn}
2171
2223
  ctx.runAction = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("action", reference.__lunoraRef, fnArgs, ctx);
2172
2224
  ctx.runMutation = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("mutation", reference.__lunoraRef, fnArgs, ctx);
2173
2225
  // \`ctx.runQuery(ref, args, { untracked: true })\` runs the sub-query on
2174
- // its OWN context, built without the read-footprint hooks — so its
2175
- // reads never enter this subscription's footprint and a write to the
2176
- // tables it touched does not re-run us. Everything else is inherited:
2177
- // \`functionPath\` (log/metric attribution), \`headroom\` (the sub-query
2178
- // must not escape this dispatch's resource ceiling), and — load-bearing
2179
- // — the identity BY VALUE. Omitting identity would let \`buildCtx\` fall
2226
+ // its OWN context, built without the subscription's read-footprint
2227
+ // hooks — so its reads never enter this subscription's footprint and a
2228
+ // write to the tables it touched does not re-run us. Everything else is
2229
+ // inherited: \`functionPath\` (log/metric attribution), \`headroom\` (the
2230
+ // sub-query must not escape this dispatch's resource ceiling),
2231
+ // \`scope\` (the reactive-cache capture — an untracked sub-query's reads
2232
+ // must still be deps of the entry the OUTER query is memoized as, or
2233
+ // the memo goes stale), and — load-bearing — the identity BY VALUE. Omitting identity would let \`buildCtx\` fall
2180
2234
  // back to the shared per-request fields, which a concurrent RPC may
2181
2235
  // have re-set, and an RLS-scoped sub-query would then read as the wrong
2182
2236
  // user. A tracked call keeps sharing \`ctx\` exactly as before.
@@ -2186,28 +2240,28 @@ ${wn}${yn}
2186
2240
  reference.__lunoraRef,
2187
2241
  fnArgs,
2188
2242
  runOptions?.untracked === true
2189
- ? this.buildCtx({ functionPath: options.functionPath, headroom: options.headroom, identity: { identity, userId } })
2243
+ ? this.buildCtx({ functionPath: options.functionPath, headroom: options.headroom, identity: { identity, userId }, scope: options.scope })
2190
2244
  : ctx,
2191
2245
  );
2192
2246
 
2193
2247
  return ctx;
2194
2248
  }
2195
2249
  };
2196
- `},Ye=e=>{switch(e.kind){case"array":case"object":case"record":case"union":return{builder:"text",mode:"json",notNull:!0,typeAnnotation:A(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"from":return{builder:"text",notNull:!0,typeAnnotation:A(e)};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?Ye(e.inner):{builder:"text",notNull:!1},notNull:!1};case"storage":case"string":return{builder:"text",notNull:!0};default:return{builder:"text",notNull:!0}}},$t=(e,t)=>{const n=ae(e);return n.kind==="id"&&n.tableName!==void 0&&t.has(n.tableName)?n.tableName:void 0},Mr=(e,t,n)=>{g(e,"drizzle column name");const r=Ye(t),o=r.mode?`, { mode: "${r.mode}" }`:"";let s=`${r.builder}("${e}"${o})`;r.typeAnnotation&&(s+=`.$type<${r.typeAnnotation}>()`);const i=$t(t,n);return i!==void 0&&(s+=`.references((): AnySQLiteColumn => ${i}._id)`),r.notNull&&(s+=".notNull()"),s},Br=e=>{const t=e.unique?"uniqueIndex":"index",n=e.fields.map(r=>(g(r,"drizzle index field"),`t.${r}`)).join(", ");return` ${X(e.name)}: ${t}(${JSON.stringify(e.name)}).on(${n}),`},jr=(e,t)=>{g(e.name,"table name");const n=[' _id: text("_id").primaryKey(),',' _creationTime: integer("_creationTime").notNull(),',...Object.entries(e.shape).map(([o,s])=>` ${o}: ${Mr(o,s,t)},`)].join(`
2250
+ `},Ye=e=>{switch(e.kind){case"array":case"object":case"record":case"union":return{builder:"text",mode:"json",notNull:!0,typeAnnotation:A(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"from":return{builder:"text",notNull:!0,typeAnnotation:A(e)};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?Ye(e.inner):{builder:"text",notNull:!1},notNull:!1};case"storage":case"string":return{builder:"text",notNull:!0};default:return{builder:"text",notNull:!0}}},St=(e,t)=>{const n=ae(e);return n.kind==="id"&&n.tableName!==void 0&&t.has(n.tableName)?n.tableName:void 0},Mr=(e,t,n)=>{g(e,"drizzle column name");const r=Ye(t),o=r.mode?`, { mode: "${r.mode}" }`:"";let s=`${r.builder}("${e}"${o})`;r.typeAnnotation&&(s+=`.$type<${r.typeAnnotation}>()`);const i=St(t,n);return i!==void 0&&(s+=`.references((): AnySQLiteColumn => ${i}._id)`),r.notNull&&(s+=".notNull()"),s},Br=e=>{const t=e.unique?"uniqueIndex":"index",n=e.fields.map(r=>(g(r,"drizzle index field"),`t.${r}`)).join(", ");return` ${Y(e.name)}: ${t}(${JSON.stringify(e.name)}).on(${n}),`},qr=(e,t)=>{g(e.name,"table name");const n=[' _id: text("_id").primaryKey(),',' _creationTime: integer("_creationTime").notNull(),',...Object.entries(e.shape).map(([o,s])=>` ${o}: ${Mr(o,s,t)},`)].join(`
2197
2251
  `),r=e.indexes.length>0?`, (t) => ({
2198
2252
  ${e.indexes.map(o=>Br(o)).join(`
2199
2253
  `)}
2200
2254
  })`:"";return`export const ${e.name} = sqliteTable("${e.name}", {
2201
2255
  ${n}
2202
- }${r});`},qr=e=>e.typeAnnotation?.includes('Id<"')??!1,Wr=(e,t)=>{const n=new Set(["integer","sqliteTable","text"]),r=new Set;let o=!1,s=!1;for(const i of e){for(const a of Object.values(i.shape)){const c=Ye(a);n.add(c.builder),s=s||qr(c),o=o||$t(a,t)!==void 0}for(const a of i.indexes)r.add(a.unique?"uniqueIndex":"index")}return{columns:[...n].toSorted((i,a)=>i.localeCompare(a)),indexes:[...r].toSorted((i,a)=>i.localeCompare(a)),needsAnyColumn:o,needsId:s}},ct=(e,t=!1)=>{if(e.length===0)return`${$}export {};
2203
- `;const n=oe(t),r=new Set(e.map(m=>m.name)),{columns:o,indexes:s,needsAnyColumn:i,needsId:a}=Wr(e,r),c=[...s,...o].toSorted((m,y)=>m.localeCompare(y)),d=e.map(m=>jr(m,r)).join(`
2256
+ }${r});`},jr=e=>e.typeAnnotation?.includes('Id<"')??!1,Wr=(e,t)=>{const n=new Set(["integer","sqliteTable","text"]),r=new Set;let o=!1,s=!1;for(const i of e){for(const a of Object.values(i.shape)){const c=Ye(a);n.add(c.builder),s=s||jr(c),o=o||St(a,t)!==void 0}for(const a of i.indexes)r.add(a.unique?"uniqueIndex":"index")}return{columns:[...n].toSorted((i,a)=>i.localeCompare(a)),indexes:[...r].toSorted((i,a)=>i.localeCompare(a)),needsAnyColumn:o,needsId:s}},lt=(e,t=!1)=>{if(e.length===0)return`${$}export {};
2257
+ `;const n=oe(t),r=new Set(e.map(m=>m.name)),{columns:o,indexes:s,needsAnyColumn:i,needsId:a}=Wr(e,r),c=[...s,...o].toSorted((m,y)=>m.localeCompare(y)),d=e.map(m=>qr(m,r)).join(`
2204
2258
 
2205
2259
  `),p=[i?`import type { AnySQLiteColumn } from "${n.serverDrizzle}";
2206
2260
  `:"",a?`import type { Id } from "./dataModel.js";
2207
2261
  `:""].join("");return`${$}import { ${c.join(", ")} } from "${n.serverDrizzle}";
2208
2262
  ${p}
2209
2263
  ${d}
2210
- `},uo=(e,t=!1)=>{const n=e.tables.filter(o=>o.shardMode==="global"),r=e.tables.filter(o=>o.shardMode!=="global");return{global:E(ct(n,t),Ge),shard:E(ct(r,t),Ge)}},po=e=>{const t=new Map;for(const i of e){const a=t.get(i.cron);a?a.push(i):t.set(i.cron,[i])}const n=[...t.keys()].map(i=>` ${JSON.stringify(i)},`).join(`
2264
+ `},uo=(e,t=!1)=>{const n=e.tables.filter(o=>o.shardMode==="global"),r=e.tables.filter(o=>o.shardMode!=="global");return{global:E(lt(n,t),Ge),shard:E(lt(r,t),Ge)}},po=e=>{const t=new Map;for(const i of e){const a=t.get(i.cron);a?a.push(i):t.set(i.cron,[i])}const n=[...t.keys()].map(i=>` ${JSON.stringify(i)},`).join(`
2211
2265
  `),r=n.length>0?`
2212
2266
  ${n}
2213
2267
  `:"",o=[...t.entries()].map(([i,a])=>{const c=a.map(d=>{const p=d.workflow?`workflow: ${JSON.stringify(d.workflow.binding)}`:`functionPath: ${JSON.stringify(d.functionPath)}`;return` { name: ${JSON.stringify(d.name)}, ${p}, args: ${JSON.stringify(d.args)} },`}).join(`