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

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 (39) hide show
  1. package/dist/index.d.mts +15 -6
  2. package/dist/index.d.ts +15 -6
  3. package/dist/index.mjs +1 -1
  4. package/dist/packem_shared/DEFAULT_TARGET-B0FkdiZq.mjs +1 -0
  5. package/dist/packem_shared/{MUTATORS_FILENAME--5kUJd5I.mjs → MUTATORS_FILENAME-Jkk8Zgkb.mjs} +1 -1
  6. package/dist/packem_shared/{NOTIFY_FILENAME-BOZ8G8zT.mjs → NOTIFY_FILENAME-CjbDYC2a.mjs} +1 -1
  7. package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-By-jJ8_K.mjs +11 -0
  8. package/dist/packem_shared/chain-CubC5VoS.mjs +1 -0
  9. package/dist/packem_shared/classify-procedure-call-CcgP-9I0.mjs +1 -0
  10. package/dist/packem_shared/{context-property-calls-DdoCuhv4.mjs → context-property-calls-Bw8u2Pz4.mjs} +1 -1
  11. package/dist/packem_shared/{context-root-lGZCyHyj.mjs → context-root-YkWLB6M2.mjs} +1 -1
  12. package/dist/packem_shared/{database-calls-CVsXSVhv.mjs → database-calls-BnVUlTx_.mjs} +1 -1
  13. package/dist/packem_shared/discoverFunctions-5Zy6K4uA.mjs +1 -0
  14. package/dist/packem_shared/{discoverHttpRoutes-BccLtGKg.mjs → discoverHttpRoutes-WBAqBcfK.mjs} +1 -1
  15. package/dist/packem_shared/discoverHyperdriveCalls-DFbp-ILH.mjs +1 -0
  16. package/dist/packem_shared/{discoverInserts-rFszl3Al.mjs → discoverInserts-DUbjhNzk.mjs} +1 -1
  17. package/dist/packem_shared/discoverMaskProcedures-BfVFPpAJ.mjs +1 -0
  18. package/dist/packem_shared/{discoverNondeterministicCalls-9ZDpRptb.mjs → discoverNondeterministicCalls-D7Ovq8ae.mjs} +1 -1
  19. package/dist/packem_shared/{discoverQueries-DDds61UD.mjs → discoverQueries-BNqjOBY_.mjs} +1 -1
  20. package/dist/packem_shared/discoverR2sqlCalls-TNwsmYje.mjs +1 -0
  21. package/dist/packem_shared/{discoverRlsMetadata-Cb8JR1b4.mjs → discoverRlsMetadata-CbdfaVep.mjs} +1 -1
  22. package/dist/packem_shared/{discoverRlsProcedures-BfEFJmU5.mjs → discoverRlsProcedures-BeLdV5RT.mjs} +1 -1
  23. package/dist/packem_shared/{discoverStorageRulesMetadata-BPJplDfz.mjs → discoverStorageRulesMetadata-BBMy9JVZ.mjs} +1 -1
  24. package/dist/packem_shared/{emitApi-Zx6VPN-7.mjs → emitApi-CDgIPAG2.mjs} +45 -33
  25. package/dist/packem_shared/{emitFunctions-BeKgL3dl.mjs → emitFunctions-amc10WSc.mjs} +112 -62
  26. package/dist/packem_shared/{emitShard-D_dkDtuY.mjs → emitShard-o8m4pR4Z.mjs} +1 -1
  27. package/dist/packem_shared/{exported-procedure-chains-DKK5HoK3.mjs → exported-procedure-chains-DAl7xBBx.mjs} +1 -1
  28. package/dist/packem_shared/{index-Bxn8ZjS0.mjs → index-DvmKcoFV.mjs} +1 -1
  29. package/dist/packem_shared/{shard-Av4rUyYS.mjs → shard-26v1MJxM.mjs} +90 -78
  30. package/dist/packem_shared/{unwrap-handler-return-BwclbliB.mjs → unwrap-handler-return-CeaOifqX.mjs} +1 -1
  31. package/package.json +9 -9
  32. package/dist/packem_shared/DEFAULT_TARGET-BnQiNNKu.mjs +0 -1
  33. package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-DM4csP6n.mjs +0 -11
  34. package/dist/packem_shared/chain-CRDaTj2c.mjs +0 -1
  35. package/dist/packem_shared/classify-procedure-call-BAj0D1u2.mjs +0 -1
  36. package/dist/packem_shared/discoverFunctions-BiA7jv30.mjs +0 -1
  37. package/dist/packem_shared/discoverHyperdriveCalls-DxYmsE3Y.mjs +0 -1
  38. package/dist/packem_shared/discoverMaskProcedures-BZlL43UV.mjs +0 -1
  39. package/dist/packem_shared/discoverR2sqlCalls-CEbVN9V1.mjs +0 -1
