@lunora/codegen 1.0.0-alpha.324 → 1.0.0-alpha.326
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.
- package/dist/index.d.mts +25 -11
- package/dist/index.d.ts +25 -11
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/DEFAULT_TARGET-BbWiB-rs.mjs +1 -0
- package/dist/packem_shared/{NOTIFY_FILENAME-bAt7J3cs.mjs → NOTIFY_FILENAME-DiYZjYts.mjs} +1 -1
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-WbrlAts0.mjs +11 -0
- package/dist/packem_shared/chain-DYBhMcDK.mjs +1 -0
- package/dist/packem_shared/classify-procedure-call-DUBO9bqm.mjs +1 -0
- package/dist/packem_shared/{context-property-calls-Cn3upNgZ.mjs → context-property-calls-eO5eiVZG.mjs} +1 -1
- package/dist/packem_shared/{context-root-BdxINX-T.mjs → context-root-D-pTjHtx.mjs} +1 -1
- package/dist/packem_shared/{database-calls-BKozZUEW.mjs → database-calls-DJgmh0Kv.mjs} +1 -1
- package/dist/packem_shared/discoverFunctions-CIJja4zp.mjs +1 -0
- package/dist/packem_shared/discoverHyperdriveCalls-DVIQ0i_e.mjs +1 -0
- package/dist/packem_shared/{discoverInserts-BjxXCACZ.mjs → discoverInserts-CednbRCq.mjs} +1 -1
- package/dist/packem_shared/discoverMaskProcedures-B4k9BS0s.mjs +1 -0
- package/dist/packem_shared/{discoverNondeterministicCalls-DvhyKM-f.mjs → discoverNondeterministicCalls-B6FUSWes.mjs} +1 -1
- package/dist/packem_shared/{discoverQueries-C8E7TeRT.mjs → discoverQueries-BezURxvr.mjs} +1 -1
- package/dist/packem_shared/discoverR2sqlCalls-B9Q6xfi6.mjs +1 -0
- package/dist/packem_shared/{discoverRlsMetadata-QRsWRQbM.mjs → discoverRlsMetadata-DCgP2H39.mjs} +1 -1
- package/dist/packem_shared/{discoverRlsProcedures-Du7ITNTQ.mjs → discoverRlsProcedures-Os1lrVX_.mjs} +1 -1
- package/dist/packem_shared/{discoverStorageRulesMetadata-ClzKLdCV.mjs → discoverStorageRulesMetadata-BTD9Vs5X.mjs} +1 -1
- package/dist/packem_shared/{emitFunctions-CuZzKaU4.mjs → emitFunctions-Cg0JxGpk.mjs} +130 -76
- package/dist/packem_shared/{emitShard-BF--3qQv.mjs → emitShard-Ba8hJ_G8.mjs} +1 -1
- package/dist/packem_shared/{exported-procedure-chains-BNBUkXui.mjs → exported-procedure-chains-DOFtzPZn.mjs} +1 -1
- package/dist/packem_shared/{index-JnqBWRYO.mjs → index-iWQbulvu.mjs} +1 -1
- package/dist/packem_shared/{shard-ceGu_Fps.mjs → shard-BtImwCVL.mjs} +95 -92
- package/package.json +9 -9
- package/dist/packem_shared/DEFAULT_TARGET-DXhxbij-.mjs +0 -1
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-CXmfa4xx.mjs +0 -11
- package/dist/packem_shared/chain-Cm6BMT8g.mjs +0 -1
- package/dist/packem_shared/classify-procedure-call-DVxdUhZt.mjs +0 -1
- package/dist/packem_shared/discoverFunctions-CZgLhsMn.mjs +0 -1
- package/dist/packem_shared/discoverHyperdriveCalls-DV4IglLE.mjs +0 -1
- package/dist/packem_shared/discoverMaskProcedures-DE-8CDen.mjs +0 -1
- package/dist/packem_shared/discoverR2sqlCalls-DVcfMO6-.mjs +0 -1
package/dist/packem_shared/{discoverRlsProcedures-Du7ITNTQ.mjs → discoverRlsProcedures-Os1lrVX_.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Node as o}from"ts-morph";import{listLunoraSourceFiles as c,lunoraRelativePath as f,findObjectProperty as u}from"./isTestPath-B81lOULB.mjs";import{b as p,d}from"./attribution-hVBriwzy.mjs";import{t as m}from"./database-calls-
|
|
1
|
+
import{Node as o}from"ts-morph";import{listLunoraSourceFiles as c,lunoraRelativePath as f,findObjectProperty as u}from"./isTestPath-B81lOULB.mjs";import{b as p,d}from"./attribution-hVBriwzy.mjs";import{t as m}from"./database-calls-DJgmh0Kv.mjs";import{c as b}from"./classify-procedure-call-DUBO9bqm.mjs";import{r as h}from"./chain-DYBhMcDK.mjs";const g=e=>{const t=e.getArguments()[0];if(!t||!o.isArrayLiteralExpression(t))return[];const r=[];for(const s of t.getElements()){if(!o.isObjectLiteralExpression(s))continue;const i=u(s,"table");if(!i||!o.isPropertyAssignment(i))continue;const n=i.getInitializer();n&&o.isStringLiteral(n)&&r.push(n.getLiteralText())}return r},y=e=>{const t=h(e);return{rlsTables:t.flatMap(r=>g(r)),usesRls:t.length>0}},v=new Set(["explain","findFirst","findFirstOrThrow","findMany","get","query"]),x=new Set(["delete","deleteMany","insert","insertMany","patch","patchIf","patchMany","replace"]),P=(e,t)=>{if(!o.isVariableDeclaration(e))return;const r=e.getInitializer();if(!r||!o.isCallExpression(r))return;const s=b(r);if(!s)return;const i=s.receiver?y(s.receiver):{rlsTables:[],usesRls:!1},{tablesRead:n,tablesWritten:a}=m(e,v,x);return{exportName:d(e)??e.getName(),file:t,rlsTables:i.rlsTables,tablesRead:n,tablesWritten:a,usesRls:i.usesRls,visibility:s.visibility}},M=(e,t)=>{const r=[];for(const s of c(t)){const i=e.getSourceFile(s)??e.addSourceFileAtPath(s),n=f(t,s);for(const a of p(i)){const l=P(a,n);l&&r.push(l)}}return r};export{M as default};
|
|
@@ -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-
|
|
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-DUBO9bqm.mjs";import{e as m}from"./exported-procedure-chains-DOFtzPZn.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,30 +1,30 @@
|
|
|
1
|
-
import{LunoraError as
|
|
1
|
+
import{LunoraError as x}from"@lunora/errors";import{L as ie,G as D,d as j,I as T,b as F,r as ce,c as le}from"./shared-DnCokNcE.mjs";import{renderAgentFunctionRegistry as ue,renderSandboxFunctionRegistry as de}from"./emitApi-CDgIPAG2.mjs";import{b as he,a as pe,r as I,c as me}from"./qualifiers-DEdXn5wP.mjs";import{s as g}from"./dispatch-namespace-DwTjD7BU.mjs";const ge=new Set(["any","bigint","boolean","date","id","null","number","storage","string","timestamp"]),U=r=>r.column!==void 0,fe=(r,t)=>{switch(r){case"bigint":return`if (typeof ${t} !== "bigint") return DEFER;
|
|
2
2
|
`;case"boolean":return`if (typeof ${t} !== "boolean") return DEFER;
|
|
3
3
|
`;case"date":case"number":case"timestamp":return`if (typeof ${t} !== "number" || !Number.isFinite(${t})) return DEFER;
|
|
4
4
|
`;case"null":return`if (${t} !== null) return DEFER;
|
|
5
5
|
`;default:return`if (typeof ${t} !== "string") return DEFER;
|
|
6
|
-
`}},
|
|
7
|
-
|
|
8
|
-
`}},
|
|
6
|
+
`}},ye=(r,t)=>r.stringMaxLength===void 0?"":`if (${t}.length > ${String(r.stringMaxLength)}) return DEFER;
|
|
7
|
+
`,$e=(r,t)=>{const n=r.literalValue?.trim();if(!(n===void 0||!ie.test(n)))return{out:t,pre:`if (${t} !== ${n}) return DEFER;
|
|
8
|
+
`}},E=(r,t,n)=>{if(!U(r)&&!(r.unmodelledRefinement||r.sourceText!==void 0)){if(ge.has(r.kind))return r.kind==="any"?{out:t,pre:""}:{out:t,pre:fe(r.kind,t)+ye(r,t)};switch(r.kind){case"array":return we(r,t,n);case"literal":return $e(r,t);case"object":return be(r,t,n);default:return}}},we=(r,t,n)=>{const{inner:o}=r;if(!o)return;const a=n.next(),i=`__arr${String(a)}`,s=`__i${String(a)}`,c=`__e${String(a)}`,d=E(o,c,n);if(!d)return;const l=`if (!Array.isArray(${t})) return DEFER;
|
|
9
9
|
const ${i} = new Array(${t}.length);
|
|
10
10
|
for (let ${s} = 0; ${s} < ${t}.length; ${s}++) {
|
|
11
|
-
const ${
|
|
12
|
-
${
|
|
11
|
+
const ${c} = ${t}[${s}];
|
|
12
|
+
${d.pre}${i}[${s}] = ${d.out};
|
|
13
13
|
}
|
|
14
|
-
`;return{out:i,pre:
|
|
15
|
-
let ${
|
|
14
|
+
`;return{out:i,pre:l}},Re=(r,t,n,o)=>{const a=JSON.stringify(r);if(t.kind==="optional"){if(t.hasRefinement||t.sourceText!==void 0||U(t))return;const{inner:s}=t;if(!s)return;const c=E(s,n,o);if(!c)return;const d=o.next(),l=`__has${String(d)}`,u=`__val${String(d)}`,f=`let ${l} = false;
|
|
15
|
+
let ${u};
|
|
16
16
|
if (${n} !== undefined) {
|
|
17
|
-
${
|
|
18
|
-
${
|
|
17
|
+
${c.pre}${u} = ${c.out};
|
|
18
|
+
${l} = true;
|
|
19
19
|
}
|
|
20
|
-
`;return{entry:`...(${
|
|
21
|
-
`,u
|
|
22
|
-
`},
|
|
23
|
-
${
|
|
24
|
-
`;return{out:s,pre:
|
|
20
|
+
`;return{entry:`...(${l} ? { ${a}: ${u} } : {})`,pre:f}}const i=E(t,n,o);if(i)return{entry:`${a}: ${i.out}`,pre:i.pre}},ke=new Set(Object.getOwnPropertyNames(Object.prototype)),J=(r,t,n)=>{let o="";const a=[];for(const i of Object.keys(r)){const s=r[i];if(!s)return;const c=JSON.stringify(i);let d=`${t}[${c}]`;if(ke.has(i)){const u=`__f${String(n.next())}`;o+=`const ${u} = Object.hasOwn(${t}, ${c}) ? ${t}[${c}] : undefined;
|
|
21
|
+
`,d=u}const l=Re(i,s,d,n);if(!l)return;o+=l.pre,a.push(l.entry)}return{entries:a.join(", "),pre:o}},B=r=>{const t=`Object.getPrototypeOf(${r})`;return`if (${t} !== Object.prototype && ${t} !== null) return DEFER;
|
|
22
|
+
`},be=(r,t,n)=>{const o=r.shape??{},a=J(o,t,n);if(!a)return;const i=n.next(),s=`__obj${String(i)}`,c=`if (typeof ${t} !== "object" || ${t} === null || Array.isArray(${t})) return DEFER;
|
|
23
|
+
${B(t)}${a.pre}const ${s} = { ${a.entries} };
|
|
24
|
+
`;return{out:s,pre:c}},q=r=>{let t=0;const o=J(r,"source",{next:()=>(t+=1,t)});if(o)return`(source) => {
|
|
25
25
|
if (typeof source !== "object" || source === null || Array.isArray(source)) return DEFER;
|
|
26
|
-
${
|
|
27
|
-
}`},
|
|
26
|
+
${B("source")}${o.pre}return { ${o.entries} };
|
|
27
|
+
}`},Ne=(r,t)=>`lunora_${g(r)}_${String(t)}`,C=r=>JSON.stringify(Object.entries(r).toSorted(([t],[n])=>t.localeCompare(n)).map(([t,n])=>{const o=n.kind==="optional",a=o?n.inner??{kind:"unknown"}:n,i=a.kind==="array"?a.inner?.kind:void 0,s=a.kind==="id"?a.tableName:void 0;return{kind:a.kind,name:t,optional:o,...s===void 0?{}:{table:s},...i===void 0||i==="unknown"?{}:{element:i}}})),H=(r,t,n,o)=>{const a=new Map,i=s=>{a.has(s)||a.set(s,Ne(s,a.size))};for(const s of r)i(s.filePath);for(const s of t)i(s.filePath);for(const s of n)i(s.filePath);for(const s of o)i(s.filePath);return a},W=(r,t,n)=>new Set([...r.map(o=>o.filePath),...t.map(o=>o.filePath),...n.map(o=>o.filePath)]),N=r=>`${r}[functionPath]`,ve=`const callRegistered = async <R>(context: CallerCtx, functionPath: string, args: Record<string, unknown> | undefined): Promise<R> => {
|
|
28
28
|
const registered = await loadFunction(functionPath);
|
|
29
29
|
|
|
30
30
|
if (!registered) {
|
|
@@ -57,29 +57,83 @@ ${J("source")}${o.pre}return { ${o.entries} };
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
return (await registered.handler(context, args ?? {})) as R;
|
|
60
|
-
};`,
|
|
61
|
-
`),
|
|
62
|
-
`),
|
|
63
|
-
`),
|
|
64
|
-
`),
|
|
65
|
-
`),y=n.map(e=>`${
|
|
66
|
-
`),v=r.filter(e=>!a||s.has(e.filePath)).map(e=>{if(e.lifecycle||Object.keys(e.args).length===0)return;const
|
|
60
|
+
};`,Oe=(r,t,n=[],o=[],a=!1)=>{const i=H(r,t,n,o),s=W(t,n,o),c=[...i.entries()].filter(([e])=>!a||s.has(e)?!0:r.some(p=>p.filePath===e&&p.channel?.kind==="room")).map(([e,p])=>{if(!T.test(e))throw new x("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(e)}`);return`import ${a&&!s.has(e)?"type ":""}* as ${p} from "../${e}.js";`}).join(`
|
|
61
|
+
`),d=r.map(e=>!a||s.has(e.filePath)?` "${g(e.filePath)}:${e.exportName}": ${i.get(e.filePath)??""}.${e.exportName} as unknown as RegisteredLunoraFunction,`:` "${g(e.filePath)}:${e.exportName}": { args: {}, handler: unloadedFunctionHandler, ...${JSON.stringify({argumentDescriptors:JSON.parse(C(e.args)),kind:e.kind,...e.channel?{channel:e.channel}:{},...e.expose?{expose:e.expose}:{},...e.lifecycle?{lifecycle:e.lifecycle}:{},...e.visibility?{visibility:e.visibility}:{},...e.x402?.price===void 0?{}:{x402:{price:e.x402.price}},...e.socket===void 0?{}:{auth:e.socket.auth,socketPath:e.socket.path}})} } satisfies RegisteredLunoraFunction & Pick<FunctionManifestEntry, "argumentDescriptors" | "channel" | "expose">,`).join(`
|
|
62
|
+
`),l=t.map(e=>` ${JSON.stringify(e.id)}: ${i.get(e.filePath)??""}.${e.exportName} as unknown as RegisteredDataMigration,`).join(`
|
|
63
|
+
`),u=n.map(e=>` "${g(e.filePath)}:${e.exportName}": ${i.get(e.filePath)??""}.${e.exportName} as unknown as RegisteredLunoraFunction,`).join(`
|
|
64
|
+
`),f=o.map(e=>` "${e.exportName}": ${i.get(e.filePath)??""}.${e.exportName} as unknown as RegisteredShape,`).join(`
|
|
65
|
+
`),y=n.map(e=>`${g(e.filePath)}:${e.exportName}`),$=[d,u].filter(e=>e.length>0).join(`
|
|
66
|
+
`),v=r.filter(e=>!a||s.has(e.filePath)).map(e=>{if(e.lifecycle||Object.keys(e.args).length===0)return;const p=q(e.args);return p===void 0?void 0:`installCompiledValidatorMap(${i.get(e.filePath)??""}.${e.exportName}.args, ${p});`}).filter(e=>e!==void 0).join(`
|
|
67
67
|
`),O=r.filter(e=>e.channel?.kind==="room").map(e=>` ${JSON.stringify(e.channel?.name??"")}: RoomMessageOf<typeof ${i.get(e.filePath)??""}[${JSON.stringify(e.exportName)}]>;`).join(`
|
|
68
|
-
`),
|
|
69
|
-
`):"",h=[...new Set(
|
|
68
|
+
`),k=[...r.map(e=>({args:e.args,definition:e,path:`${g(e.filePath)}:${e.exportName}`})),...n.map(e=>({args:e.args,definition:{...e,expose:void 0,kind:"mutation",lifecycle:void 0,visibility:void 0,x402:void 0},path:`${g(e.filePath)}:${e.exportName}`}))],S=a?k.filter(({definition:e})=>!s.has(e.filePath)):[];for(const{definition:e}of k)if(a&&e.x402&&e.x402.price===void 0)throw new x("INTERNAL",`@lunora/codegen: lazy function registry needs a literal \`.x402({ price })\` value in ${e.filePath}:${e.exportName}`);const b=a?S.map(({definition:e,path:p})=>{const R=i.get(e.filePath)??"",P="channel"in e?e.channel:void 0,L={argumentDescriptors:JSON.parse(C(e.args)),exportName:e.exportName,kind:e.kind,moduleId:R,...P?{channel:P}:{},...e.expose?{expose:e.expose}:{},...e.lifecycle?{lifecycle:e.lifecycle}:{},...e.visibility?{visibility:e.visibility}:{},...e.x402?.price===void 0?{}:{x402:{price:e.x402.price}}};return` ${JSON.stringify(p)}: ${JSON.stringify(L)},`}).join(`
|
|
69
|
+
`):"",h=[...new Set(S.map(({definition:e})=>e.filePath))],w=a?h.map(e=>{if(!T.test(e))throw new x("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(e)}`);const p=i.get(e)??"";return` ${JSON.stringify(p)}: () => import(${JSON.stringify(`./fn/${p}.js`)}),`}).join(`
|
|
70
70
|
`):"";return{dispatchBody:$.length>0?`
|
|
71
71
|
${$}
|
|
72
|
-
`:"",importBlock:
|
|
72
|
+
`:"",importBlock:c.length>0?`${c}
|
|
73
73
|
|
|
74
|
-
`:"",installBlock:v,manifestBody:
|
|
75
|
-
${
|
|
76
|
-
`:"",migrationBody:
|
|
77
|
-
${
|
|
74
|
+
`:"",installBlock:v,manifestBody:b.length>0?`
|
|
75
|
+
${b}
|
|
76
|
+
`:"",migrationBody:l.length>0?`
|
|
77
|
+
${l}
|
|
78
78
|
`:"",moduleLoaders:w.length>0?`
|
|
79
79
|
${w}
|
|
80
|
-
`:"",mutatorPaths:y,roomMessagesBody:O,shapeBody:
|
|
81
|
-
${
|
|
82
|
-
`:""}},
|
|
80
|
+
`:"",mutatorPaths:y,roomMessagesBody:O,shapeBody:f.length>0?`
|
|
81
|
+
${f}
|
|
82
|
+
`:""}},Se=r=>{const t=F(r,o=>{const a=I(ce(o.args),o.filePath),i=a==="{}"?"?":"",s=I(me(o),o.filePath);return o.kind==="stream"?`${o.exportName}: (args${i}: ${a}) => Promise<AsyncIterable<${s}>>;`:`${o.exportName}: (args${i}: ${a}) => Promise<${s}>;`},"type");return{implementation:F(r,o=>`${le(o.exportName)}: (args) => callRegistered(context, "${g(o.filePath)}:${o.exportName}", args),`,"value"),types:t}},xe=r=>{const t={connect:[],disconnect:[],init:[],reactor:[],whisper:[]};for(const n of r)!n.lifecycle||n.lifecycle==="socket"||t[n.lifecycle].push(`${g(n.filePath)}:${n.exportName}`);return t},Pe=r=>{const t=new Map,n=[];for(const o of r){if(o.lifecycle!=="socket"||o.socket===void 0)continue;const{auth:a,origin:i,path:s}=o.socket,c=`${g(o.filePath)}:${o.exportName}`,d=t.get(s);if(!(d?.origin!==void 0&&d.origin===i)){if(d!==void 0)throw new x("DUPLICATE_SOCKET_PATH",`two defineWebSocket routes serve "${s}" (${d.functionPath} and ${c}); socket paths must be unique.`);t.set(s,{functionPath:c,origin:i}),n.push(` ${JSON.stringify(s)}: { auth: ${String(a)}, functionPath: ${JSON.stringify(c)} },`)}}return`
|
|
83
|
+
/**
|
|
84
|
+
* Socket registry: the URL path of each \`defineWebSocket\` route → its function path + auth requirement.
|
|
85
|
+
* Static, so building the worker never evaluates a route's module. The generated ShardDO's \`socketRoute\` override
|
|
86
|
+
* resolves an upgraded socket through this map.
|
|
87
|
+
*/
|
|
88
|
+
export const LUNORA_SOCKETS: Readonly<Record<string, { auth: boolean; functionPath: string }>> = {
|
|
89
|
+
${n.join(`
|
|
90
|
+
`)}
|
|
91
|
+
};
|
|
92
|
+
`},Le=(r,t)=>{const n=r.some(c=>c.lifecycle==="socket"),a=n&&t?Pe(r):n&&!t?`
|
|
93
|
+
/**
|
|
94
|
+
* Socket registry: the URL path of each \`defineWebSocket\` route → its function
|
|
95
|
+
* path + auth requirement. The generated ShardDO's \`socketRoute\` override
|
|
96
|
+
* resolves an upgraded socket through this map so a route's typed
|
|
97
|
+
* \`onOpen\`/\`onMessage\`/\`onClose\` dispatch server-side under the socket's
|
|
98
|
+
* verified identity. Two routes on one path throw at module load rather than letting
|
|
99
|
+
* the map silently keep whichever came last.
|
|
100
|
+
*/
|
|
101
|
+
export const LUNORA_SOCKETS: Readonly<Record<string, { auth: boolean; functionPath: string }>> = (() => {
|
|
102
|
+
const registry: Record<string, { auth: boolean; functionPath: string }> = {};
|
|
103
|
+
const owners = new Map<string, unknown>();
|
|
104
|
+
|
|
105
|
+
for (const [path, fn] of Object.entries(LUNORA_FUNCTIONS)) {
|
|
106
|
+
if (fn.lifecycle !== "socket" || typeof fn.socketPath !== "string") {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const owner = owners.get(fn.socketPath);
|
|
111
|
+
|
|
112
|
+
// The same registration exported under two names (an alias) is one route.
|
|
113
|
+
if (owner !== undefined && owner !== fn) {
|
|
114
|
+
throw new Error(\`two defineWebSocket routes serve "\${fn.socketPath}"; socket paths must be unique\`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (owner === undefined) {
|
|
118
|
+
owners.set(fn.socketPath, fn);
|
|
119
|
+
registry[fn.socketPath] = { auth: fn.auth === true, functionPath: path };
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return registry;
|
|
124
|
+
})();
|
|
125
|
+
`:"";return{fields:n?`
|
|
126
|
+
/**
|
|
127
|
+
* Set on a \`defineWebSocket\` registration: the URL path the route serves.
|
|
128
|
+
* The generated \`LUNORA_SOCKETS\` map keys it on this path so the ShardDO
|
|
129
|
+
* resolves an upgraded socket to this registration.
|
|
130
|
+
*/
|
|
131
|
+
socketPath?: string;
|
|
132
|
+
/**
|
|
133
|
+
* Set on a \`defineWebSocket\` registration: whether the route refuses an
|
|
134
|
+
* anonymous upgrade. Read into \`LUNORA_SOCKETS\` alongside \`socketPath\`.
|
|
135
|
+
*/
|
|
136
|
+
auth?: boolean;`:"",lifecycleMember:n?' | "socket"':"",registry:a}},Ae=(r,t,n)=>r?{channelField:` /**
|
|
83
137
|
* Set on a \`defineRoom\` registration: the room's name (without the \`room:\`
|
|
84
138
|
* topic prefix). The generated \`LUNORA_ROOMS\` map keys it on the room's
|
|
85
139
|
* \`room:<name>\` whisper topic so the ShardDO resolves a room topic to this
|
|
@@ -94,7 +148,7 @@ export type LunoraRoomMessages = {
|
|
|
94
148
|
${n}
|
|
95
149
|
};
|
|
96
150
|
`,typeImport:`import type { RoomMessageOf } from "${t}";
|
|
97
|
-
`}:{channelField:"",messagesBlock:"",typeImport:""},
|
|
151
|
+
`}:{channelField:"",messagesBlock:"",typeImport:""},Te=(r,t,n)=>r?t?`
|
|
98
152
|
/**
|
|
99
153
|
* Room routes are static metadata so building the worker never evaluates user handlers.
|
|
100
154
|
*/
|
|
@@ -103,7 +157,7 @@ export const LUNORA_ROOMS: Readonly<Record<string, string>> = (() => {
|
|
|
103
157
|
const owners = new Map<string, string>();
|
|
104
158
|
|
|
105
159
|
for (const { owner, path, topic } of [
|
|
106
|
-
${n.filter(o=>o.channel?.kind==="room").map(o=>` { owner: ${JSON.stringify(o.filePath)}, path: ${JSON.stringify(`${
|
|
160
|
+
${n.filter(o=>o.channel?.kind==="room").map(o=>` { owner: ${JSON.stringify(o.filePath)}, path: ${JSON.stringify(`${g(o.filePath)}:${o.exportName}`)}, topic: ${JSON.stringify(`room:${o.channel?.name??""}`)} },`).join(`
|
|
107
161
|
`)}
|
|
108
162
|
]) {
|
|
109
163
|
const prior = owners.get(topic);
|
|
@@ -154,54 +208,54 @@ export const LUNORA_ROOMS: Readonly<Record<string, string>> = (() => {
|
|
|
154
208
|
|
|
155
209
|
return registry;
|
|
156
210
|
})();
|
|
157
|
-
`:"",
|
|
211
|
+
`:"",Ee=(r,t)=>{const n=Se(r),o=n.types?`
|
|
158
212
|
${n.types}
|
|
159
213
|
`:"",a=n.implementation?`
|
|
160
214
|
${n.implementation}
|
|
161
|
-
`:"",i=
|
|
162
|
-
`:"",
|
|
215
|
+
`:"",i=pe(n.types),s=i.length>0?`import type { ${i.join(", ")} } from "./dataModel.js";
|
|
216
|
+
`:"",c=r.length>0?"context":"_context";let d="";if(r.length>0){let l=ve;t||(l=l.replace("await loadFunction(functionPath)",N("LUNORA_FUNCTIONS"))),d=`${l}
|
|
163
217
|
|
|
164
|
-
`}return{callRegisteredHelper:
|
|
165
|
-
`);let
|
|
218
|
+
`}return{callRegisteredHelper:d,dataModelImport:s,implementation:a,parameter:c,types:o}},De=r=>{const{agents:t=[],functions:n,lazyFunctions:o=!1,migrations:a=[],mutators:i=[],shapes:s=[],useUmbrella:c=!1,usesSandbox:d=!1}=r,l=j(c),{dispatchBody:u,importBlock:f,installBlock:y,manifestBody:$,migrationBody:v,moduleLoaders:O,mutatorPaths:k,roomMessagesBody:S,shapeBody:b}=Oe(n,a,i,s,o),h=ue(t,n),w=de(d,n),e=[h.lines,w.lines].filter(m=>m.length>0).join(`
|
|
219
|
+
`);let p=u;e.length>0&&(p=u.length>0?`${u.trimEnd()}
|
|
166
220
|
${e}
|
|
167
221
|
`:`
|
|
168
222
|
${e}
|
|
169
|
-
`);const R=
|
|
223
|
+
`);const R=xe(n),P=o?"await loadFunction(functionPath)":N("LUNORA_FUNCTIONS"),L=o?` if (${N("LUNORA_FUNCTION_MANIFEST")}?.visibility === "internal") {
|
|
170
224
|
throw new LunoraError("FUNCTION_NOT_FOUND", \`function not registered: \${functionPath}\`);
|
|
171
225
|
}
|
|
172
226
|
|
|
173
|
-
`:"",z=s.length>0?`import type { RegisteredShape } from "${
|
|
174
|
-
`:"",
|
|
227
|
+
`:"",z=s.length>0?`import type { RegisteredShape } from "${l.server}";
|
|
228
|
+
`:"",M=n.some(m=>m.channel?.kind==="room"),A=Ae(M,l.server,S),Q=s.length>0?`
|
|
175
229
|
/**
|
|
176
230
|
* Replication-shape registry — one entry per \`defineShape\` in \`lunora/shapes.ts\`.
|
|
177
231
|
* The generated ShardDO's \`resolveShape\` override looks a shape up by name and
|
|
178
232
|
* evaluates its trusted \`compileWhere(ctx, args)\` to authorize + scope a
|
|
179
233
|
* \`shape_subscribe\` (reads-as-permissions).
|
|
180
234
|
*/
|
|
181
|
-
export const LUNORA_SHAPES: Record<string, RegisteredShape> = {${
|
|
182
|
-
`:"",G=
|
|
235
|
+
export const LUNORA_SHAPES: Record<string, RegisteredShape> = {${b}};
|
|
236
|
+
`:"",G=k.length>0?`
|
|
183
237
|
/**
|
|
184
238
|
* Custom-mutator function paths — the \`LUNORA_FUNCTIONS\` keys the generated
|
|
185
239
|
* ShardDO's \`isCustomMutator\` override routes through the client-watermark push
|
|
186
240
|
* protocol (\`x-lunora-client-id\`/\`x-lunora-client-seq\` ordering).
|
|
187
241
|
*/
|
|
188
|
-
export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${
|
|
189
|
-
`:"",V=
|
|
190
|
-
`:"",
|
|
242
|
+
export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${k.map(m=>JSON.stringify(m)).join(", ")}]);
|
|
243
|
+
`:"",V=Te(M,o,n),{fields:K,lifecycleMember:_,registry:Y}=Le(n,o),Z=y.length>0?`import { DEFER_VALIDATION as DEFER, installCompiledValidatorMap } from "${l.values}";
|
|
244
|
+
`:"",X=y.length>0?`
|
|
191
245
|
/**
|
|
192
246
|
* AOT-compiled argument validators (Worker-safe, no \`eval\`). Each is installed
|
|
193
247
|
* onto its function's live \`.args\` object and consulted by the interpreted
|
|
194
248
|
* parser as a zero-allocation fast path; anything it can't model is deferred.
|
|
195
249
|
*/
|
|
196
250
|
${y}
|
|
197
|
-
`:"",
|
|
251
|
+
`:"",ee=Ee(n,o),{callRegisteredHelper:te,dataModelImport:re,implementation:ne,parameter:oe,types:se}=ee,ae=o?`
|
|
198
252
|
export interface FunctionManifestEntry {
|
|
199
253
|
argumentDescriptors: ReadonlyArray<{ element?: string; kind: string; name: string; optional: boolean; table?: string }>;
|
|
200
254
|
channel?: { kind: "room"; name: string };
|
|
201
255
|
exportName: string;
|
|
202
256
|
expose?: { cache?: { credentialHeaders?: ReadonlyArray<string>; maxAge?: number; scope?: "private" | "public"; staleWhileRevalidate?: number; tag?: string; vary?: string }; rest?: boolean };
|
|
203
257
|
kind: "action" | "mutation" | "query" | "stream";
|
|
204
|
-
lifecycle?: "connect" | "disconnect" | "init" | "reactor" | "whisper";
|
|
258
|
+
lifecycle?: "connect" | "disconnect" | "init" | "reactor" | "whisper"${_};
|
|
205
259
|
moduleId: string;
|
|
206
260
|
visibility?: "internal" | "public";
|
|
207
261
|
x402?: { readonly price: number | string };
|
|
@@ -220,8 +274,8 @@ const unloadedFunctionHandler = (): never => {
|
|
|
220
274
|
|
|
221
275
|
/** Reuse an evaluated module synchronously, so dispatch does not yield after restoring request scope. */
|
|
222
276
|
export const getLoadedFunction = (functionPath: string): RegisteredLunoraFunction | undefined => {
|
|
223
|
-
const registered = ${
|
|
224
|
-
const manifest = ${
|
|
277
|
+
const registered = ${N("LUNORA_FUNCTIONS")};
|
|
278
|
+
const manifest = ${N("LUNORA_FUNCTION_MANIFEST")};
|
|
225
279
|
|
|
226
280
|
if (!registered || !manifest) {
|
|
227
281
|
return registered;
|
|
@@ -252,7 +306,7 @@ export const getLoadedFunction = (functionPath: string): RegisteredLunoraFunctio
|
|
|
252
306
|
/** Load one function's owning module once per isolate, then merge its live builder result into the registry entry. */
|
|
253
307
|
export const loadFunction = async (functionPath: string): Promise<RegisteredLunoraFunction | undefined> => {
|
|
254
308
|
const registered = getLoadedFunction(functionPath);
|
|
255
|
-
const manifest = ${
|
|
309
|
+
const manifest = ${N("LUNORA_FUNCTION_MANIFEST")};
|
|
256
310
|
|
|
257
311
|
if (registered || !manifest) {
|
|
258
312
|
return registered;
|
|
@@ -278,9 +332,9 @@ export const loadFunction = async (functionPath: string): Promise<RegisteredLuno
|
|
|
278
332
|
|
|
279
333
|
return getLoadedFunction(functionPath);
|
|
280
334
|
};
|
|
281
|
-
`:"";return
|
|
335
|
+
`:"";return he(`${D}${f}${h.importLine}${w.importLine}${Z}${z}${A.typeImport}import { LunoraError } from "${l.server}";
|
|
282
336
|
import type { ActionCtx, MutationCtx, QueryCtx } from "./server.js";
|
|
283
|
-
${
|
|
337
|
+
${re}
|
|
284
338
|
/**
|
|
285
339
|
* Single registered function, narrowed to the shape \`handleRpc\` needs.
|
|
286
340
|
* The real argument validators / return types are checked elsewhere — at
|
|
@@ -309,8 +363,8 @@ export interface RegisteredLunoraFunction {
|
|
|
309
363
|
* \`init\` and \`reactor\` have no caller identity, so RLS has no user to scope
|
|
310
364
|
* to. \`whisper\` does have one — it runs under the asking socket's identity.
|
|
311
365
|
*/
|
|
312
|
-
lifecycle?: "connect" | "disconnect" | "init" | "reactor" | "whisper"
|
|
313
|
-
${
|
|
366
|
+
lifecycle?: "connect" | "disconnect" | "init" | "reactor" | "whisper"${_};${K}
|
|
367
|
+
${A.channelField} /**
|
|
314
368
|
* Hoisted by the builder when the \`.use()\` chain carries a step with a
|
|
315
369
|
* per-dispatch effect — \`rateLimit(...)\` consuming budget, a single-use
|
|
316
370
|
* captcha token being burned. Read by \`isCacheableQuery\`: the chain runs
|
|
@@ -326,13 +380,13 @@ ${L.channelField} /**
|
|
|
326
380
|
*/
|
|
327
381
|
x402?: { readonly price: number | string };
|
|
328
382
|
}
|
|
329
|
-
${h.prelude}${w.prelude}${
|
|
383
|
+
${h.prelude}${w.prelude}${ae}
|
|
330
384
|
/**
|
|
331
385
|
* Static dispatch table. The key matches the \`__lunoraRef\` the client
|
|
332
386
|
* emits (\`api[namespace][fn].__lunoraRef === "namespace:fn"\`).
|
|
333
387
|
*/
|
|
334
|
-
export const LUNORA_FUNCTIONS: Record<string, RegisteredLunoraFunction> = {${
|
|
335
|
-
${
|
|
388
|
+
export const LUNORA_FUNCTIONS: Record<string, RegisteredLunoraFunction> = {${p}};
|
|
389
|
+
${X}${Q}${G}${V}${A.messagesBlock}${Y}
|
|
336
390
|
/**
|
|
337
391
|
* Lifecycle manifest: the function paths the generated ShardDO dispatches when a
|
|
338
392
|
* client's WebSocket connects (\`connect\`) or disconnects (\`disconnect\`), once
|
|
@@ -350,11 +404,11 @@ export const LUNORA_LIFECYCLE_HOOKS: {
|
|
|
350
404
|
reactor: readonly string[];
|
|
351
405
|
whisper: readonly string[];
|
|
352
406
|
} = {
|
|
353
|
-
connect: [${R.connect.map(
|
|
354
|
-
disconnect: [${R.disconnect.map(
|
|
355
|
-
init: [${R.init.map(
|
|
356
|
-
reactor: [${R.reactor.map(
|
|
357
|
-
whisper: [${R.whisper.map(
|
|
407
|
+
connect: [${R.connect.map(m=>JSON.stringify(m)).join(", ")}],
|
|
408
|
+
disconnect: [${R.disconnect.map(m=>JSON.stringify(m)).join(", ")}],
|
|
409
|
+
init: [${R.init.map(m=>JSON.stringify(m)).join(", ")}],
|
|
410
|
+
reactor: [${R.reactor.map(m=>JSON.stringify(m)).join(", ")}],
|
|
411
|
+
whisper: [${R.whisper.map(m=>JSON.stringify(m)).join(", ")}],
|
|
358
412
|
};
|
|
359
413
|
|
|
360
414
|
/**
|
|
@@ -364,7 +418,7 @@ export const LUNORA_LIFECYCLE_HOOKS: {
|
|
|
364
418
|
* functions are treated as not-found so their existence never leaks to clients.
|
|
365
419
|
*/
|
|
366
420
|
export const dispatchLunoraFunction = async (functionPath: string, context: unknown, args: Record<string, unknown>): Promise<unknown> => {
|
|
367
|
-
${
|
|
421
|
+
${L} const registered = ${P};
|
|
368
422
|
|
|
369
423
|
if (!registered || registered.visibility === "internal") {
|
|
370
424
|
throw new LunoraError("FUNCTION_NOT_FOUND", \`function not registered: \${functionPath}\`);
|
|
@@ -385,10 +439,10 @@ export type CallerCtx = ActionCtx | MutationCtx | QueryCtx;
|
|
|
385
439
|
* with the supplied \`context\`, exactly like \`ctx.runQuery\`/\`runMutation\`/
|
|
386
440
|
* \`runAction\` but without re-stating the function path.
|
|
387
441
|
*/
|
|
388
|
-
export interface Caller {${
|
|
442
|
+
export interface Caller {${se}}
|
|
389
443
|
|
|
390
|
-
${
|
|
391
|
-
export const createCaller = (${
|
|
444
|
+
${te}/** Build a {@link Caller} bound to \`context\` (typically a handler's \`ctx\`). */
|
|
445
|
+
export const createCaller = (${oe}: CallerCtx): Caller => ({${ne}});
|
|
392
446
|
|
|
393
447
|
/**
|
|
394
448
|
* Single registered data migration, narrowed to the shape the per-shard runner
|
|
@@ -408,12 +462,12 @@ export interface RegisteredDataMigration {
|
|
|
408
462
|
* shard DO's admin RPC and the CLI resolve migrations to run through this map.
|
|
409
463
|
*/
|
|
410
464
|
export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${v}};
|
|
411
|
-
`,
|
|
412
|
-
`:"",O=$.length>0?`import * as ${
|
|
413
|
-
`:"",
|
|
465
|
+
`,c)},je="fn",Ue=r=>{if(r.lazyFunctions!==!0)return{};const{functions:t}=r,n=r.migrations??[],o=r.mutators??[],a=r.shapes??[],i=H(t,n,o,a),s=W(n,o,a),c=[...new Set(t.filter(u=>!s.has(u.filePath)).map(u=>u.filePath))],d=j(r.useUmbrella??!1),l={};for(const u of c){if(!T.test(u))throw new x("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(u)}`);const f=i.get(u)??"",y=`../../${u}.js`,$=t.filter(h=>h.filePath===u&&!h.lifecycle&&Object.keys(h.args).length>0).flatMap(h=>{const w=q(h.args);return w===void 0?[]:[`installCompiledValidatorMap(${f}.${h.exportName}.args, ${w});`]}),v=$.length>0?`import { DEFER_VALIDATION as DEFER, installCompiledValidatorMap } from "${d.values}";
|
|
466
|
+
`:"",O=$.length>0?`import * as ${f} from "${y}";
|
|
467
|
+
`:"",k=$.length>0?`
|
|
414
468
|
/** Install the precompiled argument parsers before the module is dispatched. */
|
|
415
469
|
${$.join(`
|
|
416
470
|
`)}
|
|
417
|
-
`:"",
|
|
418
|
-
`:"";
|
|
419
|
-
${
|
|
471
|
+
`:"",b=t.some(h=>h.filePath===u&&h.exportName==="default")||n.some(h=>h.filePath===u&&h.exportName==="default")?`export { default } from "${y}";
|
|
472
|
+
`:"";l[`${f}.ts`]=`${D}${v}${O}${k}export * from "${y}";
|
|
473
|
+
${b}`}return l};export{je as LAZY_FUNCTION_DIRECTORY,De as emitFunctions,Ue as emitLazyFunctionModules};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import"./isD1GlobalTable-udvHAAzD.mjs";import"./json-data-Chfs2Cz5.mjs";import{e as d}from"./shard-
|
|
1
|
+
import"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import"./isD1GlobalTable-udvHAAzD.mjs";import"./json-data-Chfs2Cz5.mjs";import{e as d}from"./shard-BtImwCVL.mjs";import"./shard-runtime-BpoCV-aM.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-
|
|
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-DUBO9bqm.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-
|
|
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-DJgmh0Kv.mjs";import{w as g,c as h}from"./classify-procedure-call-DUBO9bqm.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};
|