@@ -1 +1 @@
1
- import{Node as u}from"ts-morph";import{listLunoraSourceFiles as f,lunoraRelativePath as p,stringPropertyOf as l}from"./isTestPath-B81lOULB.mjs";import{w as d}from"./classify-procedure-call-BAj0D1u2.mjs";import{e as m}from"./exported-procedure-chains-DKK5HoK3.mjs";const h=new Set(["delete","list","read","write"]),g=t=>d(t,"use","storageRules"),x=(t,s,n)=>{const e=t.getArguments()[0];if(!e||!u.isArrayLiteralExpression(e))return[];const i=[];for(const o of e.getElements()){if(!u.isObjectLiteralExpression(o))continue;const r=l(o,"on");if(r===void 0||!h.has(r))continue;const a=l(o,"prefix"),c={bucket:l(o,"bucket")??"",file:s,on:r,procedure:n};a!==void 0&&(c.prefix=a),i.push(c)}return i},A=(t,s)=>{const n=[];for(const e of f(s)){const i=t.getSourceFile(e)??t.addSourceFileAtPath(e),o=p(s,e);for(const{name:r,receiver:a}of m(i))for(const c of g(a))n.push(...x(c,o,r))}return{rules:n}};export{A as default};
1
+ import{Node as u}from"ts-morph";import{listLunoraSourceFiles as f,lunoraRelativePath as p,stringPropertyOf as l}from"./isTestPath-B81lOULB.mjs";import{w as d}from"./classify-procedure-call-CcgP-9I0.mjs";import{e as m}from"./exported-procedure-chains-DAl7xBBx.mjs";const h=new Set(["delete","list","read","write"]),g=t=>d(t,"use","storageRules"),x=(t,s,n)=>{const e=t.getArguments()[0];if(!e||!u.isArrayLiteralExpression(e))return[];const i=[];for(const o of e.getElements()){if(!u.isObjectLiteralExpression(o))continue;const r=l(o,"on");if(r===void 0||!h.has(r))continue;const a=l(o,"prefix"),c={bucket:l(o,"bucket")??"",file:s,on:r,procedure:n};a!==void 0&&(c.prefix=a),i.push(c)}return i},A=(t,s)=>{const n=[];for(const e of f(s)){const i=t.getSourceFile(e)??t.addSourceFileAtPath(e),o=p(s,e);for(const{name:r,receiver:a}of m(i))for(const c of g(a))n.push(...x(c,o,r))}return{rules:n}};export{A as default};
@@ -1,4 +1,4 @@
1
- import{agentComponent as N}from"@lunora/agent/component";import{LunoraError as w}from"@lunora/errors";import{r as d,a as R,b as v,c as P}from"./qualifiers-DEdXn5wP.mjs";import{a as O,r as g,p as $,G as x,b as y,c as b,d as S,e as L}from"./shared-DnCokNcE.mjs";import{s as f}from"./dispatch-namespace-DwTjD7BU.mjs";const j=t=>y(t,e=>{const a=d(g(e.args),e.filePath),n=d(P(e),e.filePath);return`${e.exportName}: FunctionReference<"${e.kind}", ${a}, ${n}>;`},"type"),A=(t,e)=>{if(t.length===0&&e.length===0)return{block:"",importLine:""};const a=[];let n="";if(t.length>0&&(n+="\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"),n+=`
1
+ import{agentComponent as N}from"@lunora/agent/component";import{LunoraError as R}from"@lunora/errors";import{r as d,a as w,b as v,c as L}from"./qualifiers-DEdXn5wP.mjs";import{a as P,r as y,p as $,G as x,b,c as m,d as S,e as j}from"./shared-DnCokNcE.mjs";import{s as h}from"./dispatch-namespace-DwTjD7BU.mjs";const O=t=>b(t,e=>{const r=d(y(e.args),e.filePath),n=d(L(e),e.filePath);return`${e.exportName}: FunctionReference<"${e.kind}", ${r}, ${n}>;`},"type"),A=(t,e)=>{if(t.length===0&&e.length===0)return{block:"",importLine:""};const r=[];let n="";if(t.length>0&&(n+="\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"),n+=`
2
2
  /** A typed reference to a durable workflow, addressable for \`cronJobs()\` targets. Mirrors \`@lunora/scheduler\`'s \`WorkflowReference\` structurally. */
3
3
  export interface WorkflowReference<Params = Record<string, unknown>> {
4
4
  readonly isLunoraWorkflow: true;
@@ -6,31 +6,31 @@ export interface WorkflowReference<Params = Record<string, unknown>> {
6
6
  readonly className: string;
7
7
  readonly name: string;
8
8
  }
9
- `,t.length>0){const i=[...t].toSorted((o,s)=>o.exportName.localeCompare(s.exportName)),r=i.map(o=>` ${o.exportName}: WorkflowReference<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${o.exportName}>>;`).join(`
10
- `),l=i.map(o=>` ${b(o.exportName)}: { isLunoraWorkflow: true, className: ${JSON.stringify(o.className)}, name: ${JSON.stringify(o.exportName)} },`).join(`
9
+ `,t.length>0){const s=[...t].toSorted((o,i)=>o.exportName.localeCompare(i.exportName)),a=s.map(o=>` ${o.exportName}: WorkflowReference<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${o.exportName}>>;`).join(`
10
+ `),l=s.map(o=>` ${m(o.exportName)}: { isLunoraWorkflow: true, className: ${JSON.stringify(o.className)}, name: ${JSON.stringify(o.exportName)} },`).join(`
11
11
  `);n+=`
12
12
  /** This project's durable workflows, addressable as typed references (e.g. \`crons.daily("digest", …, workflows.digestPipeline, params)\`). */
13
13
  export interface WorkflowsRef {
14
- ${r}
14
+ ${a}
15
15
  }
16
16
 
17
17
  export const workflows: WorkflowsRef = {
18
18
  ${l}
19
19
  };
20
- `,a.push(`import type * as lunoraWorkflowDefinitions from "../workflows.js";
21
- `)}if(e.length>0){const i=[...e].toSorted((o,s)=>o.exportName.localeCompare(s.exportName)),r=i.map(o=>` ${o.exportName}: WorkflowReference<AgentRunInput>;`).join(`
22
- `),l=i.map(o=>` ${b(o.exportName)}: { isLunoraWorkflow: true, className: ${JSON.stringify(o.className)}, name: ${JSON.stringify(o.name)} },`).join(`
20
+ `,r.push(`import type * as lunoraWorkflowDefinitions from "../workflows.js";
21
+ `)}if(e.length>0){const s=[...e].toSorted((o,i)=>o.exportName.localeCompare(i.exportName)),a=s.map(o=>` ${o.exportName}: WorkflowReference<AgentRunInput>;`).join(`
22
+ `),l=s.map(o=>` ${m(o.exportName)}: { isLunoraWorkflow: true, className: ${JSON.stringify(o.className)}, name: ${JSON.stringify(o.name)} },`).join(`
23
23
  `);n+=`
24
24
  /** 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 })\`). */
25
25
  export interface AgentsRef {
26
- ${r}
26
+ ${a}
27
27
  }
28
28
 
29
29
  export const agents: AgentsRef = {
30
30
  ${l}
31
31
  };
32
- `,a.push(`import type { AgentRunInput } from "@lunora/agent";
33
- `)}return{block:n,importLine:a.join("")}},I=()=>Object.keys(N().functions).toSorted((t,e)=>t.localeCompare(e)),C=t=>new Set(t.filter(e=>f(e.filePath)==="agents").map(e=>e.exportName)),M=()=>new Set(Object.entries(N().functions).filter(([,t])=>t.visibility==="internal").map(([t])=>t)),q=(t,e)=>{const a={importLine:"",lines:"",prelude:""};if(t.length===0)return a;const n=C(e),i=M(),r=e.find(o=>f(o.filePath)==="agents"&&i.has(o.exportName));if(r)throw new w("INTERNAL",`@lunora/codegen: "agents:${r.exportName}" is reserved for the durable agent loop's internal dispatch — rename the "${r.exportName}" export in ${r.filePath}`);const l=I().filter(o=>!n.has(o));return l.length===0?a:{importLine:`import { agentComponent } from "@lunora/agent/component";
32
+ `,r.push(`import type { AgentRunInput } from "@lunora/agent";
33
+ `)}return{block:n,importLine:r.join("")}},M=()=>Object.keys(N().functions).toSorted((t,e)=>t.localeCompare(e)),C=t=>new Set(t.filter(e=>h(e.filePath)==="agents").map(e=>e.exportName)),I=()=>new Set(Object.entries(N().functions).filter(([,t])=>t.visibility==="internal").map(([t])=>t)),U=(t,e)=>{const r={importLine:"",lines:"",prelude:""};if(t.length===0)return r;const n=C(e),s=I(),a=e.find(o=>h(o.filePath)==="agents"&&s.has(o.exportName));if(a)throw new R("INTERNAL",`@lunora/codegen: "agents:${a.exportName}" is reserved for the durable agent loop's internal dispatch — rename the "${a.exportName}" export in ${a.filePath}`);const l=M().filter(o=>!n.has(o));return l.length===0?r:{importLine:`import { agentComponent } from "@lunora/agent/component";
34
34
  `,lines:l.map(o=>` "agents:${o}": lunoraAgentRuntimeFunctions.${o} as unknown as RegisteredLunoraFunction,`).join(`
35
35
  `),prelude:`
36
36
  /**
@@ -39,29 +39,41 @@ ${l}
39
39
  * subscribe to the public queries (\`agents:agentMessages\` is the live thread view).
40
40
  */
41
41
  const lunoraAgentRuntimeFunctions = agentComponent().functions;
42
- `}},U=(t,e)=>{if(!t)return{importLine:"",lines:"",prelude:""};const a=e.find(n=>f(n.filePath)==="sandbox"&&n.exportName==="invoke");if(a)throw new w("INTERNAL",`@lunora/codegen: "sandbox:invoke" is reserved for the batteries-included sandbox tool dispatcher (browserTool/containerTool) — rename the "invoke" export in ${a.filePath}`);return{importLine:`import { sandboxComponent } from "@lunora/agent/component";
43
- `,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"}},K=(t,e)=>{if(t.length===0)return[];const a=C(e),n=[{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 i of t)i.voice&&n.push({args:{threadKey:{kind:"string"}},exportName:`${i.exportName}Voice`,filePath:"agents",kind:"stream",returnType:"Record<string, unknown>"});return n.filter(i=>!a.has(i.exportName))},E=(t,e)=>{if(t.length===0)return[];const a=new Set(e.filter(n=>f(n.filePath)==="mutators").map(n=>n.exportName));return t.filter(n=>!a.has(n.exportName)).map(n=>({args:n.args,exportName:n.exportName,filePath:n.filePath,kind:"mutation",returnType:n.returnType}))},F=t=>{const e=t.filter(r=>r.stream);if(e.length===0)return{block:"",body:""};const a=y(e,r=>{const l=d(r.chunkType??"unknown",r.filePath),o=d(g(r.searchParams),r.filePath),s=d(g(r.params),r.filePath);return`${L(r.exportName)}: HttpStreamRef<${l}, ${o}, ${s}>;`},"type"),n=y(e,r=>`${b(r.exportName)}: { method: ${JSON.stringify(r.method)}, path: ${JSON.stringify(r.path)} },`,"value");return{block:`
42
+ `}},V=(t,e)=>{if(!t)return{importLine:"",lines:"",prelude:""};const r=e.find(n=>h(n.filePath)==="sandbox"&&n.exportName==="invoke");if(r)throw new R("INTERNAL",`@lunora/codegen: "sandbox:invoke" is reserved for the batteries-included sandbox tool dispatcher (browserTool/containerTool) — rename the "invoke" export in ${r.filePath}`);return{importLine:`import { sandboxComponent } from "@lunora/agent/component";
43
+ `,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"}},K=(t,e)=>{if(t.length===0)return[];const r=C(e),n=[{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 s of t)s.voice&&n.push({args:{threadKey:{kind:"string"}},exportName:`${s.exportName}Voice`,filePath:"agents",kind:"stream",returnType:"Record<string, unknown>"});return n.filter(s=>!r.has(s.exportName))},E=(t,e)=>{if(t.length===0)return[];const r=new Set(e.filter(n=>h(n.filePath)==="mutators").map(n=>n.exportName));return t.filter(n=>!r.has(n.exportName)).map(n=>({args:n.args,exportName:n.exportName,filePath:n.filePath,kind:"mutation",returnType:n.returnType}))},F=t=>{const e=t.flatMap(s=>s.channel?.kind==="room"?[s.channel.name]:[]);if(e.length===0)return{block:"",importLine:""};const r=e.map(s=>` ${m(s)}: RoomRef<LunoraRoomMessages[${JSON.stringify(s)}]>;`).join(`
44
+ `),n=e.map(s=>` ${m(s)}: { name: ${JSON.stringify(s)} },`).join(`
45
+ `);return{block:`
46
+ /** This project's \`defineRoom\` rooms, addressable as typed references for \`client.connectRoom\`. */
47
+ export interface RoomsRef {
48
+ ${r}
49
+ }
50
+
51
+ export const rooms: RoomsRef = {
52
+ ${n}
53
+ };
54
+ `,importLine:`import type { LunoraRoomMessages } from "./functions.js";
55
+ `}},W=t=>{const e=t.filter(a=>a.stream);if(e.length===0)return{block:"",body:""};const r=b(e,a=>{const l=d(a.chunkType??"unknown",a.filePath),o=d(y(a.searchParams),a.filePath),i=d(y(a.params),a.filePath);return`${j(a.exportName)}: HttpStreamRef<${l}, ${o}, ${i}>;`},"type"),n=b(e,a=>`${m(a.exportName)}: { method: ${JSON.stringify(a.method)}, path: ${JSON.stringify(a.path)} },`,"value");return{block:`
44
56
  /** This project's HTTP-SSE stream routes (\`httpRoute.<verb>(path).stream()\`), addressable as typed references for \`client.httpStream\` / \`useHttpStream\`. */
45
57
  export interface HttpStreamsRef {
46
- ${a}
58
+ ${r}
47
59
  }
48
60
 
49
61
  export const httpStreams: HttpStreamsRef = {
50
62
  ${n}
51
63
  };
52
- `,body:a}},W=t=>y(t,e=>`${b(e.exportName)}: { __lunoraRef: ${JSON.stringify(`${f(e.filePath)}:${e.exportName}`)} },`,"value"),T=t=>{const{block:e="",constName:a,docComment:n="",functions:i,importLine:r="",typeName:l,typesBody:o="",useUmbrella:s}=t,c=j(i),p=W(i),m=R(`${c}
53
- ${o}`),k=m.length>0?`
54
- import type { ${m.join(", ")} } from "./dataModel.js";
55
- `:"",h=[...c===""?[]:["FunctionReference"],...t.clientImports??[]],u=h.length>0?`import type { ${h.join(", ")} } from "${S(s).client}";
56
- `:"";return v(`${x}${u}${r}${k}
64
+ `,body:r}},J=t=>b(t,e=>`${m(e.exportName)}: { __lunoraRef: ${JSON.stringify(`${h(e.filePath)}:${e.exportName}`)} },`,"value"),T=t=>{const{block:e="",constName:r,docComment:n="",functions:s,importLine:a="",typeName:l,typesBody:o="",useUmbrella:i}=t,c=O(s),p=J(s),u=w(`${c}
65
+ ${o}`),k=u.length>0?`
66
+ import type { ${u.join(", ")} } from "./dataModel.js";
67
+ `:"",g=[...c===""?[]:["FunctionReference"],...t.clientImports??[]],f=g.length>0?`import type { ${g.join(", ")} } from "${S(i).client}";
68
+ `:"";return v(`${x}${f}${a}${k}
57
69
  ${n}export interface ${l} {${c?`
58
70
  ${c}
59
71
  `:""}}
60
72
 
61
- export const ${a}: ${l} = {${p?`
73
+ export const ${r}: ${l} = {${p?`
62
74
  ${p}
63
75
  `:""}};
64
- ${e}`,s)},V=t=>{const{agents:e=[],functions:a,httpRoutes:n=[],mutators:i=[],useUmbrella:r=!1,workflows:l=[]}=t,o=F(n),s=A(l,e);return T({block:`${s.block}${o.block}`,clientImports:o.block===""?[]:["HttpStreamRef"],constName:"api",functions:[...a.filter(c=>c.visibility!=="internal"),...K(e,a),...E(i,a)],importLine:s.importLine,typeName:"ApiTypes",typesBody:o.body,useUmbrella:r})},z=t=>T({constName:"internal",docComment:"/** Internal functions — callable only server-side via `ctx.run*`, never from a client. */\n",functions:t.functions.filter(e=>e.visibility==="internal"),typeName:"InternalApiTypes",useUmbrella:t.useUmbrella??!1}),G=t=>t?`${x}import { createSeedClient as createSeedClientBase } from "@lunora/seed";
76
+ ${e}`,i)},z=t=>{const{agents:e=[],functions:r,httpRoutes:n=[],mutators:s=[],useUmbrella:a=!1,workflows:l=[]}=t,o=W(n),i=F(r),c=A(l,e);return T({block:`${c.block}${o.block}${i.block}`,clientImports:[...o.block===""?[]:["HttpStreamRef"],...i.block===""?[]:["RoomRef"]],constName:"api",functions:[...r.filter(p=>p.visibility!=="internal"),...K(e,r),...E(s,r)],importLine:`${c.importLine}${i.importLine}`,typeName:"ApiTypes",typesBody:o.body,useUmbrella:a})},G=t=>T({constName:"internal",docComment:"/** Internal functions — callable only server-side via `ctx.run*`, never from a client. */\n",functions:t.functions.filter(e=>e.visibility==="internal"),typeName:"InternalApiTypes",useUmbrella:t.useUmbrella??!1}),Q=t=>t?`${x}import { createSeedClient as createSeedClientBase } from "@lunora/seed";
65
77
  import type { SeedClient, SeedClientOptions } from "@lunora/seed";
66
78
 
67
79
  import schema from "../schema.js";
@@ -78,8 +90,8 @@ import type { InsertModel } from "./dataModel.js";
78
90
  * const { posts } = await seed.posts((x) => x([10, 20]));
79
91
  */
80
92
  export const createSeedClient = (options?: SeedClientOptions): SeedClient<InsertModel> => createSeedClientBase<InsertModel>(schema, options);
81
- `:"",Q=(t,e,a=!1)=>{if(t.length===0||!e)return"";const n=S(a),i=s=>s.table===void 0?"Row":`Doc<${JSON.stringify(s.table)}> & Row`,r=t.map(s=>{O(s.exportName,"shape export name");const c=i(s),p=d(g(s.args),s.filePath),m=Object.keys(s.args).length>0,k=m?` args: ${p};`:` args?: ${p};`,h=m?`(args: ${p}) => void`:`(args?: ${p}) => void`,u=`${s.exportName}CollectionOptions`;return`/** Options for the \`${s.exportName}\` shape binding. */
82
- export interface ${$(u)} {
93
+ `:"",X=(t,e,r=!1)=>{if(t.length===0||!e)return"";const n=S(r),s=i=>i.table===void 0?"Row":`Doc<${JSON.stringify(i.table)}> & Row`,a=t.map(i=>{P(i.exportName,"shape export name");const c=s(i),p=d(y(i.args),i.filePath),u=Object.keys(i.args).length>0,k=u?` args: ${p};`:` args?: ${p};`,g=u?`(args: ${p}) => void`:`(args?: ${p}) => void`,f=`${i.exportName}CollectionOptions`;return`/** Options for the \`${i.exportName}\` shape binding. */
94
+ export interface ${$(f)} {
83
95
  ${k}
84
96
  /**
85
97
  * Share the optimistic-overlay gate with other collections + mutators on this
@@ -100,11 +112,11 @@ ${k}
100
112
  }
101
113
 
102
114
  /**
103
- * Collection options for the \`${s.exportName}\` replication shape: \`config\` for
115
+ * Collection options for the \`${i.exportName}\` replication shape: \`config\` for
104
116
  * \`createCollection\`, plus the \`checkpoints\` registry to hand \`bindMutators\` and
105
117
  * \`scope\` to re-point the subscription.
106
118
  */
107
- export const ${s.exportName}CollectionOptions = (options: ${$(u)}): LunoraCollectionOptions<${c}> =>
119
+ export const ${i.exportName}CollectionOptions = (options: ${$(f)}): LunoraCollectionOptions<${c}> =>
108
120
  lunoraCollectionOptions<${c}>({
109
121
  client: options.client,
110
122
  ...(options.checkpoints === undefined ? {} : { checkpoints: options.checkpoints }),
@@ -112,24 +124,24 @@ export const ${s.exportName}CollectionOptions = (options: ${$(u)}): LunoraCollec
112
124
  ...(options.load === undefined ? {} : { load: options.load }),
113
125
  ...(options.onError === undefined ? {} : { onError: options.onError }),
114
126
  ...(options.shardKey === undefined ? {} : { shardKey: options.shardKey }),
115
- shape: { args: options.args, name: ${JSON.stringify(s.exportName)}, ...(options.shardKey === undefined ? {} : { shardKey: options.shardKey }) },
127
+ shape: { args: options.args, name: ${JSON.stringify(i.exportName)}, ...(options.shardKey === undefined ? {} : { shardKey: options.shardKey }) },
116
128
  });
117
129
 
118
- /** Live collection for the \`${s.exportName}\` shape, with its sync controls. */
119
- export const ${s.exportName}Collection = (
120
- options: ${$(u)},
121
- ): { checkpoints: CheckpointRegistry; collection: Collection<${c}, string>; scope: ${h} } => {
122
- const { checkpoints, config, scope } = ${s.exportName}CollectionOptions(options);
130
+ /** Live collection for the \`${i.exportName}\` shape, with its sync controls. */
131
+ export const ${i.exportName}Collection = (
132
+ options: ${$(f)},
133
+ ): { checkpoints: CheckpointRegistry; collection: Collection<${c}, string>; scope: ${g} } => {
134
+ const { checkpoints, config, scope } = ${i.exportName}CollectionOptions(options);
123
135
 
124
136
  return { checkpoints, collection: createCollection(config), scope };
125
137
  };`}).join(`
126
138
 
127
- `),l=R(r),o=l.length>0?`import type { ${l.join(", ")} } from "./dataModel.js";
139
+ `),l=w(a),o=l.length>0?`import type { ${l.join(", ")} } from "./dataModel.js";
128
140
  `:"";return`${x}import type { LunoraClient, SubscriptionError } from "${n.client}";
129
141
  import { lunoraCollectionOptions } from "@lunora/db/collections";
130
142
  import type { CheckpointRegistry, LunoraCollectionOptions, Row } from "@lunora/db";
131
143
  import type { Collection } from "@tanstack/db";
132
144
  import { createCollection } from "@tanstack/db";
133
145
  ${o}
134
- ${r}
135
- `};export{V as emitApi,Q as emitCollections,z as emitInternalApi,G as emitSeed,q as renderAgentFunctionRegistry,U as renderSandboxFunctionRegistry};
146
+ ${a}
147
+ `};export{z as emitApi,X as emitCollections,G as emitInternalApi,Q as emitSeed,U as renderAgentFunctionRegistry,V as renderSandboxFunctionRegistry};
@@ -1,30 +1,30 @@
1
- import{LunoraError as B}from"@lunora/errors";import{L as H,G as q,I as J,d as Q,b as S,r as G,c as z}from"./shared-DnCokNcE.mjs";import{renderAgentFunctionRegistry as V,renderSandboxFunctionRegistry as W}from"./emitApi-Zx6VPN-7.mjs";import{a as K,b as Y,r as O,c as X}from"./qualifiers-DEdXn5wP.mjs";import{s as g}from"./dispatch-namespace-DwTjD7BU.mjs";const Z=new Set(["any","bigint","boolean","date","id","null","number","storage","string","timestamp"]),A=n=>n.column!==void 0,ee=(n,e)=>{switch(n){case"bigint":return`if (typeof ${e} !== "bigint") return DEFER;
1
+ import{LunoraError as Q}from"@lunora/errors";import{L as G,G as z,I as V,d as W,b as A,r as K,c as Y}from"./shared-DnCokNcE.mjs";import{renderAgentFunctionRegistry as X,renderSandboxFunctionRegistry as Z}from"./emitApi-CDgIPAG2.mjs";import{a as ee,b as te,r as _,c as ne}from"./qualifiers-DEdXn5wP.mjs";import{s as g}from"./dispatch-namespace-DwTjD7BU.mjs";const re=new Set(["any","bigint","boolean","date","id","null","number","storage","string","timestamp"]),L=n=>n.column!==void 0,oe=(n,e)=>{switch(n){case"bigint":return`if (typeof ${e} !== "bigint") return DEFER;
2
2
  `;case"boolean":return`if (typeof ${e} !== "boolean") return DEFER;
3
3
  `;case"date":case"number":case"timestamp":return`if (typeof ${e} !== "number" || !Number.isFinite(${e})) return DEFER;
4
4
  `;case"null":return`if (${e} !== null) return DEFER;
5
5
  `;default:return`if (typeof ${e} !== "string") return DEFER;
6
- `}},te=(n,e)=>n.stringMaxLength===void 0?"":`if (${e}.length > ${String(n.stringMaxLength)}) return DEFER;
7
- `,ne=(n,e)=>{const r=n.literalValue?.trim();if(!(r===void 0||!H.test(r)))return{out:e,pre:`if (${e} !== ${r}) return DEFER;
8
- `}},v=(n,e,r)=>{if(!A(n)&&!(n.unmodelledRefinement||n.sourceText!==void 0)){if(Z.has(n.kind))return n.kind==="any"?{out:e,pre:""}:{out:e,pre:ee(n.kind,e)+te(n,e)};switch(n.kind){case"array":return re(n,e,r);case"literal":return ne(n,e);case"object":return se(n,e,r);default:return}}},re=(n,e,r)=>{const{inner:o}=n;if(!o)return;const a=r.next(),s=`__arr${String(a)}`,i=`__i${String(a)}`,c=`__e${String(a)}`,l=v(o,c,r);if(!l)return;const u=`if (!Array.isArray(${e})) return DEFER;
9
- const ${s} = new Array(${e}.length);
6
+ `}},se=(n,e)=>n.stringMaxLength===void 0?"":`if (${e}.length > ${String(n.stringMaxLength)}) return DEFER;
7
+ `,ae=(n,e)=>{const r=n.literalValue?.trim();if(!(r===void 0||!G.test(r)))return{out:e,pre:`if (${e} !== ${r}) return DEFER;
8
+ `}},N=(n,e,r)=>{if(!L(n)&&!(n.unmodelledRefinement||n.sourceText!==void 0)){if(re.has(n.kind))return n.kind==="any"?{out:e,pre:""}:{out:e,pre:oe(n.kind,e)+se(n,e)};switch(n.kind){case"array":return ie(n,e,r);case"literal":return ae(n,e);case"object":return ue(n,e,r);default:return}}},ie=(n,e,r)=>{const{inner:o}=n;if(!o)return;const s=r.next(),a=`__arr${String(s)}`,i=`__i${String(s)}`,c=`__e${String(s)}`,u=N(o,c,r);if(!u)return;const l=`if (!Array.isArray(${e})) return DEFER;
9
+ const ${a} = new Array(${e}.length);
10
10
  for (let ${i} = 0; ${i} < ${e}.length; ${i}++) {
11
11
  const ${c} = ${e}[${i}];
12
- ${l.pre}${s}[${i}] = ${l.out};
12
+ ${u.pre}${a}[${i}] = ${u.out};
13
13
  }
14
- `;return{out:s,pre:u}},oe=(n,e,r,o)=>{const a=JSON.stringify(n);if(e.kind==="optional"){if(e.hasRefinement||e.sourceText!==void 0||A(e))return;const{inner:i}=e;if(!i)return;const c=v(i,r,o);if(!c)return;const l=o.next(),u=`__has${String(l)}`,d=`__val${String(l)}`,f=`let ${u} = false;
15
- let ${d};
14
+ `;return{out:a,pre:l}},ce=(n,e,r,o)=>{const s=JSON.stringify(n);if(e.kind==="optional"){if(e.hasRefinement||e.sourceText!==void 0||L(e))return;const{inner:i}=e;if(!i)return;const c=N(i,r,o);if(!c)return;const u=o.next(),l=`__has${String(u)}`,h=`__val${String(u)}`,f=`let ${l} = false;
15
+ let ${h};
16
16
  if (${r} !== undefined) {
17
- ${c.pre}${d} = ${c.out};
18
- ${u} = true;
17
+ ${c.pre}${h} = ${c.out};
18
+ ${l} = true;
19
19
  }
20
- `;return{entry:`...(${u} ? { ${a}: ${d} } : {})`,pre:f}}const s=v(e,r,o);if(s)return{entry:`${a}: ${s.out}`,pre:s.pre}},ae=new Set(Object.getOwnPropertyNames(Object.prototype)),_=(n,e,r)=>{let o="";const a=[];for(const s of Object.keys(n)){const i=n[s];if(!i)return;const c=JSON.stringify(s);let l=`${e}[${c}]`;if(ae.has(s)){const d=`__f${String(r.next())}`;o+=`const ${d} = Object.hasOwn(${e}, ${c}) ? ${e}[${c}] : undefined;
21
- `,l=d}const u=oe(s,i,l,r);if(!u)return;o+=u.pre,a.push(u.entry)}return{entries:a.join(", "),pre:o}},T=n=>{const e=`Object.getPrototypeOf(${n})`;return`if (${e} !== Object.prototype && ${e} !== null) return DEFER;
22
- `},se=(n,e,r)=>{const o=n.shape??{},a=_(o,e,r);if(!a)return;const s=r.next(),i=`__obj${String(s)}`,c=`if (typeof ${e} !== "object" || ${e} === null || Array.isArray(${e})) return DEFER;
23
- ${T(e)}${a.pre}const ${i} = { ${a.entries} };
24
- `;return{out:i,pre:c}},ie=n=>{let e=0;const o=_(n,"source",{next:()=>(e+=1,e)});if(o)return`(source) => {
20
+ `;return{entry:`...(${l} ? { ${s}: ${h} } : {})`,pre:f}}const a=N(e,r,o);if(a)return{entry:`${s}: ${a.out}`,pre:a.pre}},le=new Set(Object.getOwnPropertyNames(Object.prototype)),P=(n,e,r)=>{let o="";const s=[];for(const a of Object.keys(n)){const i=n[a];if(!i)return;const c=JSON.stringify(a);let u=`${e}[${c}]`;if(le.has(a)){const h=`__f${String(r.next())}`;o+=`const ${h} = Object.hasOwn(${e}, ${c}) ? ${e}[${c}] : undefined;
21
+ `,u=h}const l=ce(a,i,u,r);if(!l)return;o+=l.pre,s.push(l.entry)}return{entries:s.join(", "),pre:o}},M=n=>{const e=`Object.getPrototypeOf(${n})`;return`if (${e} !== Object.prototype && ${e} !== null) return DEFER;
22
+ `},ue=(n,e,r)=>{const o=n.shape??{},s=P(o,e,r);if(!s)return;const a=r.next(),i=`__obj${String(a)}`,c=`if (typeof ${e} !== "object" || ${e} === null || Array.isArray(${e})) return DEFER;
23
+ ${M(e)}${s.pre}const ${i} = { ${s.entries} };
24
+ `;return{out:i,pre:c}},de=n=>{let e=0;const o=P(n,"source",{next:()=>(e+=1,e)});if(o)return`(source) => {
25
25
  if (typeof source !== "object" || source === null || Array.isArray(source)) return DEFER;
26
- ${T("source")}${o.pre}return { ${o.entries} };
27
- }`},ce=(n,e)=>`lunora_${g(n)}_${String(e)}`,le=`const callRegistered = async <R>(context: CallerCtx, functionPath: string, args: Record<string, unknown> | undefined): Promise<R> => {
26
+ ${M("source")}${o.pre}return { ${o.entries} };
27
+ }`},he=(n,e)=>`lunora_${g(n)}_${String(e)}`,me=`const callRegistered = async <R>(context: CallerCtx, functionPath: string, args: Record<string, unknown> | undefined): Promise<R> => {
28
28
  const registered = LUNORA_FUNCTIONS[functionPath];
29
29
 
30
30
  if (!registered) {
@@ -57,60 +57,110 @@ ${T("source")}${o.pre}return { ${o.entries} };
57
57
  }
58
58
 
59
59
  return (await registered.handler(context, args ?? {})) as R;
60
- };`,ue=(n,e,r=[],o=[])=>{const a=new Map,s=t=>{a.has(t)||a.set(t,ce(t,a.size))};for(const t of n)s(t.filePath);for(const t of e)s(t.filePath);for(const t of r)s(t.filePath);for(const t of o)s(t.filePath);const i=[...a.entries()].map(([t,m])=>{if(!J.test(t))throw new B("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(t)}`);return`import * as ${m} from "../${t}.js";`}).join(`
61
- `),c=n.map(t=>` "${g(t.filePath)}:${t.exportName}": ${a.get(t.filePath)??""}.${t.exportName} as unknown as RegisteredLunoraFunction,`).join(`
62
- `),l=e.map(t=>` ${JSON.stringify(t.id)}: ${a.get(t.filePath)??""}.${t.exportName} as unknown as RegisteredDataMigration,`).join(`
63
- `),u=r.map(t=>` "${g(t.filePath)}:${t.exportName}": ${a.get(t.filePath)??""}.${t.exportName} as unknown as RegisteredLunoraFunction,`).join(`
64
- `),d=o.map(t=>` "${t.exportName}": ${a.get(t.filePath)??""}.${t.exportName} as unknown as RegisteredShape,`).join(`
65
- `),f=r.map(t=>`${g(t.filePath)}:${t.exportName}`),p=[c,u].filter(t=>t.length>0).join(`
66
- `),R=n.map(t=>{if(t.lifecycle||Object.keys(t.args).length===0)return;const m=ie(t.args);return m===void 0?void 0:`installCompiledValidatorMap(${a.get(t.filePath)??""}.${t.exportName}.args, ${m});`}).filter(t=>t!==void 0).join(`
67
- `);return{dispatchBody:p.length>0?`
68
- ${p}
60
+ };`,pe=(n,e,r=[],o=[])=>{const s=new Map,a=t=>{s.has(t)||s.set(t,he(t,s.size))};for(const t of n)a(t.filePath);for(const t of e)a(t.filePath);for(const t of r)a(t.filePath);for(const t of o)a(t.filePath);const i=[...s.entries()].map(([t,p])=>{if(!V.test(t))throw new Q("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(t)}`);return`import * as ${p} from "../${t}.js";`}).join(`
61
+ `),c=n.map(t=>` "${g(t.filePath)}:${t.exportName}": ${s.get(t.filePath)??""}.${t.exportName} as unknown as RegisteredLunoraFunction,`).join(`
62
+ `),u=e.map(t=>` ${JSON.stringify(t.id)}: ${s.get(t.filePath)??""}.${t.exportName} as unknown as RegisteredDataMigration,`).join(`
63
+ `),l=r.map(t=>` "${g(t.filePath)}:${t.exportName}": ${s.get(t.filePath)??""}.${t.exportName} as unknown as RegisteredLunoraFunction,`).join(`
64
+ `),h=o.map(t=>` "${t.exportName}": ${s.get(t.filePath)??""}.${t.exportName} as unknown as RegisteredShape,`).join(`
65
+ `),f=r.map(t=>`${g(t.filePath)}:${t.exportName}`),m=[c,l].filter(t=>t.length>0).join(`
66
+ `),b=n.map(t=>{if(t.lifecycle||Object.keys(t.args).length===0)return;const p=de(t.args);return p===void 0?void 0:`installCompiledValidatorMap(${s.get(t.filePath)??""}.${t.exportName}.args, ${p});`}).filter(t=>t!==void 0).join(`
67
+ `),R=n.filter(t=>t.channel?.kind==="room").map(t=>` ${JSON.stringify(t.channel?.name??"")}: RoomMessageOf<typeof ${s.get(t.filePath)??""}[${JSON.stringify(t.exportName)}]>;`).join(`
68
+ `);return{dispatchBody:m.length>0?`
69
+ ${m}
69
70
  `:"",importBlock:i.length>0?`${i}
70
71
 
71
- `:"",installBlock:R,migrationBody:l.length>0?`
72
- ${l}
73
- `:"",mutatorPaths:f,shapeBody:d.length>0?`
74
- ${d}
75
- `:""}},de=n=>{const e=S(n,o=>{const a=O(G(o.args),o.filePath),s=a==="{}"?"?":"",i=O(X(o),o.filePath);return o.kind==="stream"?`${o.exportName}: (args${s}: ${a}) => Promise<AsyncIterable<${i}>>;`:`${o.exportName}: (args${s}: ${a}) => Promise<${i}>;`},"type");return{implementation:S(n,o=>`${z(o.exportName)}: (args) => callRegistered(context, "${g(o.filePath)}:${o.exportName}", args),`,"value"),types:e}},he=n=>{const e={connect:[],disconnect:[],init:[],reactor:[],whisper:[]};for(const r of n)r.lifecycle&&e[r.lifecycle].push(`${g(r.filePath)}:${r.exportName}`);return e},$e=n=>{const{agents:e=[],functions:r,migrations:o=[],mutators:a=[],shapes:s=[],useUmbrella:i=!1,usesSandbox:c=!1}=n,l=r.length>0,u=Q(i),{dispatchBody:d,importBlock:f,installBlock:p,migrationBody:R,mutatorPaths:t,shapeBody:m}=ue(r,o,a,s),b=V(e,r),w=W(c,r),k=[b.lines,w.lines].filter(h=>h.length>0).join(`
76
- `);let N=d;k.length>0&&(N=d.length>0?`${d.trimEnd()}
77
- ${k}
72
+ `:"",installBlock:b,migrationBody:u.length>0?`
73
+ ${u}
74
+ `:"",mutatorPaths:f,roomMessagesBody:R,shapeBody:h.length>0?`
75
+ ${h}
76
+ `:""}},ge=n=>{const e=A(n,o=>{const s=_(K(o.args),o.filePath),a=s==="{}"?"?":"",i=_(ne(o),o.filePath);return o.kind==="stream"?`${o.exportName}: (args${a}: ${s}) => Promise<AsyncIterable<${i}>>;`:`${o.exportName}: (args${a}: ${s}) => Promise<${i}>;`},"type");return{implementation:A(n,o=>`${Y(o.exportName)}: (args) => callRegistered(context, "${g(o.filePath)}:${o.exportName}", args),`,"value"),types:e}},fe=n=>{const e={connect:[],disconnect:[],init:[],reactor:[],whisper:[]};for(const r of n)r.lifecycle&&e[r.lifecycle].push(`${g(r.filePath)}:${r.exportName}`);return e},ye=(n,e,r)=>n?{channelField:` /**
77
+ * Set on a \`defineRoom\` registration: the room's name (without the \`room:\`
78
+ * topic prefix). The generated \`LUNORA_ROOMS\` map keys it on the room's
79
+ * \`room:<name>\` whisper topic so the ShardDO resolves a room topic to this
80
+ * path.
81
+ */
82
+ channel?: { readonly kind: "room"; readonly name: string };
83
+ `,messagesBlock:`
84
+ /**
85
+ * The message type each \`defineRoom\` carries, read off the room's own registration. The generated \`rooms\` references type a client's \`connectRoom\` from it.
86
+ */
87
+ export type LunoraRoomMessages = {
88
+ ${r}
89
+ };
90
+ `,typeImport:`import type { RoomMessageOf } from "${e}";
91
+ `}:{channelField:"",messagesBlock:"",typeImport:""},ve=n=>{const{agents:e=[],functions:r,migrations:o=[],mutators:s=[],shapes:a=[],useUmbrella:i=!1,usesSandbox:c=!1}=n,u=r.length>0,l=W(i),{dispatchBody:h,importBlock:f,installBlock:m,migrationBody:b,mutatorPaths:R,roomMessagesBody:t,shapeBody:p}=pe(r,o,s,a),w=X(e,r),k=Z(c,r),v=[w.lines,k.lines].filter(d=>d.length>0).join(`
92
+ `);let S=h;v.length>0&&(S=h.length>0?`${h.trimEnd()}
93
+ ${v}
78
94
  `:`
79
- ${k}
80
- `);const y=he(r),P=s.length>0?`import type { RegisteredShape } from "${u.server}";
81
- `:"",L=s.length>0?`
95
+ ${v}
96
+ `);const y=fe(r),E=a.length>0?`import type { RegisteredShape } from "${l.server}";
97
+ `:"",x=r.some(d=>d.channel?.kind==="room"),O=ye(x,l.server,t),C=a.length>0?`
82
98
  /**
83
99
  * Replication-shape registry — one entry per \`defineShape\` in \`lunora/shapes.ts\`.
84
100
  * The generated ShardDO's \`resolveShape\` override looks a shape up by name and
85
101
  * evaluates its trusted \`compileWhere(ctx, args)\` to authorize + scope a
86
102
  * \`shape_subscribe\` (reads-as-permissions).
87
103
  */
88
- export const LUNORA_SHAPES: Record<string, RegisteredShape> = {${m}};
89
- `:"",E=t.length>0?`
104
+ export const LUNORA_SHAPES: Record<string, RegisteredShape> = {${p}};
105
+ `:"",F=R.length>0?`
90
106
  /**
91
107
  * Custom-mutator function paths — the \`LUNORA_FUNCTIONS\` keys the generated
92
108
  * ShardDO's \`isCustomMutator\` override routes through the client-watermark push
93
109
  * protocol (\`x-lunora-client-id\`/\`x-lunora-client-seq\` ordering).
94
110
  */
95
- export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${t.map(h=>JSON.stringify(h)).join(", ")}]);
96
- `:"",C=p.length>0?`import { DEFER_VALIDATION as DEFER, installCompiledValidatorMap } from "${u.values}";
97
- `:"",j=p.length>0?`
111
+ export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${R.map(d=>JSON.stringify(d)).join(", ")}]);
112
+ `:"",j=x?`
113
+ /**
114
+ * Room registry: the whisper topic of each \`defineRoom\` registration → its
115
+ * function path. The generated ShardDO's \`roomHandlerPath\` override resolves a
116
+ * room topic through this map so a room's typed \`onJoin\`/\`onMessage\`/\`onLeave\`
117
+ * dispatch server-side, reusing the whisper channel for membership and fan-out.
118
+ * Two registrations under one name throw at module load: the map would otherwise
119
+ * silently keep whichever came last.
120
+ */
121
+ export const LUNORA_ROOMS: Readonly<Record<string, string>> = (() => {
122
+ const registry: Record<string, string> = {};
123
+ const owners = new Map<string, unknown>();
124
+
125
+ for (const [path, fn] of Object.entries(LUNORA_FUNCTIONS)) {
126
+ if (fn.channel?.kind !== "room") {
127
+ continue;
128
+ }
129
+
130
+ const topic = \`room:\${fn.channel.name}\`;
131
+ const owner = owners.get(topic);
132
+
133
+ // The same registration exported under two names (an alias) is one room.
134
+ if (owner !== undefined && owner !== fn) {
135
+ throw new Error(\`two defineRoom registrations are named "\${fn.channel.name}"; room names must be unique\`);
136
+ }
137
+
138
+ if (owner === undefined) {
139
+ owners.set(topic, fn);
140
+ registry[topic] = path;
141
+ }
142
+ }
143
+
144
+ return registry;
145
+ })();
146
+ `:"",I=m.length>0?`import { DEFER_VALIDATION as DEFER, installCompiledValidatorMap } from "${l.values}";
147
+ `:"",D=m.length>0?`
98
148
  /**
99
149
  * AOT-compiled argument validators (Worker-safe, no \`eval\`). Each is installed
100
150
  * onto its function's live \`.args\` object and consulted by the interpreted
101
151
  * parser as a zero-allocation fast path; anything it can't model is deferred.
102
152
  */
103
- ${p}
104
- `:"",$=de(r),F=$.types?`
153
+ ${m}
154
+ `:"",$=ge(r),U=$.types?`
105
155
  ${$.types}
106
- `:"",M=$.implementation?`
156
+ `:"",B=$.implementation?`
107
157
  ${$.implementation}
108
- `:"",x=K($.types),D=x.length>0?`import type { ${x.join(", ")} } from "./dataModel.js";
109
- `:"",I=l?"context":"_context",U=l?`${le}
158
+ `:"",T=ee($.types),H=T.length>0?`import type { ${T.join(", ")} } from "./dataModel.js";
159
+ `:"",J=u?"context":"_context",q=u?`${me}
110
160
 
111
- `:"";return Y(`${q}${f}${b.importLine}${w.importLine}${C}${P}import { LunoraError } from "${u.server}";
161
+ `:"";return te(`${z}${f}${w.importLine}${k.importLine}${I}${E}${O.typeImport}import { LunoraError } from "${l.server}";
112
162
  import type { ActionCtx, MutationCtx, QueryCtx } from "./server.js";
113
- ${D}
163
+ ${H}
114
164
  /**
115
165
  * Single registered function, narrowed to the shape \`handleRpc\` needs.
116
166
  * The real argument validators / return types are checked elsewhere — at
@@ -140,7 +190,7 @@ export interface RegisteredLunoraFunction {
140
190
  * to. \`whisper\` does have one — it runs under the asking socket's identity.
141
191
  */
142
192
  lifecycle?: "connect" | "disconnect" | "init" | "reactor" | "whisper";
143
- /**
193
+ ${O.channelField} /**
144
194
  * Hoisted by the builder when the \`.use()\` chain carries a step with a
145
195
  * per-dispatch effect — \`rateLimit(...)\` consuming budget, a single-use
146
196
  * captcha token being burned. Read by \`isCacheableQuery\`: the chain runs
@@ -156,13 +206,13 @@ export interface RegisteredLunoraFunction {
156
206
  */
157
207
  x402?: { readonly price: number | string };
158
208
  }
159
- ${b.prelude}${w.prelude}
209
+ ${w.prelude}${k.prelude}
160
210
  /**
161
211
  * Static dispatch table. The key matches the \`__lunoraRef\` the client
162
212
  * emits (\`api[namespace][fn].__lunoraRef === "namespace:fn"\`).
163
213
  */
164
- export const LUNORA_FUNCTIONS: Record<string, RegisteredLunoraFunction> = {${N}};
165
- ${j}${L}${E}
214
+ export const LUNORA_FUNCTIONS: Record<string, RegisteredLunoraFunction> = {${S}};
215
+ ${D}${C}${F}${j}${O.messagesBlock}
166
216
  /**
167
217
  * Lifecycle manifest: the function paths the generated ShardDO dispatches when a
168
218
  * client's WebSocket connects (\`connect\`) or disconnects (\`disconnect\`), once
@@ -180,11 +230,11 @@ export const LUNORA_LIFECYCLE_HOOKS: {
180
230
  reactor: readonly string[];
181
231
  whisper: readonly string[];
182
232
  } = {
183
- connect: [${y.connect.map(h=>JSON.stringify(h)).join(", ")}],
184
- disconnect: [${y.disconnect.map(h=>JSON.stringify(h)).join(", ")}],
185
- init: [${y.init.map(h=>JSON.stringify(h)).join(", ")}],
186
- reactor: [${y.reactor.map(h=>JSON.stringify(h)).join(", ")}],
187
- whisper: [${y.whisper.map(h=>JSON.stringify(h)).join(", ")}],
233
+ connect: [${y.connect.map(d=>JSON.stringify(d)).join(", ")}],
234
+ disconnect: [${y.disconnect.map(d=>JSON.stringify(d)).join(", ")}],
235
+ init: [${y.init.map(d=>JSON.stringify(d)).join(", ")}],
236
+ reactor: [${y.reactor.map(d=>JSON.stringify(d)).join(", ")}],
237
+ whisper: [${y.whisper.map(d=>JSON.stringify(d)).join(", ")}],
188
238
  };
189
239
 
190
240
  /**
@@ -215,10 +265,10 @@ export type CallerCtx = ActionCtx | MutationCtx | QueryCtx;
215
265
  * with the supplied \`context\`, exactly like \`ctx.runQuery\`/\`runMutation\`/
216
266
  * \`runAction\` but without re-stating the function path.
217
267
  */
218
- export interface Caller {${F}}
268
+ export interface Caller {${U}}
219
269
 
220
- ${U}/** Build a {@link Caller} bound to \`context\` (typically a handler's \`ctx\`). */
221
- export const createCaller = (${I}: CallerCtx): Caller => ({${M}});
270
+ ${q}/** Build a {@link Caller} bound to \`context\` (typically a handler's \`ctx\`). */
271
+ export const createCaller = (${J}: CallerCtx): Caller => ({${B}});
222
272
 
223
273
  /**
224
274
  * Single registered data migration, narrowed to the shape the per-shard runner
@@ -237,5 +287,5 @@ export interface RegisteredDataMigration {
237
287
  * Registry of online data migrations keyed by \`defineMigration\`'s \`id\`. The
238
288
  * shard DO's admin RPC and the CLI resolve migrations to run through this map.
239
289
  */
240
- export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${R}};
241
- `,i)};export{$e as default};
290
+ export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${b}};
291
+ `,i)};export{ve as default};
@@ -1 +1 @@
1
- import"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import"./isD1GlobalTable-udvHAAzD.mjs";import"./json-data-Chfs2Cz5.mjs";import{e as d}from"./shard-Av4rUyYS.mjs";import"./shard-runtime-CkTgY8tL.mjs";import"./shared-DnCokNcE.mjs";import"./platform-8oj7iXQy.mjs";import"./schema-BgM8A3XV.mjs";export{d as default};
1
+ import"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import"./isD1GlobalTable-udvHAAzD.mjs";import"./json-data-Chfs2Cz5.mjs";import{e as d}from"./shard-26v1MJxM.mjs";import"./shard-runtime-CkTgY8tL.mjs";import"./shared-DnCokNcE.mjs";import"./platform-8oj7iXQy.mjs";import"./schema-BgM8A3XV.mjs";export{d as default};
@@ -1 +1 @@
1
- import{Node as s}from"ts-morph";import{b as t,d as c}from"./attribution-hVBriwzy.mjs";import{c as n}from"./classify-procedure-call-BAj0D1u2.mjs";const m=a=>{const i=[];for(const e of t(a)){const r=e.getInitializer(),o=r&&s.isCallExpression(r)?n(r):void 0;o?.receiver&&i.push({name:c(e)??e.getName(),receiver:o.receiver})}return i};export{m as e};
1
+ import{Node as s}from"ts-morph";import{b as t,d as c}from"./attribution-hVBriwzy.mjs";import{c as n}from"./classify-procedure-call-CcgP-9I0.mjs";const m=a=>{const i=[];for(const e of t(a)){const r=e.getInitializer(),o=r&&s.isCallExpression(r)?n(r):void 0;o?.receiver&&i.push({name:c(e)??e.getName(),receiver:o.receiver})}return i};export{m as e};
@@ -1 +1 @@
1
- import{Node as r}from"ts-morph";import{listLunoraSourceFiles as u,lunoraRelativePath as f}from"./isTestPath-B81lOULB.mjs";import{b as m,d as p}from"./attribution-hVBriwzy.mjs";import{t as d}from"./database-calls-CVsXSVhv.mjs";import{w as g,c as h}from"./classify-procedure-call-BAj0D1u2.mjs";import{a as k}from"./project-config-file-BV7RR-l6.mjs";const l=e=>{if(!(!r.isPropertyAssignment(e)&&!r.isShorthandPropertyAssignment(e)&&!r.isMethodDeclaration(e)&&!r.isGetAccessorDeclaration(e)))return k(e)},v=e=>g(e,"use","mask"),D=e=>{if(r.isPropertyAssignment(e)){const s=e.getInitializer();if(s&&r.isStringLiteral(s)){const t=s.getLiteralText();if(t==="redact"||t==="hash")return t}}return"custom"},P=e=>{const s=e.getArguments()[0];if(!s||!r.isObjectLiteralExpression(s))return[];const t=[];for(const i of s.getProperties()){const o=l(i);if(o===void 0||!r.isPropertyAssignment(i))continue;const n=i.getInitializer();if(!(!n||!r.isObjectLiteralExpression(n)))for(const a of n.getProperties()){const c=l(a);c!==void 0&&t.push({column:c,table:o})}}return t},y=e=>{const s=v(e);return{maskColumns:s.flatMap(t=>P(t)),usesMask:s.length>0}},C=new Set(["explain","findFirst","findFirstOrThrow","findMany","get","query"]),M=new Set(["delete","insert","patch","replace"]),x=(e,s)=>{if(!r.isVariableDeclaration(e))return;const t=e.getInitializer();if(!t||!r.isCallExpression(t))return;const i=h(t);if(!i)return;const o=i.receiver?y(i.receiver):{maskColumns:[],usesMask:!1},{tablesRead:n,tablesWritten:a}=d(e,C,M);return{exportName:p(e)??e.getName(),file:s,maskColumns:o.maskColumns,tablesRead:n,tablesWritten:a,usesMask:o.usesMask,visibility:i.visibility}},E=(e,s)=>{const t=[];for(const i of u(s)){const o=e.getSourceFile(i)??e.addSourceFileAtPath(i),n=f(s,i);for(const a of m(o)){const c=x(a,n);c&&t.push(c)}}return t};export{l as a,E as d,v as m,D as s};
1
+ import{Node as r}from"ts-morph";import{listLunoraSourceFiles as u,lunoraRelativePath as f}from"./isTestPath-B81lOULB.mjs";import{b as m,d as p}from"./attribution-hVBriwzy.mjs";import{t as d}from"./database-calls-BnVUlTx_.mjs";import{w as g,c as h}from"./classify-procedure-call-CcgP-9I0.mjs";import{a as k}from"./project-config-file-BV7RR-l6.mjs";const l=e=>{if(!(!r.isPropertyAssignment(e)&&!r.isShorthandPropertyAssignment(e)&&!r.isMethodDeclaration(e)&&!r.isGetAccessorDeclaration(e)))return k(e)},v=e=>g(e,"use","mask"),D=e=>{if(r.isPropertyAssignment(e)){const s=e.getInitializer();if(s&&r.isStringLiteral(s)){const t=s.getLiteralText();if(t==="redact"||t==="hash")return t}}return"custom"},P=e=>{const s=e.getArguments()[0];if(!s||!r.isObjectLiteralExpression(s))return[];const t=[];for(const i of s.getProperties()){const o=l(i);if(o===void 0||!r.isPropertyAssignment(i))continue;const n=i.getInitializer();if(!(!n||!r.isObjectLiteralExpression(n)))for(const a of n.getProperties()){const c=l(a);c!==void 0&&t.push({column:c,table:o})}}return t},y=e=>{const s=v(e);return{maskColumns:s.flatMap(t=>P(t)),usesMask:s.length>0}},C=new Set(["explain","findFirst","findFirstOrThrow","findMany","get","query"]),M=new Set(["delete","insert","patch","replace"]),x=(e,s)=>{if(!r.isVariableDeclaration(e))return;const t=e.getInitializer();if(!t||!r.isCallExpression(t))return;const i=h(t);if(!i)return;const o=i.receiver?y(i.receiver):{maskColumns:[],usesMask:!1},{tablesRead:n,tablesWritten:a}=d(e,C,M);return{exportName:p(e)??e.getName(),file:s,maskColumns:o.maskColumns,tablesRead:n,tablesWritten:a,usesMask:o.usesMask,visibility:i.visibility}},E=(e,s)=>{const t=[];for(const i of u(s)){const o=e.getSourceFile(i)??e.addSourceFileAtPath(i),n=f(s,i);for(const a of m(o)){const c=x(a,n);c&&t.push(c)}}return t};export{l as a,E as d,v as m,D as s};