@lunora/codegen 1.0.0-alpha.164 → 1.0.0-alpha.165
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 +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{GENERATED_HEADER-zxE5ds4T.mjs → GENERATED_HEADER-CR0AOQsV.mjs} +1 -1
- package/dist/packem_shared/{OPENRPC_VERSION-BgLkvCYK.mjs → OPENRPC_VERSION-DlF2XS7T.mjs} +1 -1
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-CSgeeyQD.mjs +9 -0
- package/dist/packem_shared/{buildOpenApiDocument-qYjkmRTX.mjs → buildOpenApiDocument-CE9SDrBg.mjs} +1 -1
- package/dist/packem_shared/{emit-BNdsZPcd.mjs → emit-Lx7UkoGn.mjs} +195 -186
- package/dist/packem_shared/{emitApp-CxmA4W3C.mjs → emitApp-9dMkNu6n.mjs} +47 -27
- package/package.json +9 -9
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-C9nFNiHX.mjs +0 -9
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
import{agentComponent as
|
|
1
|
+
import{agentComponent as ht}from"@lunora/agent/component";import{LunoraError as X}from"@lunora/errors";import{serializeSchemaSnapshot as $n,hashSchemaSnapshot as Tn}from"./SCHEMA_SNAPSHOT_VERSION-CWESEYLi.mjs";import{s as T}from"./paths-C-9fwEgQ.mjs";const mt=[{contextProperty:"access",key:"access",moduleSpecifier:"@lunora/cloudflare-access",requiredPackage:"@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",requiredPackage:"@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",requiredPackage:"@lunora/bindings",serverCtxField:{field:`
|
|
2
2
|
/** Analytics Engine telemetry sink. Fire-and-forget and sampled; do not read it back in-handler. */
|
|
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:`
|
|
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",requiredPackage:"@lunora/browser",serverCtxField:{field:`
|
|
4
4
|
/** Browser Rendering (screenshots/PDF/scrape). Non-deterministic — available only in actions. */
|
|
5
|
-
readonly browser: import("@lunora/browser").Browser;`,tier:"action"}},{contextProperty:"containers",key:"container",moduleSpecifier:"@lunora/container"},{contextProperty:"flags",key:"flags",moduleSpecifier:"@lunora/flags"},{appMethod:{configKey:"sql",doc:"Wire the Hyperdrive SQL client backing `ctx.sql` — build it with `createHyperdrive` + `fromPostgresJs`/`fromNodePg`/`fromMysql2`.",method:"hyperdrive"},contextProperty:"sql",key:"hyperdrive",moduleSpecifier:"@lunora/hyperdrive",serverCtxField:{field:`
|
|
5
|
+
readonly browser: import("@lunora/browser").Browser;`,tier:"action"}},{contextProperty:"containers",key:"container",moduleSpecifier:"@lunora/container"},{contextProperty:"flags",key:"flags",moduleSpecifier:"@lunora/flags"},{appMethod:{configKey:"sql",doc:"Wire the Hyperdrive SQL client backing `ctx.sql` — build it with `createHyperdrive` + `fromPostgresJs`/`fromNodePg`/`fromMysql2`.",method:"hyperdrive"},contextProperty:"sql",key:"hyperdrive",moduleSpecifier:"@lunora/hyperdrive",requiredPackage:"@lunora/hyperdrive",serverCtxField:{field:`
|
|
6
6
|
/**
|
|
7
7
|
* External database access via Hyperdrive. Non-deterministic — available only in actions. Writes here are NOT tracked by Lunora live queries; subscriptions will not re-run on external DB changes.
|
|
8
8
|
*/
|
|
9
|
-
readonly sql: import("@lunora/hyperdrive").SqlClient;`,tier:"action"}},{appMethod:{configKey:"images",doc:"Override the Images binding backing `ctx.images` (defaults to `env.IMAGES`).",method:"images"},contextProperty:"images",key:"images",moduleSpecifier:"@lunora/bindings/images",serverCtxField:{field:`
|
|
9
|
+
readonly sql: import("@lunora/hyperdrive").SqlClient;`,tier:"action"}},{appMethod:{configKey:"images",doc:"Override the Images binding backing `ctx.images` (defaults to `env.IMAGES`).",method:"images"},contextProperty:"images",key:"images",moduleSpecifier:"@lunora/bindings/images",requiredPackage:"@lunora/bindings",serverCtxField:{field:`
|
|
10
10
|
/** Cloudflare Images transforms (resize/format/optimize). Non-deterministic — available only in actions. */
|
|
11
|
-
readonly images: import("@lunora/bindings/images").Images;`,tier:"action"}},{appMethod:{configKey:"kv",doc:"Override the Workers KV binding backing `ctx.kv` (defaults to `env.KV`).",method:"kv"},contextProperty:"kv",key:"kv",moduleSpecifier:"@lunora/bindings/kv",serverCtxField:{field:`
|
|
12
|
-
readonly kv: import("@lunora/bindings/kv").Kv;`,tier:"every"}},{key:"mail",moduleSpecifier:"@lunora/mail"},{contextProperty:"notify",key:"notify",moduleSpecifier:"@lunora/notify"},{appMethod:{configKey:"payment",doc:"Wire the payment options backing `ctx.payments`.",method:"payment"},contextProperty:"payments",key:"payments",moduleSpecifier:"@lunora/payment"},{appMethod:{configKey:"x402",doc:"Wire the x402 agent-wallet pay rail backing `ctx.x402` — a payment-enabled `fetch` that answers `402` challenges under a mandatory spend policy (ActionCtx-only; spends real funds).",method:"x402"},contextProperty:"x402",key:"x402",moduleSpecifier:"@lunora/x402/pay"},{contextProperty:"pipelines",key:"pipelines",moduleSpecifier:"@lunora/bindings/pipelines",serverCtxField:{field:`
|
|
11
|
+
readonly images: import("@lunora/bindings/images").Images;`,tier:"action"}},{appMethod:{configKey:"kv",doc:"Override the Workers KV binding backing `ctx.kv` (defaults to `env.KV`).",method:"kv"},contextProperty:"kv",key:"kv",moduleSpecifier:"@lunora/bindings/kv",requiredPackage:"@lunora/bindings",serverCtxField:{field:`
|
|
12
|
+
readonly kv: import("@lunora/bindings/kv").Kv;`,tier:"every"}},{key:"mail",moduleSpecifier:"@lunora/mail"},{contextProperty:"notify",key:"notify",moduleSpecifier:"@lunora/notify"},{appMethod:{configKey:"payment",doc:"Wire the payment options backing `ctx.payments`.",method:"payment"},contextProperty:"payments",key:"payments",moduleSpecifier:"@lunora/payment",requiredPackage:"@lunora/payment"},{appMethod:{configKey:"x402",doc:"Wire the x402 agent-wallet pay rail backing `ctx.x402` — a payment-enabled `fetch` that answers `402` challenges under a mandatory spend policy (ActionCtx-only; spends real funds).",method:"x402"},contextProperty:"x402",key:"x402",moduleSpecifier:"@lunora/x402/pay",requiredPackage:"@lunora/x402"},{contextProperty:"pipelines",key:"pipelines",moduleSpecifier:"@lunora/bindings/pipelines",requiredPackage:"@lunora/bindings",serverCtxField:{field:`
|
|
13
13
|
/** Pipelines ingestion sink (durable, R2-backed). Fire-and-forget and batched; do not read it back in-handler. */
|
|
14
|
-
readonly pipelines: import("@lunora/bindings/pipelines").PipelineClient;`,tier:"action"}},{appMethod:{configKey:"r2sql",doc:"Wire the R2 SQL client backing `ctx.r2sql` — build it with `createR2Sql({ accountId, apiToken, bucket })` (defaults to env `R2_SQL_TOKEN` / `R2_SQL_ACCOUNT_ID` / `R2_SQL_BUCKET`).",method:"r2sql"},contextProperty:"r2sql",key:"r2sql",moduleSpecifier:"@lunora/bindings/r2sql",serverCtxField:{field:`
|
|
14
|
+
readonly pipelines: import("@lunora/bindings/pipelines").PipelineClient;`,tier:"action"}},{appMethod:{configKey:"r2sql",doc:"Wire the R2 SQL client backing `ctx.r2sql` — build it with `createR2Sql({ accountId, apiToken, bucket })` (defaults to env `R2_SQL_TOKEN` / `R2_SQL_ACCOUNT_ID` / `R2_SQL_BUCKET`).",method:"r2sql"},contextProperty:"r2sql",key:"r2sql",moduleSpecifier:"@lunora/bindings/r2sql",requiredPackage:"@lunora/bindings",serverCtxField:{field:`
|
|
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"}],
|
|
18
|
+
readonly r2sql: import("@lunora/bindings/r2sql").R2SqlClient;`,tier:"action"}},{contextProperty:"scheduler",key:"scheduler",moduleSpecifier:"@lunora/scheduler"},{contextProperty:"storage",key:"storage",moduleSpecifier:"@lunora/storage"},{appMethod:{configKey:"vectors",doc:"Wire the Vectorize index map backing `ctx.vectors`.",method:"vectors"},contextProperty:"vectors",key:"vectors",moduleSpecifier:"@lunora/bindings/vectors"},{contextProperty:"workflows",key:"workflows",moduleSpecifier:"@lunora/workflow"}],Nn=mt,An=new Map(Nn.flatMap(e=>e.serverCtxField?[[e.key,e.serverCtxField]]:[])),oo=mt.flatMap(e=>"appMethod"in e?[{appMethod:e.appMethod,key:e.key}]:[]),gt=/^(?:"(?:[^"\\]|\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4}))*"|'[^'\\]*'|-?\d+(?:\.\d+)?|true|false|null)$/u,On=new Set(["any","bigint","boolean","date","id","null","number","storage","string","timestamp"]),ft=e=>e.column!==void 0,In=(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
|
-
`}},
|
|
24
|
-
`,
|
|
25
|
-
`}},Ge=(e,t,n)=>{if(!
|
|
23
|
+
`}},Cn=(e,t)=>e.stringMaxLength===void 0?"":`if (${t}.length > ${String(e.stringMaxLength)}) return DEFER;
|
|
24
|
+
`,Ln=(e,t)=>{const n=e.literalValue?.trim();if(!(n===void 0||!gt.test(n)))return{out:t,pre:`if (${t} !== ${n}) return DEFER;
|
|
25
|
+
`}},Ge=(e,t,n)=>{if(!ft(e)&&!(e.unmodelledRefinement||e.sourceText!==void 0)){if(On.has(e.kind))return e.kind==="any"?{out:t,pre:""}:{out:t,pre:In(e.kind,t)+Cn(e,t)};switch(e.kind){case"array":return En(e,t,n);case"literal":return Ln(e,t);case"object":return Pn(e,t,n);default:return}}},En=(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=Ge(r,a,n);if(!c)return;const d=`if (!Array.isArray(${t})) return DEFER;
|
|
26
26
|
const ${s} = new Array(${t}.length);
|
|
27
27
|
for (let ${i} = 0; ${i} < ${t}.length; ${i}++) {
|
|
28
28
|
const ${a} = ${t}[${i}];
|
|
29
29
|
${c.pre}${s}[${i}] = ${c.out};
|
|
30
30
|
}
|
|
31
|
-
`;return{out:s,pre:d}},
|
|
32
|
-
let ${
|
|
31
|
+
`;return{out:s,pre:d}},Dn=(e,t,n,r)=>{const o=JSON.stringify(e);if(t.kind==="optional"){if(t.hasRefinement||t.sourceText!==void 0||ft(t))return;const{inner:i}=t;if(!i)return;const a=Ge(i,n,r);if(!a)return;const c=r.next(),d=`__has${String(c)}`,p=`__val${String(c)}`,g=`let ${d} = false;
|
|
32
|
+
let ${p};
|
|
33
33
|
if (${n} !== undefined) {
|
|
34
|
-
${a.pre}${
|
|
34
|
+
${a.pre}${p} = ${a.out};
|
|
35
35
|
${d} = true;
|
|
36
36
|
}
|
|
37
|
-
`;return{entry:`...(${d} ? { ${o}: ${
|
|
38
|
-
`,c=
|
|
39
|
-
`},
|
|
40
|
-
${
|
|
41
|
-
`;return{out:i,pre:a}},
|
|
37
|
+
`;return{entry:`...(${d} ? { ${o}: ${p} } : {})`,pre:g}}const s=Ge(t,n,r);if(s)return{entry:`${o}: ${s.out}`,pre:s.pre}},_n=new Set(Object.getOwnPropertyNames(Object.prototype)),bt=(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(_n.has(s)){const p=`__f${String(n.next())}`;r+=`const ${p} = Object.hasOwn(${t}, ${a}) ? ${t}[${a}] : undefined;
|
|
38
|
+
`,c=p}const d=Dn(s,i,c,n);if(!d)return;r+=d.pre,o.push(d.entry)}return{entries:o.join(", "),pre:r}},yt=e=>{const t=`Object.getPrototypeOf(${e})`;return`if (${t} !== Object.prototype && ${t} !== null) return DEFER;
|
|
39
|
+
`},Pn=(e,t,n)=>{const r=e.shape??{},o=bt(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;
|
|
40
|
+
${yt(t)}${o.pre}const ${i} = { ${o.entries} };
|
|
41
|
+
`;return{out:i,pre:a}},Mn=e=>{let t=0;const r=bt(e,"source",{next:()=>(t+=1,t)});if(r)return`(source) => {
|
|
42
42
|
if (typeof source !== "object" || source === null || Array.isArray(source)) return DEFER;
|
|
43
|
-
${
|
|
43
|
+
${yt("source")}${r.pre}return { ${r.entries} };
|
|
44
44
|
}`},$=`// GENERATED by @lunora/codegen — do not edit.
|
|
45
45
|
// Run \`lunora codegen\` to regenerate.
|
|
46
46
|
|
|
47
|
-
`,ae=(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"},
|
|
47
|
+
`,ae=(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"},wt=/^[A-Za-z_$][\w$]*$/u,Fn=/^[\w./-]+$/u,f=(e,t)=>{if(!wt.test(e))throw new X("INTERNAL",`@lunora/codegen: ${t} is not a valid JS identifier: ${JSON.stringify(e)}`)},He=e=>e.charAt(0).toUpperCase()+e.slice(1),q=e=>wt.test(e)?e:JSON.stringify(e),Y=e=>e==="__proto__"?`[${JSON.stringify(e)}]`:q(e),Bn={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"},qn=e=>{if(e===void 0)return"unknown";if(!gt.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},O=e=>{const t=Bn[e.kind];if(t!==void 0)return t;switch(e.kind){case"array":return`Array<${e.inner?O(e.inner):"unknown"}>`;case"from":return e.tsType??"unknown";case"id":{const n=e.tableName??"_unknown_";return f(n,"v.id() table name"),`Id<"${n}">`}case"literal":return qn(e.literalValue);case"object":return e.shape?`{ ${Object.entries(e.shape).map(([r,o])=>kt(r,o)).join("; ")} }`:"Record<string, unknown>";case"optional":return`${e.inner?O(e.inner):"unknown"} | undefined`;case"record":{const n=e.keyType?O(e.keyType):"string",r=e.valueType?O(e.valueType):"unknown";return`Record<${n}, ${r}>`}case"union":return e.members&&e.members.length>0?e.members.map(n=>O(n)).join(" | "):"never";default:return"unknown"}},kt=(e,t)=>{const n=q(e);if(t.kind==="optional"){const r=t.inner?O(t.inner):"unknown";return`${n}?: ${r}`}return`${n}: ${O(t)}`},xe=e=>{const t=Object.entries(e);return t.length===0?"{}":`{ ${t.map(([n,r])=>kt(n,r)).join("; ")} }`},xt=e=>e.kind==="optional"||!!e.column?.hasDefault,se=e=>e.kind==="optional"&&e.inner?e.inner:e,jn=e=>{f(e.name,"table name");const t=Object.entries(e.shape).map(([r,o])=>{const s=se(o),i=O(s),a=q(r);return xt(o)?` ${a}?: ${i};`:` ${a}: ${i};`}).join(`
|
|
48
48
|
`),n=t?`
|
|
49
49
|
${t}
|
|
50
50
|
`:"";return`export interface Insert_${e.name} {
|
|
51
51
|
_id?: Id<"${e.name}">;
|
|
52
|
-
_creationTime?: number;${n}}`},Je="schema",
|
|
52
|
+
_creationTime?: number;${n}}`},Je="schema",ao=e=>{for(const u of e.tables)f(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(([x,v])=>{const S=q(x);if(v.kind==="optional"){const N=v.inner?O(v.inner):"unknown";return` ${S}?: ${N};`}return` ${S}: ${O(v)};`}).join(`
|
|
53
53
|
`),b=l?`
|
|
54
54
|
${l}
|
|
55
55
|
`:"",R=u.commitOrdered===!0?`
|
|
@@ -62,9 +62,9 @@ ${l}
|
|
|
62
62
|
`),i=e.tables.map(u=>{const l=u.searchIndexes.map(b=>JSON.stringify(b.name)).join(" | ");return` ${u.name}: ${l||"never"};`}).join(`
|
|
63
63
|
`),a=e.tables.map(u=>{const l=u.rankIndexes.map(b=>JSON.stringify(b.name)).join(" | ");return` ${u.name}: ${l||"never"};`}).join(`
|
|
64
64
|
`),c=e.tables.map(u=>{const l=u.shardMode==="global"?"":(u.geoIndexes??[]).map(b=>JSON.stringify(b.name)).join(" | ");return` ${u.name}: ${l||"never"};`}).join(`
|
|
65
|
-
`),d=e.vectorIndexes.map(u=>JSON.stringify(u.name)).join(" | ")||"never",
|
|
65
|
+
`),d=e.vectorIndexes.map(u=>JSON.stringify(u.name)).join(" | ")||"never",p=e.tables.map(u=>jn(u)).join(`
|
|
66
66
|
|
|
67
|
-
`),
|
|
67
|
+
`),g=e.tables.map(u=>` ${u.name}: Insert_${u.name};`).join(`
|
|
68
68
|
`),y=e.tables.map(u=>{const l=u.relations.map(b=>(f(b.table,"relation target table"),` ${q(b.name)}: ${b.kind==="one"?"OneRelation":"ManyRelation"}<"${b.table}">;`)).join(`
|
|
69
69
|
`);return l?` ${u.name}: {
|
|
70
70
|
${l}
|
|
@@ -132,11 +132,11 @@ export type GeoIndexName<T extends keyof DataModel> = GeoIndexNamesByTable[T];
|
|
|
132
132
|
/** Union of declared vector index names. \`never\` when none are declared. */
|
|
133
133
|
export type VectorIndexName = ${d};
|
|
134
134
|
|
|
135
|
-
${
|
|
135
|
+
${p}
|
|
136
136
|
|
|
137
137
|
/** Per-table insert shape, accepted by \`ctx.db.<table>.insert(...)\`. */
|
|
138
138
|
export interface InsertModel {
|
|
139
|
-
${
|
|
139
|
+
${g}
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
export type Insert<T extends keyof DataModel> = InsertModel[T];
|
|
@@ -161,11 +161,11 @@ export interface Relations {
|
|
|
161
161
|
${y}
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
`,Je)},
|
|
164
|
+
`,Je)},Wn=/import\("(?<spec>(?:\.\.?\/)*_generated\/[^"]+)"\)/gu,vt=/^(?:\.\.?\/)*_generated\//u,Rt=/\.[A-Za-z]\w*$/u,Un=e=>e.replaceAll(Wn,(t,n)=>{const r=n.replace(vt,"./");return`import("${Rt.test(r)?r:`${r}.js`}")`}),Kn=/import\("(?<spec>[^"]+)"\)/gu,dt="node_modules/",Qn=/^@types\//u,Vn=e=>e.replaceAll(Kn,(t,n)=>{const r=n.lastIndexOf(dt);if(r===-1||r>0&&n[r-1]!=="/")return t;const o=n.slice(r+dt.length);return o===""||Qn.test(o)?t:`import("${o}")`}),Hn=/import\("(?<spec>\.\.?\/[^"]+)"\)/gu,Gn=/^(?:\.\.?\/)+/u,Jn=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("/")},zn=(e,t)=>e.replaceAll(Hn,(n,r)=>{if(vt.test(r.replace(Gn,"")))return n;const o=t.includes("/")?t.slice(0,t.lastIndexOf("/")):"",i=`../${Jn(`${o}/${r}`)}`;return`import("${Rt.test(i)?i:`${i}.js`}")`}),E=(e,t)=>Un(zn(Vn(e),t)),Yn=["client","do","errors","flags","observability","platform","ratelimit","runtime","server","values"],Xn=new RegExp(String.raw`import\("@lunora/(?<pkg>${Yn.join("|")})(?<subpath>/[^"]*)?"\)`,"gu"),Zn={flags:new Set(["/web"]),platform:new Set},St=(e,t)=>t?e.replaceAll(Xn,(n,r,o)=>{const s=Zn[r];return o&&s&&!s.has(o)?n:`import("lunorash/${r}${o??""}")`}):e,ze=e=>["Doc","Id"].filter(t=>new RegExp(String.raw`(?<![.$\w])${t}<`,"u").test(e)),$t=e=>e.output===void 0||e.output.kind==="any"||e.kind==="stream"?e.returnType:O(e.output),Ye=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))},ut=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($t(s),s.filePath);return` ${s.exportName}: FunctionReference<"${s.kind}", ${i}, ${a}>;`}).join(`
|
|
165
165
|
`);return` ${q(T(n))}: {
|
|
166
166
|
${o}
|
|
167
167
|
};`};return Ye(e).map(n=>t(n)).join(`
|
|
168
|
-
`)},
|
|
168
|
+
`)},er=(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+=`
|
|
169
169
|
/** A typed reference to a durable workflow, addressable for \`cronJobs()\` targets. Mirrors \`@lunora/scheduler\`'s \`WorkflowReference\` structurally. */
|
|
170
170
|
export interface WorkflowReference<Params = Record<string, unknown>> {
|
|
171
171
|
readonly isLunoraWorkflow: true;
|
|
@@ -197,7 +197,7 @@ export const agents: AgentsRef = {
|
|
|
197
197
|
${i}
|
|
198
198
|
};
|
|
199
199
|
`,n.push(`import type { AgentRunInput } from "@lunora/agent";
|
|
200
|
-
`)}return{block:r,importLine:n.join("")}},
|
|
200
|
+
`)}return{block:r,importLine:n.join("")}},tr=()=>Object.keys(ht().functions).toSorted((e,t)=>e.localeCompare(t)),Tt=e=>new Set(e.filter(t=>T(t.filePath)==="agents").map(t=>t.exportName)),nr=()=>new Set(Object.entries(ht().functions).filter(([,e])=>e.visibility==="internal").map(([e])=>e)),rr=(e,t)=>{const n={importLine:"",lines:"",prelude:""};if(e.length===0)return n;const r=Tt(t),o=nr(),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=tr().filter(a=>!r.has(a));return i.length===0?n:{importLine:`import { agentComponent } from "@lunora/agent/component";
|
|
201
201
|
`,lines:i.map(a=>` "agents:${a}": lunoraAgentRuntimeFunctions.${a} as unknown as RegisteredLunoraFunction,`).join(`
|
|
202
202
|
`),prelude:`
|
|
203
203
|
/**
|
|
@@ -206,8 +206,8 @@ ${i}
|
|
|
206
206
|
* subscribe to the public queries (\`agents:agentMessages\` is the live thread view).
|
|
207
207
|
*/
|
|
208
208
|
const lunoraAgentRuntimeFunctions = agentComponent().functions;
|
|
209
|
-
`}},
|
|
210
|
-
`,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"}},
|
|
209
|
+
`}},or=(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";
|
|
210
|
+
`,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"}},ar=(e,t)=>{if(e.length===0)return[];const n=Tt(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))},sr=(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}))},ir=e=>{const t=e.filter(i=>i.stream);if(t.length===0)return{block:"",body:""};const n=Ye(t),r=n.map(([i,a])=>{const c=a.map(d=>{const p=E(d.chunkType??"unknown",d.filePath),g=E(xe(d.searchParams),d.filePath),y=E(xe(d.params),d.filePath);return` ${q(d.exportName)}: HttpStreamRef<${p}, ${g}, ${y}>;`}).join(`
|
|
211
211
|
`);return` ${q(T(i))}: {
|
|
212
212
|
${c}
|
|
213
213
|
};`}).join(`
|
|
@@ -224,15 +224,15 @@ ${r}
|
|
|
224
224
|
export const httpStreams: HttpStreamsRef = {
|
|
225
225
|
${o}
|
|
226
226
|
};
|
|
227
|
-
`,body:r}},
|
|
228
|
-
${
|
|
227
|
+
`,body:r}},so=e=>{const{agents:t=[],functions:n,httpRoutes:r=[],mutators:o=[],useUmbrella:s=!1,workflows:i=[]}=e,a=ae(s),c=[...n.filter(A=>A.visibility!=="internal"),...ar(t,n),...sr(o,n)],d=n.filter(A=>A.visibility==="internal"),p=ut(c),g=ut(d),y=ir(r),u=`${p}
|
|
228
|
+
${g}
|
|
229
229
|
${y.body}`,l=ze(u),b=l.length>0?`
|
|
230
230
|
import type { ${l.join(", ")} } from "./dataModel.js";
|
|
231
|
-
`:"",R=
|
|
232
|
-
${
|
|
233
|
-
`:"",x=
|
|
234
|
-
${
|
|
235
|
-
`:"",v=
|
|
231
|
+
`:"",R=p?`
|
|
232
|
+
${p}
|
|
233
|
+
`:"",x=g?`
|
|
234
|
+
${g}
|
|
235
|
+
`:"",v=er(i,t),S=`export interface ApiTypes {${R}}
|
|
236
236
|
|
|
237
237
|
export const api = anyApi as unknown as ApiTypes;
|
|
238
238
|
|
|
@@ -241,9 +241,9 @@ export interface InternalApiTypes {${x}}
|
|
|
241
241
|
|
|
242
242
|
export const internal = anyApi as unknown as InternalApiTypes;
|
|
243
243
|
${v.block}${y.block}`,N=[...S.includes("FunctionReference<")?["FunctionReference"]:[],...y.block===""?[]:["HttpStreamRef"]],Q=N.length>0?`import type { ${N.join(", ")} } from "${a.client}";
|
|
244
|
-
`:"";return
|
|
244
|
+
`:"";return St(`${$}import { anyApi } from "${a.client}";
|
|
245
245
|
${Q}${v.importLine}${b}
|
|
246
|
-
${S}`,s)},
|
|
246
|
+
${S}`,s)},io=e=>e?`${$}import { createSeedClient as createSeedClientBase } from "@lunora/seed";
|
|
247
247
|
import type { SeedClient, SeedClientOptions } from "@lunora/seed";
|
|
248
248
|
|
|
249
249
|
import schema from "../schema.js";
|
|
@@ -260,7 +260,7 @@ import type { InsertModel } from "./dataModel.js";
|
|
|
260
260
|
* const { posts } = await seed.posts((x) => x([10, 20]));
|
|
261
261
|
*/
|
|
262
262
|
export const createSeedClient = (options?: SeedClientOptions): SeedClient<InsertModel> => createSeedClientBase<InsertModel>(schema, options);
|
|
263
|
-
`:"",
|
|
263
|
+
`:"",lo=(e,t,n=!1)=>{if(e.length===0||!t)return"";const r=ae(n),o=c=>c.table===void 0?"Row":`Doc<${JSON.stringify(c.table)}> & Row`,s=e.map(c=>{f(c.exportName,"shape export name");const d=o(c),p=E(xe(c.args),c.filePath),g=Object.keys(c.args).length>0,y=g?` args: ${p};`:` args?: ${p};`,u=g?`(args: ${p}) => void`:`(args?: ${p}) => void`,l=`${c.exportName}CollectionOptions`;return`/** Options for the \`${c.exportName}\` shape binding. */
|
|
264
264
|
export interface ${He(l)} {
|
|
265
265
|
${y}
|
|
266
266
|
/**
|
|
@@ -314,7 +314,7 @@ import type { Collection } from "@tanstack/db";
|
|
|
314
314
|
import { createCollection } from "@tanstack/db";
|
|
315
315
|
${a}
|
|
316
316
|
${s}
|
|
317
|
-
`},
|
|
317
|
+
`},lr=(e,t)=>`lunora_${T(e)}_${String(t)}`,cr=`const callRegistered = async <R>(context: CallerCtx, functionPath: string, args: Record<string, unknown> | undefined): Promise<R> => {
|
|
318
318
|
const registered = LUNORA_FUNCTIONS[functionPath];
|
|
319
319
|
|
|
320
320
|
if (!registered) {
|
|
@@ -343,22 +343,22 @@ ${s}
|
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
return (await registered.handler(context, args ?? {})) as R;
|
|
346
|
-
};`,
|
|
346
|
+
};`,dr=(e,t,n=[],r=[])=>{const o=new Map,s=l=>{o.has(l)||o.set(l,lr(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,b])=>{if(!Fn.test(l))throw new X("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(l)}`);return`import * as ${b} from "../${l}.js";`}).join(`
|
|
347
347
|
`),a=e.map(l=>` "${T(l.filePath)}:${l.exportName}": ${o.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredLunoraFunction,`).join(`
|
|
348
348
|
`),c=t.map(l=>` ${JSON.stringify(l.id)}: ${o.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredDataMigration,`).join(`
|
|
349
349
|
`),d=n.map(l=>` "${T(l.filePath)}:${l.exportName}": ${o.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredLunoraFunction,`).join(`
|
|
350
|
-
`),
|
|
351
|
-
`),
|
|
352
|
-
`),u=e.map(l=>{if(l.lifecycle||Object.keys(l.args).length===0)return;const b=
|
|
350
|
+
`),p=r.map(l=>` "${l.exportName}": ${o.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredShape,`).join(`
|
|
351
|
+
`),g=n.map(l=>`${T(l.filePath)}:${l.exportName}`),y=[a,d].filter(l=>l.length>0).join(`
|
|
352
|
+
`),u=e.map(l=>{if(l.lifecycle||Object.keys(l.args).length===0)return;const b=Mn(l.args);return b===void 0?void 0:`installCompiledValidatorMap(${o.get(l.filePath)??""}.${l.exportName}.args, ${b});`}).filter(l=>l!==void 0).join(`
|
|
353
353
|
`);return{dispatchBody:y.length>0?`
|
|
354
354
|
${y}
|
|
355
355
|
`:"",importBlock:i.length>0?`${i}
|
|
356
356
|
|
|
357
357
|
`:"",installBlock:u,migrationBody:c.length>0?`
|
|
358
358
|
${c}
|
|
359
|
-
`:"",mutatorPaths:
|
|
360
|
-
${
|
|
361
|
-
`:""}},
|
|
359
|
+
`:"",mutatorPaths:g,shapeBody:p.length>0?`
|
|
360
|
+
${p}
|
|
361
|
+
`:""}},ur=e=>{const t=Ye(e),n=t.map(([o,s])=>{const i=s.map(a=>{const c=E(xe(a.args),a.filePath),d=c==="{}"?"?":"",p=E($t(a),a.filePath);return a.kind==="stream"?` ${a.exportName}: (args${d}: ${c}) => Promise<AsyncIterable<${p}>>;`:` ${a.exportName}: (args${d}: ${c}) => Promise<${p}>;`}).join(`
|
|
362
362
|
`);return` ${q(T(o))}: {
|
|
363
363
|
${i}
|
|
364
364
|
};`}).join(`
|
|
@@ -366,7 +366,7 @@ ${i}
|
|
|
366
366
|
`);return` ${Y(i)}: {
|
|
367
367
|
${a}
|
|
368
368
|
},`}).join(`
|
|
369
|
-
`),types:n}},
|
|
369
|
+
`),types:n}},pr=(e,t=[])=>{const n=new Set;for(const r of e.tables)for(const o of Object.values(r.shape)){const s=se(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))]},co=({agents:e=[],containers:t=[],env:n,hasAccessFacade:r=!1,hasAi:o=!1,hasAnalytics:s=!1,hasBrowser:i=!1,hasVectors:a=!0,hasFlags:c=!1,hasHyperdrive:d=!1,hasImages:p=!1,hasKv:g=!1,hasNotify:y=!1,hasPayments:u=!1,hasPipelines:l=!1,hasR2sql:b=!1,hasX402:R=!1,identity:x,queues:v=[],schema:S,storageRuleBuckets:N=[],useUmbrella:Q=!1,workflows:A=[]}={})=>{const C=ae(Q),w=pr(S??{tables:[]},N).map(h=>JSON.stringify(h)).join(" | "),P=o?`import type { LunoraAi } from "@lunora/ai";
|
|
370
370
|
`:"",M=o?`
|
|
371
371
|
readonly ai: LunoraAi;`:"",ie=u?`import type { LunoraPayment } from "@lunora/payment";
|
|
372
372
|
`:"",le=u?`
|
|
@@ -374,13 +374,13 @@ ${a}
|
|
|
374
374
|
`:"",V=R?`
|
|
375
375
|
readonly x402: X402Pay;`:"",L=t.length>0?`import type { ContainerAccessor } from "@lunora/container";
|
|
376
376
|
`:"",ee=t.length>0?`
|
|
377
|
-
readonly containers: {${t.map(
|
|
378
|
-
readonly ${
|
|
379
|
-
};`:"",k=[...o?[" /** Workers AI binding (the conventional `env.AI`), narrowing `ctx.ai`. */\n readonly AI?: unknown;"]:[],...t.map(
|
|
380
|
-
readonly ${
|
|
381
|
-
readonly ${
|
|
382
|
-
readonly ${
|
|
383
|
-
readonly ${
|
|
377
|
+
readonly containers: {${t.map(h=>`
|
|
378
|
+
readonly ${h.exportName}: ContainerAccessor;`).join("")}
|
|
379
|
+
};`:"",k=[...o?[" /** Workers AI binding (the conventional `env.AI`), narrowing `ctx.ai`. */\n readonly AI?: unknown;"]:[],...t.map(h=>(f(h.bindingName,`container binding "${h.bindingName}"`),` /** Durable Object namespace for the \`${h.exportName}\` container. */
|
|
380
|
+
readonly ${h.bindingName}?: unknown;`)),...A.map(h=>(f(h.bindingName,`workflow binding "${h.bindingName}"`),` /** Workflow binding for the \`${h.exportName}\` workflow. */
|
|
381
|
+
readonly ${h.bindingName}?: unknown;`)),...v.map(h=>(f(h.bindingName,`queue binding "${h.bindingName}"`),` /** Queue producer binding for the \`${h.exportName}\` queue. */
|
|
382
|
+
readonly ${h.bindingName}?: unknown;`)),...e.map(h=>(f(h.bindingName,`agent binding "${h.bindingName}"`),` /** Workflow binding for the \`${h.exportName}\` agent. */
|
|
383
|
+
readonly ${h.bindingName}?: unknown;`))].join(`
|
|
384
384
|
`),Ae=`
|
|
385
385
|
|
|
386
386
|
/**
|
|
@@ -399,9 +399,9 @@ ${k}`:""}
|
|
|
399
399
|
}
|
|
400
400
|
|
|
401
401
|
/** Alias for {@link CloudflareBindings} — the typed shape of \`env\`. */
|
|
402
|
-
export type Env = CloudflareBindings;`,F=(
|
|
403
|
-
readonly vectors: VectorSearch<VectorIndexName>;`:"",
|
|
404
|
-
readonly vectors: VectorSearchReader<VectorIndexName>;`:"",J=
|
|
402
|
+
export type Env = CloudflareBindings;`,F=(h,We,Te)=>{const re=An.get(h);if(re!==void 0&&re.tier!==Te)throw new X("INTERNAL",`@lunora/codegen: capability "${h}" declares tier "${re.tier}" in SERVER_CTX_FIELDS but is emitted onto the "${Te}" context — update whichever is wrong.`);return We?re?.field??"":""},ce=F("kv",g,"every"),de=F("analytics",s,"every"),Oe=F("hyperdrive",d,"action"),Ie=F("browser",i,"action"),Ce=F("images",p,"action"),ue=F("pipelines",l,"action"),H=F("r2sql",b,"action"),_=a&&(S?.vectorIndexes.length??0)>0,G=_?' | "vectors"':"",te=_?`
|
|
403
|
+
readonly vectors: VectorSearch<VectorIndexName>;`:"",pe=_?`
|
|
404
|
+
readonly vectors: VectorSearchReader<VectorIndexName>;`:"",J=_?`import type { VectorSearch, VectorSearchReader } from "${C.server}";
|
|
405
405
|
import type { VectorIndexName } from "./dataModel.js";
|
|
406
406
|
`:"",j=r?`
|
|
407
407
|
/** Verified Cloudflare Access identity — a synchronous facade over the resolved claims (email / groups / hasGroup / claims). Anonymous when no Access token is present. */
|
|
@@ -424,27 +424,27 @@ type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params
|
|
|
424
424
|
|
|
425
425
|
/** This project's declared workflows, addressable from \`ctx.workflows\` by their \`lunora/workflows.ts\` export name. */
|
|
426
426
|
export interface LunoraWorkflows {
|
|
427
|
-
${A.map(
|
|
427
|
+
${A.map(h=>` get(name: ${JSON.stringify(h.exportName)}): WorkflowHandle<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${h.exportName}>>;`).join(`
|
|
428
428
|
`)}
|
|
429
429
|
}`:"",ve=B?' | "workflows"':"",Re=B?`
|
|
430
|
-
readonly workflows: LunoraWorkflows;`:"",
|
|
430
|
+
readonly workflows: LunoraWorkflows;`:"",he=v.length>0,Ee=he?`import type { QueueProducer } from "@lunora/queue";
|
|
431
431
|
import type * as lunoraQueueDefinitions from "../queues.js";
|
|
432
|
-
`:"",
|
|
432
|
+
`:"",De=he?`
|
|
433
433
|
|
|
434
434
|
/** Message body type carried by a \`defineQueue\` definition (its phantom \`__lunoraBody\`). */
|
|
435
435
|
type QueueBodyOf<Definition> = Definition extends { __lunoraBody?: infer Body } ? (unknown extends Body ? unknown : NonNullable<Body>) : unknown;
|
|
436
436
|
|
|
437
437
|
/** This project's declared queues, addressable from \`ctx.queues\` by their \`lunora/queues.ts\` export name. */
|
|
438
438
|
export interface LunoraQueues {
|
|
439
|
-
${v.map(
|
|
439
|
+
${v.map(h=>` readonly ${h.exportName}: QueueProducer<QueueBodyOf<typeof lunoraQueueDefinitions.${h.exportName}>>;`).join(`
|
|
440
440
|
`)}
|
|
441
|
-
}`:"",Se=
|
|
442
|
-
readonly queues: LunoraQueues;`:"",me=e.length>0,
|
|
441
|
+
}`:"",Se=he?`
|
|
442
|
+
readonly queues: LunoraQueues;`:"",me=e.length>0,_e=me?`import type { AgentHandle } from "@lunora/agent";
|
|
443
443
|
`:"",Pe=me?`
|
|
444
444
|
|
|
445
445
|
/** This project's declared agents, addressable from \`ctx.agents\` by their \`lunora/agents.ts\` export name. */
|
|
446
446
|
export interface LunoraAgents {
|
|
447
|
-
${e.map(
|
|
447
|
+
${e.map(h=>(f(h.exportName,`agent export "${h.exportName}"`),` readonly ${h.exportName}: AgentHandle;`)).join(`
|
|
448
448
|
`)}
|
|
449
449
|
}`:"",$e=me?`
|
|
450
450
|
readonly agents: LunoraAgents;`:"",Me=x?`import type { InferIdentity } from "${C.server}";
|
|
@@ -517,7 +517,7 @@ export type {
|
|
|
517
517
|
} from "${C.serverDataModel}";
|
|
518
518
|
|
|
519
519
|
import type { DataModel, Doc, GeoIndexNamesByTable, Id as IdOfTable, IndexNamesByTable, Insert, InsertModel, RankIndexNamesByTable, Relations, SearchIndexNamesByTable, TableName } from "./dataModel.js";
|
|
520
|
-
${J}${P}${ie}${Z}${L}${ne}${Ee}${
|
|
520
|
+
${J}${P}${ie}${Z}${L}${ne}${Ee}${_e}${Me}${qe}
|
|
521
521
|
export type { AppTableName, DataModel, Doc, Id, TableName } from "./dataModel.js";
|
|
522
522
|
|
|
523
523
|
/**
|
|
@@ -577,7 +577,7 @@ export interface OrmWriter extends OrmReader {
|
|
|
577
577
|
}
|
|
578
578
|
|
|
579
579
|
/** Storage buckets this schema declares (\`v.storage("name")\`), narrowing \`ctx.storage.bucket(name)\`. */
|
|
580
|
-
export type StorageBucketName = ${w};${Ae}${Le}${
|
|
580
|
+
export type StorageBucketName = ${w};${Ae}${Le}${De}${Pe}${Fe}${je}
|
|
581
581
|
|
|
582
582
|
/**
|
|
583
583
|
* Project-typed contexts. The base contexts from \`@lunora/server\` are
|
|
@@ -643,7 +643,7 @@ type TypedAsId = <T extends string>(tableName: AsIdTable<T>, id: string) => IdOf
|
|
|
643
643
|
export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"${G}${ge}${be}> {
|
|
644
644
|
readonly db: Omit<DatabaseReader, "asId" | "query" | "get"> & DatabaseReaderFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
|
|
645
645
|
readonly orm: OrmReader;
|
|
646
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${
|
|
646
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${pe}${j}${ce}${W}${U}${de}${ye}${fe}
|
|
647
647
|
}
|
|
648
648
|
|
|
649
649
|
export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${G}${ve}${ge}${be}> {
|
|
@@ -730,12 +730,12 @@ export const definePolicy = createPolicyDsl<DataModel, Relations${Be}>();
|
|
|
730
730
|
export const v = vBase as unknown as Omit<typeof vBase, "id"> & {
|
|
731
731
|
id: <T extends TableName>(table: T) => ColumnValidator<IdOfTable<T>, IdOfTable<T>>;
|
|
732
732
|
};
|
|
733
|
-
`},
|
|
734
|
-
`);let S=
|
|
733
|
+
`},hr=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},uo=e=>{const{agents:t=[],functions:n,migrations:r=[],mutators:o=[],shapes:s=[],useUmbrella:i=!1,usesSandbox:a=!1}=e,c=n.length>0,d=ae(i),{dispatchBody:p,importBlock:g,installBlock:y,migrationBody:u,mutatorPaths:l,shapeBody:b}=dr(n,r,o,s),R=rr(t,n),x=or(a,n),v=[R.lines,x.lines].filter(k=>k.length>0).join(`
|
|
734
|
+
`);let S=p;v.length>0&&(S=p.length>0?`${p.trimEnd()}
|
|
735
735
|
${v}
|
|
736
736
|
`:`
|
|
737
737
|
${v}
|
|
738
|
-
`);const N=
|
|
738
|
+
`);const N=hr(n),Q=s.length>0?`import type { RegisteredShape } from "${d.server}";
|
|
739
739
|
`:"",A=s.length>0?`
|
|
740
740
|
/**
|
|
741
741
|
* Replication-shape registry — one entry per \`defineShape\` in \`lunora/shapes.ts\`.
|
|
@@ -759,14 +759,14 @@ export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${l.map(k=>JSO
|
|
|
759
759
|
* parser as a zero-allocation fast path; anything it can't model is deferred.
|
|
760
760
|
*/
|
|
761
761
|
${y}
|
|
762
|
-
`:"",M=
|
|
762
|
+
`:"",M=ur(n),ie=M.types?`
|
|
763
763
|
${M.types}
|
|
764
764
|
`:"",le=M.implementation?`
|
|
765
765
|
${M.implementation}
|
|
766
766
|
`:"",Z=ze(M.types),V=Z.length>0?`import type { ${Z.join(", ")} } from "./dataModel.js";
|
|
767
|
-
`:"",L=c?"context":"_context",ee=c?`${
|
|
767
|
+
`:"",L=c?"context":"_context",ee=c?`${cr}
|
|
768
768
|
|
|
769
|
-
`:"";return
|
|
769
|
+
`:"";return St(`${$}${g}${R.importLine}${x.importLine}${w}${Q}import { LunoraError } from "${d.server}";
|
|
770
770
|
import type { ActionCtx, MutationCtx, QueryCtx } from "./server.js";
|
|
771
771
|
${V}
|
|
772
772
|
/**
|
|
@@ -879,7 +879,7 @@ export interface RegisteredDataMigration {
|
|
|
879
879
|
* shard DO's admin RPC and the CLI resolve migrations to run through this map.
|
|
880
880
|
*/
|
|
881
881
|
export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${u}};
|
|
882
|
-
`,i)},
|
|
882
|
+
`,i)},mr=e=>{const t={};for(const n of e.tables){const r={};for(const[o,s]of Object.entries(n.shape)){const i=se(s);i.kind==="id"&&i.tableName!==void 0&&(r[o]=i.tableName)}Object.keys(r).length>0&&(t[n.name]=r)}return t},gr=e=>{const t={};for(const n of e.tables){const r=[];for(const[o,s]of Object.entries(n.shape))se(s).kind==="storage"&&r.push(o);r.length>0&&(t[n.name]=r)}return t},fr=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},br=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},yr=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},wr=(e,t)=>{const n=se(t),r={name:e,optional:xt(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=yr(n);return o!==void 0&&(r.enumValues=o),n.column?.notNull===!1&&(r.nullable=!0),r},kr=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(wr(o,s));t[n.name]=r}return t},xr=e=>e?{importFragment:"serveRelationFanout, ",override:`
|
|
883
883
|
protected override async runRelationFanoutRead(functionPath: string, args: Record<string, unknown>): Promise<unknown> {
|
|
884
884
|
this.ensureMigrated();
|
|
885
885
|
|
|
@@ -887,7 +887,7 @@ export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${u}}
|
|
|
887
887
|
|
|
888
888
|
return serveRelationFanout(schema as unknown as SchemaLike, db, functionPath, args);
|
|
889
889
|
}
|
|
890
|
-
`}:{importFragment:"",override:""},
|
|
890
|
+
`}:{importFragment:"",override:""},vr=e=>{if(!e)return{build:"",configField:"",contextField:"",stub:""};const t='throw new Error("ctx.ai: no AI binding found. Add an \\`ai\\` binding (env.AI) to wrangler.jsonc, or pass \\`ai\\` to createShardDO().");';return{build:`
|
|
891
891
|
const aiBinding = config.ai?.(env) ?? (env as Record<string, unknown>).AI;
|
|
892
892
|
// Correlate AI-Gateway-routed calls with the Lunora trace: thread the
|
|
893
893
|
// function path + trace id into createAi, which folds them into the
|
|
@@ -925,7 +925,7 @@ const aiStub: LunoraAi = {
|
|
|
925
925
|
const ${e} = {
|
|
926
926
|
${s}
|
|
927
927
|
}${r};
|
|
928
|
-
`},
|
|
928
|
+
`},D={build:"",configField:"",contextField:"",importLines:[],stub:""},Rr=e=>e?{build:`
|
|
929
929
|
const kvBinding = config.kv?.(env) ?? (env as Record<string, unknown>).KV;
|
|
930
930
|
// KV is not this shard's SQLite, so nothing appends a \`__cdc_log\` entry
|
|
931
931
|
// when a value changes — a subscription that read one can never be proven
|
|
@@ -939,24 +939,24 @@ ${s}
|
|
|
939
939
|
]);
|
|
940
940
|
`,configField:`
|
|
941
941
|
kv?: (env: Record<string, unknown>) => KVNamespaceLike;`,contextField:`
|
|
942
|
-
kv,`,importLines:['import type { Kv, KVNamespaceLike } from "@lunora/bindings/kv";','import { createKv } from "@lunora/bindings/kv";'],stub:I("kvStub: Kv",'throw new Error("ctx.kv: no KV binding found. Add a \\`kv_namespaces\\` binding (env.KV) to wrangler.jsonc, or pass \\`kv\\` to createShardDO().");',["delete","get","getRaw","getWithMetadata","list","put"])}:
|
|
942
|
+
kv,`,importLines:['import type { Kv, KVNamespaceLike } from "@lunora/bindings/kv";','import { createKv } from "@lunora/bindings/kv";'],stub:I("kvStub: Kv",'throw new Error("ctx.kv: no KV binding found. Add a \\`kv_namespaces\\` binding (env.KV) to wrangler.jsonc, or pass \\`kv\\` to createShardDO().");',["delete","get","getRaw","getWithMetadata","list","put"])}:D,Sr=(e,t)=>e?{build:`
|
|
943
943
|
const flags: import("${t}").LunoraFlags = createFlags(flagsConfig, env, {
|
|
944
944
|
provider: () => config.flags?.(env),
|
|
945
945
|
targetingKey: () => flagsConfig.identify?.({ identity: identity ?? null, userId: userId ?? null }),
|
|
946
946
|
});
|
|
947
947
|
`,configField:`
|
|
948
948
|
flags?: (env: Record<string, unknown>) => import("${t}").Provider;`,contextField:`
|
|
949
|
-
flags,`,importLines:[`import { createFlags } from "${t}";`,'import flagsConfig from "../flags.js";'],stub:""}:
|
|
949
|
+
flags,`,importLines:[`import { createFlags } from "${t}";`,'import flagsConfig from "../flags.js";'],stub:""}:D,$r=e=>e?{build:`
|
|
950
950
|
const { notify, push } = createNotify(notifyConfig, env, { log, metrics });
|
|
951
951
|
`,configField:"",contextField:`
|
|
952
952
|
notify,
|
|
953
|
-
push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:
|
|
953
|
+
push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:D,Tr=e=>e?{build:`
|
|
954
954
|
const envConfig = lunoraEnvContract.${e.exportName}(env);
|
|
955
955
|
`,configField:"",contextField:`
|
|
956
|
-
env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:
|
|
956
|
+
env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:D,Nr=e=>e?{build:`
|
|
957
957
|
const access = accessFacade(identity, userId);
|
|
958
958
|
`,configField:"",contextField:`
|
|
959
|
-
access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:
|
|
959
|
+
access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:D,Ar=(e,t,n)=>{if(!t)return{constant:"",evaluateOverride:"",subscriptionOverride:""};const r=a=>`
|
|
960
960
|
const env = (this.env ?? {}) as Record<string, unknown>;
|
|
961
961
|
const flags: import("${n}").LunoraFlags = createFlags(flagsConfig, env, {
|
|
962
962
|
provider: () => config.flags?.(env),
|
|
@@ -1018,25 +1018,25 @@ const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number"
|
|
|
1018
1018
|
|
|
1019
1019
|
return flags.boolean(key, typeof args.default === "boolean" ? args.default : false, context);
|
|
1020
1020
|
}
|
|
1021
|
-
`;return{constant:o,evaluateOverride:s,subscriptionOverride:i}},
|
|
1021
|
+
`;return{constant:o,evaluateOverride:s,subscriptionOverride:i}},Or=e=>e?{build:`
|
|
1022
1022
|
const analyticsBinding = config.analytics?.(env) ?? (env as Record<string, unknown>).ANALYTICS;
|
|
1023
1023
|
const analytics: AnalyticsClient = analyticsBinding ? createAnalytics(analyticsBinding as AnalyticsEngineDatasetLike) : analyticsStub;
|
|
1024
1024
|
`,configField:`
|
|
1025
1025
|
analytics?: (env: Record<string, unknown>) => AnalyticsEngineDatasetLike;`,contextField:`
|
|
1026
|
-
analytics,`,importLines:['import type { AnalyticsClient, AnalyticsEngineDatasetLike } from "@lunora/bindings/analytics";','import { createAnalytics } from "@lunora/bindings/analytics";'],stub:I("analyticsStub: AnalyticsClient",'throw new Error("ctx.analytics: no Analytics Engine binding found. Add an \\`analytics_engine_datasets\\` binding (env.ANALYTICS) to wrangler.jsonc, or pass \\`analytics\\` to createShardDO().");',["track","writeDataPoint"],{sync:["track","writeDataPoint"]})}:
|
|
1026
|
+
analytics,`,importLines:['import type { AnalyticsClient, AnalyticsEngineDatasetLike } from "@lunora/bindings/analytics";','import { createAnalytics } from "@lunora/bindings/analytics";'],stub:I("analyticsStub: AnalyticsClient",'throw new Error("ctx.analytics: no Analytics Engine binding found. Add an \\`analytics_engine_datasets\\` binding (env.ANALYTICS) to wrangler.jsonc, or pass \\`analytics\\` to createShardDO().");',["track","writeDataPoint"],{sync:["track","writeDataPoint"]})}:D,Ir=e=>e?{build:`
|
|
1027
1027
|
const imagesBinding = config.images?.(env) ?? (env as Record<string, unknown>).IMAGES;
|
|
1028
1028
|
const images: Images = imagesBinding ? createImages({ binding: imagesBinding as ImagesBindingLike }) : imagesStub;
|
|
1029
1029
|
`,configField:`
|
|
1030
1030
|
images?: (env: Record<string, unknown>) => ImagesBindingLike;`,contextField:`
|
|
1031
|
-
images,`,importLines:['import type { Images, ImagesBindingLike } from "@lunora/bindings/images";','import { createImages } from "@lunora/bindings/images";'],stub:I("imagesStub: Images",'throw new Error("ctx.images: no Images binding found. Add an \\`images\\` binding (env.IMAGES) to wrangler.jsonc, or pass \\`images\\` to createShardDO().");',["info","transform"])}:
|
|
1031
|
+
images,`,importLines:['import type { Images, ImagesBindingLike } from "@lunora/bindings/images";','import { createImages } from "@lunora/bindings/images";'],stub:I("imagesStub: Images",'throw new Error("ctx.images: no Images binding found. Add an \\`images\\` binding (env.IMAGES) to wrangler.jsonc, or pass \\`images\\` to createShardDO().");',["info","transform"])}:D,Cr=e=>e?{build:`
|
|
1032
1032
|
const sql: SqlClient = config.sql ? config.sql(env) : sqlStub;
|
|
1033
1033
|
`,configField:`
|
|
1034
1034
|
sql?: (env: Record<string, unknown>) => SqlClient;`,contextField:`
|
|
1035
|
-
sql,`,importLines:['import type { SqlClient } from "@lunora/hyperdrive";'],stub:I("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"])}:
|
|
1035
|
+
sql,`,importLines:['import type { SqlClient } from "@lunora/hyperdrive";'],stub:I("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,Lr=e=>e?{build:`
|
|
1036
1036
|
const browser: Browser = config.browser ? config.browser(env) : browserStub;
|
|
1037
1037
|
`,configField:`
|
|
1038
1038
|
browser?: (env: Record<string, unknown>) => Browser;`,contextField:`
|
|
1039
|
-
browser,`,importLines:['import type { Browser } from "@lunora/browser";'],stub:I("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"])}:
|
|
1039
|
+
browser,`,importLines:['import type { Browser } from "@lunora/browser";'],stub:I("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,Er=e=>e?{build:`
|
|
1040
1040
|
const r2sqlEnv = env as Record<string, unknown>;
|
|
1041
1041
|
const r2sqlAccountId = (r2sqlEnv.R2_SQL_ACCOUNT_ID ?? r2sqlEnv.CLOUDFLARE_ACCOUNT_ID) as string | undefined;
|
|
1042
1042
|
const r2sqlToken = r2sqlEnv.R2_SQL_TOKEN as string | undefined;
|
|
@@ -1047,11 +1047,11 @@ const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number"
|
|
|
1047
1047
|
? createR2Sql({ accountId: r2sqlAccountId, apiToken: r2sqlToken, bucket: r2sqlBucket })
|
|
1048
1048
|
: r2sqlStub;
|
|
1049
1049
|
`,configField:`
|
|
1050
|
-
r2sql?: (env: Record<string, unknown>) => R2SqlClient;`,contextField:"",importLines:['import type { R2SqlClient } from "@lunora/bindings/r2sql";','import { createR2Sql } from "@lunora/bindings/r2sql";'],stub:I("r2sqlStub: R2SqlClient",'throw new Error("ctx.r2sql: no R2 SQL credentials found. Set \\`R2_SQL_TOKEN\\`, \\`R2_SQL_ACCOUNT_ID\\` (or \\`CLOUDFLARE_ACCOUNT_ID\\`), and \\`R2_SQL_BUCKET\\` in your env/.dev.vars, or pass an \\`r2sql\\` config thunk to createShardDO().");',["describe","explain","from","query","showDatabases","showTables"],{sync:["from"]})}:
|
|
1050
|
+
r2sql?: (env: Record<string, unknown>) => R2SqlClient;`,contextField:"",importLines:['import type { R2SqlClient } from "@lunora/bindings/r2sql";','import { createR2Sql } from "@lunora/bindings/r2sql";'],stub:I("r2sqlStub: R2SqlClient",'throw new Error("ctx.r2sql: no R2 SQL credentials found. Set \\`R2_SQL_TOKEN\\`, \\`R2_SQL_ACCOUNT_ID\\` (or \\`CLOUDFLARE_ACCOUNT_ID\\`), and \\`R2_SQL_BUCKET\\` in your env/.dev.vars, or pass an \\`r2sql\\` config thunk to createShardDO().");',["describe","explain","from","query","showDatabases","showTables"],{sync:["from"]})}:D,Dr=e=>e?{build:`
|
|
1051
1051
|
const pipelinesBinding = config.pipelines?.(env) ?? (env as Record<string, unknown>).PIPELINES;
|
|
1052
1052
|
const pipelines: PipelineClient = pipelinesBinding ? createPipelines({ binding: pipelinesBinding as PipelineBindingLike }) : pipelinesStub;
|
|
1053
1053
|
`,configField:`
|
|
1054
|
-
pipelines?: (env: Record<string, unknown>) => PipelineBindingLike;`,contextField:"",importLines:['import type { PipelineBindingLike, PipelineClient } from "@lunora/bindings/pipelines";','import { createPipelines } from "@lunora/bindings/pipelines";'],stub:I("pipelinesStub: PipelineClient",'throw new Error("ctx.pipelines: no Pipelines binding found. Add a \\`pipelines\\` binding (env.PIPELINES) to wrangler.jsonc, or pass \\`pipelines\\` to createShardDO().");',["send"])}:
|
|
1054
|
+
pipelines?: (env: Record<string, unknown>) => PipelineBindingLike;`,contextField:"",importLines:['import type { PipelineBindingLike, PipelineClient } from "@lunora/bindings/pipelines";','import { createPipelines } from "@lunora/bindings/pipelines";'],stub:I("pipelinesStub: PipelineClient",'throw new Error("ctx.pipelines: no Pipelines binding found. Add a \\`pipelines\\` binding (env.PIPELINES) to wrangler.jsonc, or pass \\`pipelines\\` to createShardDO().");',["send"])}:D,po=(e,t)=>{if(e.length===0)return"";const n=t?`, ${JSON.stringify(t)}`:"",r=e.map(s=>(f(s.exportName,`container export "${s.exportName}"`),f(s.className,`container class "${s.className}"`),`/** Container DO for the \`${s.exportName}\` definition (binding \`${s.bindingName}\`). */
|
|
1055
1055
|
export class ${s.className} extends LunoraContainer {
|
|
1056
1056
|
public constructor(ctx: ConstructorParameters<typeof LunoraContainer>[0], env: Record<string, unknown>) {
|
|
1057
1057
|
super(ctx, env, ${s.exportName}, "${s.exportName}"${n});
|
|
@@ -1076,7 +1076,7 @@ import { ${o} } from "../containers.js";
|
|
|
1076
1076
|
|
|
1077
1077
|
export { ContainerProxy } from "@lunora/container/do";
|
|
1078
1078
|
|
|
1079
|
-
${r}`},
|
|
1079
|
+
${r}`},_r=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const r of e)f(r.exportName,`container export "${r.exportName}"`),f(r.bindingName,`container binding "${r.bindingName}"`);const n=e.map(r=>{const o=r.maxInstances===void 0?"":`, maxInstances: ${String(r.maxInstances)}`;return` { binding: "${r.bindingName}", exportName: "${r.exportName}"${o} },`}).join(`
|
|
1080
1080
|
`);return{build:`
|
|
1081
1081
|
const containers = createContainerContext(env, LUNORA_CONTAINERS, ${t?JSON.stringify(t):"undefined"}, this.getCurrentTraceparent());
|
|
1082
1082
|
`,contextField:`
|
|
@@ -1085,7 +1085,7 @@ ${r}`},Lr=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[]
|
|
|
1085
1085
|
const LUNORA_CONTAINERS: ReadonlyArray<ContainerBindingSpec> = [
|
|
1086
1086
|
${n}
|
|
1087
1087
|
];
|
|
1088
|
-
`}},
|
|
1088
|
+
`}},ho=e=>{if(e.length===0)return"";const t=e.map(r=>(f(r.exportName,`workflow export "${r.exportName}"`),f(r.className,`workflow class "${r.className}"`),`/** WorkflowEntrypoint for the \`${r.exportName}\` definition (binding \`${r.bindingName}\`). */
|
|
1089
1089
|
export class ${r.className} extends LunoraWorkflow<WorkflowParamsOf<typeof ${r.exportName}>, WorkflowOutputOf<typeof ${r.exportName}>> {
|
|
1090
1090
|
public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
1091
1091
|
super(ctx, env, ${r.exportName}, "${r.exportName}");
|
|
@@ -1113,20 +1113,20 @@ type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params
|
|
|
1113
1113
|
/** Output type carried by a \`defineWorkflow\` definition (its phantom \`__output\`), so each entrypoint keeps the authored return type. */
|
|
1114
1114
|
type WorkflowOutputOf<Definition> = Definition extends { __output?: infer Output } ? Output : unknown;
|
|
1115
1115
|
|
|
1116
|
-
${t}`},
|
|
1116
|
+
${t}`},mo=e=>{if(e.length===0)return"";const n=e.filter(a=>a.voice).length>0,r=e.map(a=>{f(a.exportName,`agent export "${a.exportName}"`),f(a.className,`agent class "${a.className}"`);const c=`/** WorkflowEntrypoint for the \`${a.exportName}\` agent (binding \`${a.bindingName}\`). */
|
|
1117
1117
|
export class ${a.className} extends LunoraWorkflow<AgentRunInput, AgentRunResult> {
|
|
1118
1118
|
public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
1119
1119
|
super(ctx, env, compileAgentWorkflow(${a.exportName}, "${a.exportName}"), "${a.exportName}");
|
|
1120
1120
|
}
|
|
1121
1121
|
}
|
|
1122
|
-
`;if(!a.voice)return c;const d=a.voiceClassName??"",
|
|
1123
|
-
/** Voice-session Durable Object for the \`${a.exportName}\` agent (binding \`${
|
|
1122
|
+
`;if(!a.voice)return c;const d=a.voiceClassName??"",p=a.voiceBindingName??"";f(d,`agent voice class "${d}"`);const g=`
|
|
1123
|
+
/** Voice-session Durable Object for the \`${a.exportName}\` agent (binding \`${p}\`). */
|
|
1124
1124
|
export class ${d} extends VoiceSessionDO {
|
|
1125
1125
|
public constructor(ctx: ConstructorParameters<typeof VoiceSessionDO>[0], env: Record<string, unknown>) {
|
|
1126
1126
|
super(ctx, env, ${a.exportName}, "${a.exportName}");
|
|
1127
1127
|
}
|
|
1128
1128
|
}
|
|
1129
|
-
`;return`${c}${
|
|
1129
|
+
`;return`${c}${g}`}).join(`
|
|
1130
1130
|
`),o=e.map(a=>a.exportName).join(", ");return`${$}/**
|
|
1131
1131
|
* WorkflowEntrypoint classes for the agents declared in \`lunora/agents.ts\`.
|
|
1132
1132
|
* Each \`defineAgent\` compiles a replay-safe tool-loop onto a Cloudflare
|
|
@@ -1141,7 +1141,7 @@ import type { AgentRunInput, AgentRunResult } from "@lunora/agent";
|
|
|
1141
1141
|
|
|
1142
1142
|
import { ${o} } from "../agents.js";
|
|
1143
1143
|
|
|
1144
|
-
${r}`},
|
|
1144
|
+
${r}`},go=e=>{const t=e.filter(o=>o.mode==="push");if(t.length===0)return"";for(const o of t)f(o.exportName,`queue export "${o.exportName}"`);const n=t.map(o=>o.exportName).join(", "),r=t.map(o=>` ${JSON.stringify(o.name)}: { definition: ${o.exportName}, exportName: ${JSON.stringify(o.exportName)} },`).join(`
|
|
1145
1145
|
`);return`${$}/**
|
|
1146
1146
|
* Push-consumer registry for the queues declared in \`lunora/queues.ts\`. The
|
|
1147
1147
|
* composed worker's \`queue(batch, env, ctx)\` entry routes each delivered batch
|
|
@@ -1156,7 +1156,7 @@ import { ${n} } from "../queues.js";
|
|
|
1156
1156
|
export const LUNORA_QUEUE_REGISTRY: QueueRegistry = {
|
|
1157
1157
|
${r}
|
|
1158
1158
|
};
|
|
1159
|
-
`},
|
|
1159
|
+
`},Pr=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)f(n.exportName,`workflow export "${n.exportName}"`),f(n.bindingName,`workflow binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}" },`).join(`
|
|
1160
1160
|
`);return{build:`
|
|
1161
1161
|
const workflows = createWorkflowContext(env, LUNORA_WORKFLOWS);
|
|
1162
1162
|
`,contextField:`
|
|
@@ -1165,7 +1165,7 @@ ${r}
|
|
|
1165
1165
|
const LUNORA_WORKFLOWS: ReadonlyArray<WorkflowBindingSpec> = [
|
|
1166
1166
|
${t}
|
|
1167
1167
|
];
|
|
1168
|
-
`}},
|
|
1168
|
+
`}},Mr=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)f(n.exportName,`queue export "${n.exportName}"`),f(n.bindingName,`queue binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}", name: ${JSON.stringify(n.name)} },`).join(`
|
|
1169
1169
|
`);return{build:`
|
|
1170
1170
|
const queues = createQueueContext(env, LUNORA_QUEUES);
|
|
1171
1171
|
`,contextField:`
|
|
@@ -1174,7 +1174,7 @@ ${t}
|
|
|
1174
1174
|
const LUNORA_QUEUES: ReadonlyArray<QueueBindingSpec> = [
|
|
1175
1175
|
${t}
|
|
1176
1176
|
];
|
|
1177
|
-
`}},
|
|
1177
|
+
`}},Fr=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)f(n.exportName,`agent export "${n.exportName}"`),f(n.bindingName,`agent binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}"${n.publicRun===!0?", publicRun: true":""} },`).join(`
|
|
1178
1178
|
`);return{build:`
|
|
1179
1179
|
const agents = createAgentContext(env, LUNORA_AGENTS);
|
|
1180
1180
|
`,contextField:`
|
|
@@ -1183,28 +1183,28 @@ ${t}
|
|
|
1183
1183
|
const LUNORA_AGENTS: ReadonlyArray<AgentBindingSpec> = [
|
|
1184
1184
|
${t}
|
|
1185
1185
|
];
|
|
1186
|
-
`}},
|
|
1186
|
+
`}},Nt=(e,t,n,r,o)=>({constant:`
|
|
1187
1187
|
${o}
|
|
1188
1188
|
const ${e}: ${t} = ${JSON.stringify(r,void 0,4)};
|
|
1189
1189
|
`,override:`
|
|
1190
1190
|
protected override ${n}(): ${t} {
|
|
1191
1191
|
return ${e};
|
|
1192
1192
|
}
|
|
1193
|
-
`}),
|
|
1193
|
+
`}),Br=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 Nt("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. */")},qr=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 Nt("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. */")},jr=e=>e?{imports:['import type { LunoraDatabaseLike as LunoraPaymentDbLike, LunoraPayment, PaymentsFromContextOptions } from "@lunora/payment";','import { paymentsFromContext } from "@lunora/payment";'],build:`
|
|
1194
1194
|
const payments: LunoraPayment = config.payment
|
|
1195
1195
|
? paymentsFromContext({ auth: { userId: userId ?? null }, db: db as unknown as LunoraPaymentDbLike }, config.payment(env))
|
|
1196
1196
|
: paymentStub;
|
|
1197
1197
|
`,configField:`
|
|
1198
1198
|
payment?: (env: Record<string, unknown>) => PaymentsFromContextOptions;`,contextField:`
|
|
1199
|
-
payments,`,stub:I("paymentStub: LunoraPayment",'throw new Error("ctx.payments: no payment configured. Pass \\`payment\\` to createShardDO().");',["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"],{cast:" as unknown as LunoraPayment",sync:["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"]})}:{build:"",configField:"",contextField:"",imports:[],stub:""},
|
|
1199
|
+
payments,`,stub:I("paymentStub: LunoraPayment",'throw new Error("ctx.payments: no payment configured. Pass \\`payment\\` to createShardDO().");',["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"],{cast:" as unknown as LunoraPayment",sync:["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"]})}:{build:"",configField:"",contextField:"",imports:[],stub:""},Wr=e=>e?{imports:['import type { X402Pay, X402PayConfig } from "@lunora/x402/pay";','import { lazyX402Pay } from "@lunora/x402/pay";'],build:`
|
|
1200
1200
|
const x402: X402Pay = config.x402
|
|
1201
1201
|
? lazyX402Pay(config.x402(env), { getSecret: (name: string) => secrets.get(name) })
|
|
1202
1202
|
: x402Stub;
|
|
1203
1203
|
`,configField:`
|
|
1204
|
-
x402?: (env: Record<string, unknown>) => X402PayConfig;`,stub:I("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:""},
|
|
1204
|
+
x402?: (env: Record<string, unknown>) => X402PayConfig;`,stub:I("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:""},Ur=(e,t,n,r,o)=>["AdvisorProcedure","AdvisoryFinding","DatabaseWriterLike","DataMigrationLike","DispatchBookmark","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"]:[]],fo=({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:g=!1,hasImages:y=!1,hasKv:u=!1,hasNotify:l=!1,hasPayments:b=!1,hasPipelines:R=!1,hasR2sql:x=!1,hasVectors:v=!0,hasX402:S=!1,maskMetadata:N,mutators:Q=[],queues:A=[],rlsMetadata:C,schema:w,schemaSnapshot:P,shapes:M=[],storageRules:ie,studioFeatures:le,useUmbrella:Z=!1,workflows:V=[]})=>{const L=ae(Z),ee=Q.length>0,k=M.length>0,Ae=P===void 0?"":$n(P),F=P===void 0?"":`
|
|
1205
1205
|
/** 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. */
|
|
1206
|
-
const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(
|
|
1207
|
-
`,ce=P===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",{build:de,configField:Oe,contextField:Ie,stub:Ce}=
|
|
1206
|
+
const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(Tn(P))}, json: ${JSON.stringify(Ae)} };
|
|
1207
|
+
`,ce=P===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",{build:de,configField:Oe,contextField:Ie,stub:Ce}=vr(a),ue=Nr(i),H=Rr(u),_=Sr(p,L.flags),G=Ar(s,p,L.flags),te=$r(l),pe=Tr(o),J=Or(c),j=Ir(y),W=Cr(g),U=Lr(d),B=Er(x),ne=Dr(R),{build:Le,contextField:ve,importLines:Re,specs:he}=Mr(A),{build:Ee,contextField:De,importLines:Se,specs:me}=_r(r,w.jurisdiction),{build:_e,contextField:Pe,importLines:$e,specs:Me}=Pr(V),{build:Fe,contextField:ge,importLines:fe,specs:Be}=Fr(n),{build:qe,configField:je,contextField:be,imports:ye,stub:Ze}=jr(b),{build:h,configField:We,imports:Te,stub:re}=Wr(S),Ot=e,It=t,et=C??{policies:[],roles:[]},Ct=N??{columns:[]},Lt=ie??{rules:[]},Et=le??{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:Dt,override:_t}=Br(V),{constant:Pt,override:Mt}=qr(A),K=v&&w.vectorIndexes.length>0,tt=new Set(w.tables.filter(m=>typeof m.shardMode=="object"&&m.shardMode.kind==="shardBy").map(m=>m.name)),Ne=K&&w.vectorIndexes.some(m=>tt.has(m.table)),we=w.tables.some(m=>m.shardMode==="global"),Ue=w.tables.some(m=>m.shardMode==="global"&&m.globalBackend==="hyperdrive"),nt=w.tables.some(m=>m.shardMode==="global"&&m.globalBackend!=="hyperdrive"),oe=w.tables.some(m=>m.externalSource!==void 0),rt=w.tables.some(m=>m.memory===!0),Ke=w.tables.some(m=>m.shardMode!=="global"&&m.searchIndexes.length>0);if(nt&&Ue)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 Qe=w.tables.length>0,Ft=mr(w),Bt=fr(w),qt=kr(w),jt=gr(w),ot=br(w),at=Ur(K,V.length>0,A.length>0,p,Ke);k&&at.push("WhereInput");const st=xr(we),Wt=k?`
|
|
1208
1208
|
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 {
|
|
1209
1209
|
const shape = LUNORA_SHAPES[name];
|
|
1210
1210
|
|
|
@@ -1226,20 +1226,26 @@ const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.st
|
|
|
1226
1226
|
ownerField: (schema as unknown as { tables: Record<string, { ownerField?: string }> }).tables[shape.table]?.ownerField,
|
|
1227
1227
|
}) as unknown as WhereInput;
|
|
1228
1228
|
|
|
1229
|
-
// AND-compose with the
|
|
1230
|
-
//
|
|
1231
|
-
//
|
|
1232
|
-
// (
|
|
1233
|
-
//
|
|
1229
|
+
// AND-compose with the read policies this SHAPE declares
|
|
1230
|
+
// (\`defineShape({ use: [guard] })\`, pre-indexed into
|
|
1231
|
+
// \`shape.rlsRegistry\`). A shape runs no procedure, so the
|
|
1232
|
+
// \`.use(rls(...))\` middleware never fires; without this merge its
|
|
1233
|
+
// reads would bypass the read policies it opted into.
|
|
1234
|
+
// \`composeShapeReadWhere\` evaluates them under this same trusted ctx
|
|
1234
1235
|
// and fails closed under a \`.rls("required")\` schema for a
|
|
1235
|
-
// non-\`.public()
|
|
1236
|
+
// non-\`.public()\` table the shape declared no read policy for.
|
|
1237
|
+
//
|
|
1238
|
+
// The registry is the shape's OWN — never one folded from every
|
|
1239
|
+
// registered function. A project-wide union let one admin-only
|
|
1240
|
+
// procedure's allow-all read policy unrestrict every shape on the
|
|
1241
|
+
// table; see the SCOPE note in \`shape-read-base.ts\`.
|
|
1236
1242
|
//
|
|
1237
1243
|
// It is NOT identical to the request-time path, and must not be
|
|
1238
1244
|
// described as such: roles come from the identity's \`roles\` claim
|
|
1239
1245
|
// only, because no middleware runs here to contribute
|
|
1240
1246
|
// \`ctx.auth.roles\`. Derive roles at the identity if a policy gates
|
|
1241
1247
|
// on them — see \`shape-read-base.ts\`.
|
|
1242
|
-
const effectiveWhere = composeShapeReadWhere(
|
|
1248
|
+
const effectiveWhere = composeShapeReadWhere(shape.rlsRegistry, {
|
|
1243
1249
|
ctx,
|
|
1244
1250
|
identity: identity?.identity ?? null,
|
|
1245
1251
|
rlsRequired: (schema as unknown as { rlsMode?: string }).rlsMode === "required",
|
|
@@ -1262,25 +1268,28 @@ const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.st
|
|
|
1262
1268
|
|
|
1263
1269
|
return { columns: shape.columns, effectiveWhere, global: isGlobal, table: shape.table };
|
|
1264
1270
|
}
|
|
1265
|
-
`:"",
|
|
1271
|
+
`:"",it=k?[...new Set(et.policies.filter(m=>m.on==="read"&&m.table!=="").map(m=>m.table))].toSorted((m,Sn)=>m.localeCompare(Sn)):[],lt=it.length>0?`
|
|
1272
|
+
/** Refuses to boot a shape that would replicate around the read policies its table is governed by (\`defineShape({ use })\` is how a shape opts in; \`use: []\` acknowledges an ungoverned one). */
|
|
1273
|
+
assertShapesDeclareReadPolicies(LUNORA_SHAPES, ${JSON.stringify(it)}, (schema as unknown as { rlsMode?: string }).rlsMode === "required");
|
|
1274
|
+
`:"",Ut=ee?`
|
|
1266
1275
|
protected override isCustomMutator(functionPath: string): boolean {
|
|
1267
1276
|
return LUNORA_MUTATOR_PATHS.has(functionPath);
|
|
1268
1277
|
}
|
|
1269
|
-
`:"",
|
|
1270
|
-
vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",
|
|
1271
|
-
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;`:"",
|
|
1272
|
-
hyperdriveGlobal?: (env: Record<string, unknown>, request?: { cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",
|
|
1273
|
-
sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",
|
|
1278
|
+
`:"",Kt=k?"assertShapeShardable, ":"",Qt=lt===""?"":"assertShapesDeclareReadPolicies, ",ke=[`import type { ${at.join(", ")} } from "${L.do}";`,`import { applyCdcChanges, ${Ke?"backfillSearchIndexes, ":""}buildReprojectionMigration, ${rt?"clearMemoryTables, ":""}${Kt}createReadFootprint, createShardCtxDb, exportShardRows, importShardRows, ${oe?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}markUnvouchableReads, ${Ne?"ROOT_SHARD_NAME, ":""}runDataMigration, runShardMigrations, ${st.importFragment}ShardDO as ShardDOBase } from "${L.do}";`,...oe?[`import type { ExternalSourceLike, SourceClientLike, TraceRefLike } from "${L.do}";`]:[],k?`import { asBucketStorage, ${Qt}beginDeferredSchedules, composeShapeReadWhere, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes, withDeferredSchedules } from "${L.server}";`:`import { asBucketStorage, beginDeferredSchedules, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes, withDeferredSchedules } from "${L.server}";`];Qe&&ke.push(`import { bindOrm, bindTableFacade } from "${L.server}";`),K&&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,...H.importLines,..._.importLines,...te.importLines,...pe.importLines,...J.importLines,...j.importLines,...W.importLines,...U.importLines,...B.importLines,...ne.importLines,...Se,...$e,...Re,...fe,...ye,...Te,"",'import schema from "../schema.js";',`import { ${["LUNORA_FUNCTIONS","LUNORA_LIFECYCLE_HOOKS","LUNORA_MIGRATIONS",...ee?["LUNORA_MUTATOR_PATHS"]:[],...k?["LUNORA_SHAPES"]:[]].join(", ")} } from "./functions.js";`);const Vt=K?`
|
|
1279
|
+
vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",Ht=nt?`
|
|
1280
|
+
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;`:"",Gt=Ue?`
|
|
1281
|
+
hyperdriveGlobal?: (env: Record<string, unknown>, request?: { cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",Jt=oe?`
|
|
1282
|
+
sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",zt='throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");',Yt='throw new Error("ctx.vectors: no vectors configured. Pass `vectors` to createShardDO().");',Xt='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().");',en=we?I("globalDbStub: DatabaseWriterLike",zt,["aggregate","count","delete","findFirst","findFirstOrThrow","findMany","get","groupBy","insert","normalizeId","patch","query","rank","rankPage","replace"],{sync:["normalizeId","query"]}):"",tn=K?I("vectorsStub: VectorSearchLike",Yt,["deleteByIds","getByIds","query","upsert","upsertNow"]):"",nn=Ne?`
|
|
1274
1283
|
const vectorShardKey = this.currentShardKey();
|
|
1275
|
-
`:"",
|
|
1284
|
+
`:"",rn=Ne?"namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, ":"",on=Ne?`, { namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, shardedIndexNames: [${w.vectorIndexes.filter(m=>tt.has(m.table)).map(m=>JSON.stringify(m.name)).join(", ")}] }`:"",an=K?`
|
|
1276
1285
|
let vectors: VectorSearchLike;
|
|
1277
1286
|
let onWrite: WriteHook | undefined;
|
|
1278
1287
|
|
|
1279
1288
|
if (config.vectors) {
|
|
1280
1289
|
const lunora = createVectors({ indexes: config.vectors(env) });
|
|
1281
|
-
${
|
|
1282
|
-
vectors = createContextVectors(lunora${
|
|
1283
|
-
onWrite = createVectorSyncHook({ ${
|
|
1290
|
+
${nn}
|
|
1291
|
+
vectors = createContextVectors(lunora${on});
|
|
1292
|
+
onWrite = createVectorSyncHook({ ${rn}schema: schema as unknown as VectorSchemaLike, vectors });
|
|
1284
1293
|
} else {
|
|
1285
1294
|
vectors = vectorsStub;
|
|
1286
1295
|
onWrite = undefined;
|
|
@@ -1292,7 +1301,7 @@ ${en}
|
|
|
1292
1301
|
// \`__cdc_log\`. Wrapped AFTER \`onWrite\` is built so the write-through
|
|
1293
1302
|
// vector-sync hook keeps calling the bare facade.
|
|
1294
1303
|
vectors = markUnvouchableReads(vectors, options.onRead, ["getByIds", "query"]);
|
|
1295
|
-
`:"",
|
|
1304
|
+
`:"",sn=`{
|
|
1296
1305
|
...this.ctxDbTuning(),
|
|
1297
1306
|
auth: { identity: identity ?? null, userId: userId ?? null },
|
|
1298
1307
|
broadcast: (delta) => {
|
|
@@ -1330,7 +1339,7 @@ ${en}
|
|
|
1330
1339
|
sql: this.sql as SqlExec,
|
|
1331
1340
|
storage,${we?`
|
|
1332
1341
|
globalDb,`:""}
|
|
1333
|
-
}`,
|
|
1342
|
+
}`,ln=` /**
|
|
1334
1343
|
* The bare writer every admin/maintenance entry point writes through.
|
|
1335
1344
|
*
|
|
1336
1345
|
* Admin and maintenance writes go through the SAME reactive-cache hooks as a
|
|
@@ -1362,11 +1371,11 @@ ${en}
|
|
|
1362
1371
|
schema: schema as unknown as SchemaLike,
|
|
1363
1372
|
sql: this.sql as SqlExec,
|
|
1364
1373
|
});
|
|
1365
|
-
}`,z=(
|
|
1366
|
-
vectors,`:"",
|
|
1367
|
-
orm: bindOrm(facade),`:"",Ve=Ue?"config.hyperdriveGlobal":"config.d1",
|
|
1374
|
+
}`,z=(m="")=>` const writer = this.adminWriter(${m});`,cn=K?`
|
|
1375
|
+
vectors,`:"",dn=Qe?`
|
|
1376
|
+
orm: bindOrm(facade),`:"",Ve=Ue?"config.hyperdriveGlobal":"config.d1",un=we?` const globalRequest = { ...this.globalCdcOptions(config.cdc ?? false), bookmark: this.getInboundBookmark(), identity, onBookmark: (bookmarkValue: string | undefined) => { if (options.bookmarks !== undefined) { options.bookmarks.value = bookmarkValue; } }, userId };
|
|
1368
1377
|
const globalDb: DatabaseWriterLike = ${Ve}?.(env, globalRequest) ?? globalDbStub;
|
|
1369
|
-
`:"",
|
|
1378
|
+
`:"",pn=k&&we?`
|
|
1370
1379
|
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 }>> {
|
|
1371
1380
|
const env = this.env as Record<string, unknown>;
|
|
1372
1381
|
// A shape read performs no writes, so the widened request only needs
|
|
@@ -1411,17 +1420,17 @@ ${en}
|
|
|
1411
1420
|
|
|
1412
1421
|
return globalDb.cdcChangedTables?.(sinceSeq, { cursorOnly });
|
|
1413
1422
|
}
|
|
1414
|
-
`:"",
|
|
1423
|
+
`:"",hn=oe?`
|
|
1415
1424
|
const sourceClientCache = new WeakMap<object, Map<string, SourceClientLike>>();
|
|
1416
1425
|
const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
|
|
1417
|
-
`:"",
|
|
1426
|
+
`:"",mn=`
|
|
1418
1427
|
protected override async runShardInit(): Promise<void> {
|
|
1419
1428
|
this.ensureMigrated();
|
|
1420
|
-
${
|
|
1429
|
+
${rt?` clearMemoryTables(this.sql as SqlExec, schema as unknown as SchemaLike);
|
|
1421
1430
|
`:""}
|
|
1422
1431
|
await this.dispatchShardInit();
|
|
1423
1432
|
}
|
|
1424
|
-
`,
|
|
1433
|
+
`,gn=oe?`
|
|
1425
1434
|
protected override async pollExternalSources(trace?: TraceRefLike): Promise<number | undefined> {
|
|
1426
1435
|
const env = (this.env ?? {}) as Record<string, unknown>;
|
|
1427
1436
|
const sourced = Object.entries((schema as unknown as SchemaLike).tables)
|
|
@@ -1561,7 +1570,7 @@ ${nt?` clearMemoryTables(this.sql as SqlExec, schema as unknown as Sc
|
|
|
1561
1570
|
|
|
1562
1571
|
return nextDueAt;
|
|
1563
1572
|
}
|
|
1564
|
-
`:"",
|
|
1573
|
+
`:"",fn=ot.length>0,bn=`
|
|
1565
1574
|
public constructor(state: ShardDOState, env: unknown) {
|
|
1566
1575
|
super(state, env, {
|
|
1567
1576
|
// Every writer this file builds spreads the ctxDbTuning() slice —
|
|
@@ -1584,7 +1593,7 @@ ${oe?`
|
|
|
1584
1593
|
if (autoSourced) {
|
|
1585
1594
|
void this.scheduleSourcePoll();
|
|
1586
1595
|
}
|
|
1587
|
-
`:""}${
|
|
1596
|
+
`:""}${fn?`
|
|
1588
1597
|
if (LUNORA_TTL_SWEEPS.length > 0) {
|
|
1589
1598
|
void this.scheduleTtlSweep();
|
|
1590
1599
|
}
|
|
@@ -1597,21 +1606,21 @@ ${oe?`
|
|
|
1597
1606
|
protected override isPaidFunction(functionPath: string): boolean {
|
|
1598
1607
|
return LUNORA_FUNCTIONS[functionPath]?.x402 !== undefined;
|
|
1599
1608
|
}
|
|
1600
|
-
`,
|
|
1609
|
+
`,yn=Qe?`
|
|
1601
1610
|
const facade = db as unknown as Record<string, ReturnType<typeof bindTableFacade>>;
|
|
1602
|
-
${w.tables.map(
|
|
1611
|
+
${w.tables.map(m=>` facade[${JSON.stringify(m.name)}] = bindTableFacade(db, ${JSON.stringify(m.name)});`).join(`
|
|
1603
1612
|
`)}
|
|
1604
|
-
`:"",
|
|
1613
|
+
`:"",wn=`${ue.build}${H.build}${_.build}${J.build}${pe.build}
|
|
1605
1614
|
const secrets = createSecrets(env);
|
|
1606
|
-
`,
|
|
1607
|
-
secrets,`,
|
|
1615
|
+
`,kn=`${ue.contextField}${H.contextField}${_.contextField}${te.contextField}${J.contextField}${pe.contextField}
|
|
1616
|
+
secrets,`,xn=te.build,ct=y||g||d||x||R||S,vn=ct?`
|
|
1608
1617
|
// ActionCtx-only helpers (external, non-deterministic I/O): constructed
|
|
1609
1618
|
// and attached only for an \`action\` so query/mutation ctx never carry them.
|
|
1610
1619
|
if (isAction) {
|
|
1611
|
-
${j.build}${W.build}${U.build}${B.build}${ne.build}${
|
|
1620
|
+
${j.build}${W.build}${U.build}${B.build}${ne.build}${h}${[...y?[" ctx.images = images;"]:[],...g?[" ctx.sql = sql;"]:[],...d?[" ctx.browser = browser;"]:[],...x?[" ctx.r2sql = r2sql;"]:[],...R?[" ctx.pipelines = pipelines;"]:[],...S?[" ctx.x402 = x402;"]:[]].join(`
|
|
1612
1621
|
`)}
|
|
1613
1622
|
}
|
|
1614
|
-
`:"",
|
|
1623
|
+
`:"",Rn=ct?` const isAction = LUNORA_FUNCTIONS[options.functionPath ?? ""]?.kind === "action";
|
|
1615
1624
|
`:"";return`${$}${ke.join(`
|
|
1616
1625
|
`)}
|
|
1617
1626
|
|
|
@@ -1622,41 +1631,41 @@ interface FunctionReference {
|
|
|
1622
1631
|
}
|
|
1623
1632
|
|
|
1624
1633
|
/** Foreign-key columns per table (\`v.id("target")\` fields) for the data browser. */
|
|
1625
|
-
const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(
|
|
1634
|
+
const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(Ft,void 0,4)};
|
|
1626
1635
|
|
|
1627
1636
|
/** Declared indexes per table (secondary, search, geo, rank, vector) for the schema viewer. */
|
|
1628
|
-
const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(
|
|
1637
|
+
const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(Bt,void 0,4)};
|
|
1629
1638
|
|
|
1630
1639
|
/** Columns per table (typed, with PK/FK markers) for the studio's schema diagram, served via \`__lunora_admin__:describeTable\`. */
|
|
1631
1640
|
const LUNORA_TABLE_COLUMNS: Record<
|
|
1632
1641
|
string,
|
|
1633
1642
|
Array<{ bucket?: string; enumValues?: string[]; isStorage?: boolean; name: string; nullable?: boolean; optional: boolean; pk?: boolean; ref?: string; type: string }>
|
|
1634
|
-
> = ${JSON.stringify(
|
|
1643
|
+
> = ${JSON.stringify(qt,void 0,4)};
|
|
1635
1644
|
|
|
1636
1645
|
/** Storage-key columns per table (\`v.storage(...)\` fields) for the file browser's records↔files join. */
|
|
1637
|
-
const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify(
|
|
1646
|
+
const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify(jt,void 0,4)};
|
|
1638
1647
|
|
|
1639
1648
|
/** Declarative TTL policies (\`.ttl(field, { after? })\`) the DO alarm sweep auto-expires rows for. */
|
|
1640
|
-
const LUNORA_TTL_SWEEPS: Array<{ after?: number; field: string; softDeleteField?: string; table: string }> = ${JSON.stringify(
|
|
1649
|
+
const LUNORA_TTL_SWEEPS: Array<{ after?: number; field: string; softDeleteField?: string; table: string }> = ${JSON.stringify(ot,void 0,4)};
|
|
1641
1650
|
|
|
1642
1651
|
/** Static schema advisories (computed by @lunora/advisor at codegen time) served via \`__lunora_admin__:getAdvisories\`. */
|
|
1643
|
-
const LUNORA_ADVISORIES: AdvisoryFinding[] = ${JSON.stringify(
|
|
1652
|
+
const LUNORA_ADVISORIES: AdvisoryFinding[] = ${JSON.stringify(Ot,void 0,4)};
|
|
1644
1653
|
|
|
1645
1654
|
/** Every declared procedure (discovered by @lunora/codegen) served via \`__lunora_admin__:getAdvisorProcedures\` — the health map's denominator. */
|
|
1646
|
-
const LUNORA_ADVISOR_PROCEDURES: AdvisorProcedure[] = ${JSON.stringify(
|
|
1655
|
+
const LUNORA_ADVISOR_PROCEDURES: AdvisorProcedure[] = ${JSON.stringify(It,void 0,4)};
|
|
1647
1656
|
|
|
1648
1657
|
/** Read-only RLS metadata (policies + roles discovered from \`.use(rls(...))\` chains) served via \`__lunora_admin__:rlsPolicies\` for the studio's RLS inspector. */
|
|
1649
|
-
const LUNORA_RLS_METADATA: RlsPoliciesResult = ${JSON.stringify(
|
|
1650
|
-
|
|
1658
|
+
const LUNORA_RLS_METADATA: RlsPoliciesResult = ${JSON.stringify(et,void 0,4)};
|
|
1659
|
+
${lt}
|
|
1651
1660
|
/** 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. */
|
|
1652
|
-
const LUNORA_MASK_METADATA: MaskPoliciesResult = ${JSON.stringify(
|
|
1661
|
+
const LUNORA_MASK_METADATA: MaskPoliciesResult = ${JSON.stringify(Ct,void 0,4)};
|
|
1653
1662
|
|
|
1654
1663
|
/** Read-only storage access-rule metadata (discovered from \`.use(storageRules(...))\` chains) served via \`__lunora_admin__:storageRules\` for the studio's access-rules view. */
|
|
1655
|
-
const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(
|
|
1664
|
+
const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(Lt,void 0,4)};
|
|
1656
1665
|
|
|
1657
1666
|
/** 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. */
|
|
1658
|
-
const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(
|
|
1659
|
-
${F}${G.constant}${
|
|
1667
|
+
const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(Et,void 0,4)};
|
|
1668
|
+
${F}${G.constant}${Dt}${Pt}${me}${Me}${he}${Be}
|
|
1660
1669
|
export interface ShardDOConfig {
|
|
1661
1670
|
/** Opt into change-data-capture: records a post-image to \`__cdc_log\` on every write (backs streaming export + replay-PITR). */
|
|
1662
1671
|
cdc?: boolean;
|
|
@@ -1670,9 +1679,9 @@ export interface ShardDOConfig {
|
|
|
1670
1679
|
observability?: (env: Record<string, unknown>) => TelemetrySink | undefined;
|
|
1671
1680
|
/** \`unknown\` because \`@lunora/scheduler\`'s \`Scheduler\` is not assignable to \`SchedulerLike\`; the shard casts it. */
|
|
1672
1681
|
scheduler?: (env: Record<string, unknown>) => unknown;
|
|
1673
|
-
storage?: (env: Record<string, unknown>) => unknown;${
|
|
1682
|
+
storage?: (env: Record<string, unknown>) => unknown;${Vt}${Oe}${H.configField}${_.configField}${J.configField}${j.configField}${W.configField}${U.configField}${B.configField}${ne.configField}${je}${We}${Ht}${Gt}${Jt}
|
|
1674
1683
|
}
|
|
1675
|
-
${I("schedulerStub",
|
|
1684
|
+
${I("schedulerStub",Xt,["cancel","runAfter","runAt"])}${I("storageStub",Zt,["delete","download","getMetadata","getSignedUrl","getUrl","head","list","upload"],{sync:["getUrl"]})}${en}${hn}${tn}${Ce}${H.stub}${_.stub}${J.stub}${j.stub}${W.stub}${U.stub}${B.stub}${ne.stub}${Ze}${re}
|
|
1676
1685
|
// Bound in-process \`ctx.run*\` composition depth so a self- or cyclically-
|
|
1677
1686
|
// referencing call fails loudly with a clear error instead of overflowing the
|
|
1678
1687
|
// stack. Tracked across the awaited handler chain (one DO invocation is
|
|
@@ -1746,10 +1755,10 @@ const dispatchRun = async (
|
|
|
1746
1755
|
* from the worker entry so wrangler binds it by name.
|
|
1747
1756
|
*/
|
|
1748
1757
|
export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOState, env: unknown) => ShardDOBase =>
|
|
1749
|
-
class extends ShardDOBase {${
|
|
1758
|
+
class extends ShardDOBase {${bn}
|
|
1750
1759
|
private migrated = false;
|
|
1751
1760
|
|
|
1752
|
-
public override async handleRpc(functionPath: string, args: Record<string, unknown>, headroom?: TransactionHeadroomTracker, scope?: QueryReadScope): Promise<unknown> {
|
|
1761
|
+
public override async handleRpc(functionPath: string, args: Record<string, unknown>, headroom?: TransactionHeadroomTracker, scope?: QueryReadScope, bookmarks?: DispatchBookmark): Promise<unknown> {
|
|
1753
1762
|
const registered = LUNORA_FUNCTIONS[functionPath];
|
|
1754
1763
|
|
|
1755
1764
|
// Internal functions are reachable server-side only: via \`ctx.run*\`
|
|
@@ -1776,7 +1785,7 @@ export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOSt
|
|
|
1776
1785
|
// our dep set — and ours out of theirs. A dispatch with no scope (a
|
|
1777
1786
|
// mutation, an action, a cache-less shard) builds unbound hooks that
|
|
1778
1787
|
// stamp no deps.
|
|
1779
|
-
const ctx = this.buildCtx({ functionPath, headroom, scope, trusted: registered.lifecycle === "init" });
|
|
1788
|
+
const ctx = this.buildCtx({ bookmarks, functionPath, headroom, scope, trusted: registered.lifecycle === "init" });
|
|
1780
1789
|
|
|
1781
1790
|
// A mutation's writes must commit all-or-nothing, so its dispatch runs
|
|
1782
1791
|
// under \`runMutationTransaction\` — the ONE place that opens the span,
|
|
@@ -1897,7 +1906,7 @@ export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOSt
|
|
|
1897
1906
|
protected override isMutationFunction(functionPath: string): boolean {
|
|
1898
1907
|
return LUNORA_FUNCTIONS[functionPath]?.kind === "mutation";
|
|
1899
1908
|
}
|
|
1900
|
-
${
|
|
1909
|
+
${st.override}
|
|
1901
1910
|
protected override async executeSubscription(functionPath: string, args: Record<string, unknown>, identity?: { identity?: Record<string, unknown>; userId?: string }): Promise<{ ranges?: Map<string, KeyRange[]>; result: unknown; tables: Set<string> } | null> {
|
|
1902
1911
|
const registered = LUNORA_FUNCTIONS[functionPath];
|
|
1903
1912
|
|
|
@@ -1938,11 +1947,11 @@ ${at.override}
|
|
|
1938
1947
|
iterator: (signal) => (registered.handler as (context: unknown, args: Record<string, unknown>, signal: AbortSignal) => AsyncIterable<unknown>)(this.buildCtx({ functionPath, identity }), args, signal),
|
|
1939
1948
|
};
|
|
1940
1949
|
}
|
|
1941
|
-
${
|
|
1950
|
+
${Ut}${Wt}${pn}${gn}
|
|
1942
1951
|
protected override lifecycleHookPaths(event: "connect" | "disconnect" | "init" | "reactor"): readonly string[] {
|
|
1943
1952
|
return LUNORA_LIFECYCLE_HOOKS[event];
|
|
1944
1953
|
}
|
|
1945
|
-
${
|
|
1954
|
+
${mn}
|
|
1946
1955
|
// One \`onQueryChange\` dispatch. Mirrors \`executeSubscription\` — the
|
|
1947
1956
|
// socket-terminated half of the same reactivity — and differs only in who
|
|
1948
1957
|
// consumes the result: the base's \`dispatchReactors\` stores the digest as
|
|
@@ -2021,7 +2030,7 @@ ${hn}
|
|
|
2021
2030
|
protected override studioFeatures(): StudioFeaturesResult {
|
|
2022
2031
|
return LUNORA_STUDIO_FEATURES;
|
|
2023
2032
|
}
|
|
2024
|
-
${G.evaluateOverride}${G.subscriptionOverride}${
|
|
2033
|
+
${G.evaluateOverride}${G.subscriptionOverride}${_t}${Mt}
|
|
2025
2034
|
protected override advisories(): AdvisoryFinding[] {
|
|
2026
2035
|
return LUNORA_ADVISORIES;
|
|
2027
2036
|
}
|
|
@@ -2030,7 +2039,7 @@ ${G.evaluateOverride}${G.subscriptionOverride}${Et}${Dt}
|
|
|
2030
2039
|
return LUNORA_ADVISOR_PROCEDURES;
|
|
2031
2040
|
}
|
|
2032
2041
|
|
|
2033
|
-
${
|
|
2042
|
+
${ln}
|
|
2034
2043
|
|
|
2035
2044
|
protected override async runShardDataMigration(args: RunShardMigrationArgs): Promise<MigrationRunResult> {
|
|
2036
2045
|
this.ensureMigrated();
|
|
@@ -2223,7 +2232,7 @@ ${Ke?`
|
|
|
2223
2232
|
return backfillSearchIndexes(this.sql as SqlExec, schema as unknown as SchemaLike, options);
|
|
2224
2233
|
}
|
|
2225
2234
|
`:""}
|
|
2226
|
-
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 {
|
|
2235
|
+
private buildCtx(options: { bookmarks?: DispatchBookmark; 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 {
|
|
2227
2236
|
const env = (this.env ?? {}) as Record<string, unknown>;
|
|
2228
2237
|
// When the caller threads an explicit identity (subscription seed /
|
|
2229
2238
|
// refresh — both run in deferred/interleaved contexts), use it by
|
|
@@ -2232,7 +2241,7 @@ ${Ke?`
|
|
|
2232
2241
|
// dispatch path) fall back to the per-request fields as before.
|
|
2233
2242
|
const userId = options.identity ? options.identity.userId : this.getCurrentUserId();
|
|
2234
2243
|
const identity = options.identity ? options.identity.identity : this.getCurrentIdentity();
|
|
2235
|
-
${
|
|
2244
|
+
${an}${de}${wn}${Ee}${_e}${Le}${Fe}
|
|
2236
2245
|
// Which dispatch this ctx belongs to. Drives the two deferral facades
|
|
2237
2246
|
// below and the \`ctx.run*\` caller guard; a ctx built for an
|
|
2238
2247
|
// admin/lifecycle path has no registered function, and so no kind.
|
|
@@ -2319,13 +2328,13 @@ ${rn}${de}${bn}${Ee}${De}${Le}${Fe}
|
|
|
2319
2328
|
// so both write to the same trace.
|
|
2320
2329
|
const span = this.makeDispatchSpan(traceAnchor, observability);
|
|
2321
2330
|
|
|
2322
|
-
${
|
|
2331
|
+
${un} // \`ctx.db\`, wrapped in automatic instrumentation: by default this
|
|
2323
2332
|
// adds aggregate counters (call count, total time, per-operation
|
|
2324
2333
|
// breakdown) to the wide event rather than a span per call, so a
|
|
2325
2334
|
// handler making hundreds of queries stays readable. See
|
|
2326
2335
|
// \`instrumentDatabase\` for the \`"spans"\` / \`"off"\` levels.
|
|
2327
|
-
const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${
|
|
2328
|
-
${
|
|
2336
|
+
const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${sn}), logFunctionPath, traceAnchor, observability);
|
|
2337
|
+
${yn}${qe}
|
|
2329
2338
|
|
|
2330
2339
|
// \`ctx.trace\` / \`ctx.metrics\`: spans and measurements to the same sink.
|
|
2331
2340
|
// The trace anchor is threaded explicitly for the same reason \`identity\`
|
|
@@ -2333,7 +2342,7 @@ ${fn}${qe}
|
|
|
2333
2342
|
// writing mutation's trace from the shared per-request field.
|
|
2334
2343
|
const trace = this.makeTracer(logFunctionPath, observability, traceAnchor);
|
|
2335
2344
|
const metrics = this.makeMetrics(logFunctionPath, observability);
|
|
2336
|
-
${
|
|
2345
|
+
${xn}
|
|
2337
2346
|
// \`ctx.now\`: the wall-clock instant (epoch ms) this function began,
|
|
2338
2347
|
// captured ONCE so the whole handler body sees a single stable value.
|
|
2339
2348
|
// Query/mutation handlers must be deterministic (they may be re-run on
|
|
@@ -2356,13 +2365,13 @@ ${wn}
|
|
|
2356
2365
|
ip: this.getCurrentIp(),
|
|
2357
2366
|
log,
|
|
2358
2367
|
metrics,
|
|
2359
|
-
now,${
|
|
2368
|
+
now,${dn}
|
|
2360
2369
|
scheduler,
|
|
2361
2370
|
span,
|
|
2362
2371
|
storage: contextStorage,
|
|
2363
|
-
trace,${
|
|
2372
|
+
trace,${cn}${Ie}${kn}${be}${De}${Pe}${ve}${ge}
|
|
2364
2373
|
};
|
|
2365
|
-
${
|
|
2374
|
+
${Rn}${vn}
|
|
2366
2375
|
ctx.runAction = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("action", reference.__lunoraRef, fnArgs, ctx, contextKind);
|
|
2367
2376
|
// The composed mutation runs under the SAME wrapper the top-level RPC
|
|
2368
2377
|
// uses, so "do the transactional work in a mutation and call it from the
|
|
@@ -2387,7 +2396,7 @@ ${xn}${kn}
|
|
|
2387
2396
|
reference.__lunoraRef,
|
|
2388
2397
|
fnArgs,
|
|
2389
2398
|
runOptions?.untracked === true
|
|
2390
|
-
? this.buildCtx({ functionPath: options.functionPath, headroom: options.headroom, identity: { identity, userId }, scope: options.scope })
|
|
2399
|
+
? this.buildCtx({ bookmarks: options.bookmarks, functionPath: options.functionPath, headroom: options.headroom, identity: { identity, userId }, scope: options.scope })
|
|
2391
2400
|
: ctx,
|
|
2392
2401
|
contextKind,
|
|
2393
2402
|
);
|
|
@@ -2395,24 +2404,24 @@ ${xn}${kn}
|
|
|
2395
2404
|
return ctx;
|
|
2396
2405
|
}
|
|
2397
2406
|
};
|
|
2398
|
-
`},Xe=e=>{switch(e.kind){case"array":case"object":case"record":case"union":return{builder:"text",mode:"json",notNull:!0,typeAnnotation:O(e)};case"bigint":return{builder:"blob",mode:"bigint",notNull:!0};case"boolean":return{builder:"integer",mode:"boolean",notNull:!0};case"bytes":return{builder:"blob",mode:"buffer",notNull:!0};case"date":case"timestamp":return{builder:"integer",notNull:!0};case"from":return{builder:"text",notNull:!0,typeAnnotation:O(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?Xe(e.inner):{builder:"text",notNull:!1},notNull:!1};case"storage":case"string":return{builder:"text",notNull:!0};default:return{builder:"text",notNull:!0}}}
|
|
2407
|
+
`},Xe=e=>{switch(e.kind){case"array":case"object":case"record":case"union":return{builder:"text",mode:"json",notNull:!0,typeAnnotation:O(e)};case"bigint":return{builder:"blob",mode:"bigint",notNull:!0};case"boolean":return{builder:"integer",mode:"boolean",notNull:!0};case"bytes":return{builder:"blob",mode:"buffer",notNull:!0};case"date":case"timestamp":return{builder:"integer",notNull:!0};case"from":return{builder:"text",notNull:!0,typeAnnotation:O(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?Xe(e.inner):{builder:"text",notNull:!1},notNull:!1};case"storage":case"string":return{builder:"text",notNull:!0};default:return{builder:"text",notNull:!0}}},At=(e,t)=>{const n=se(e);return n.kind==="id"&&n.tableName!==void 0&&t.has(n.tableName)?n.tableName:void 0},Kr=(e,t,n)=>{f(e,"drizzle column name");const r=Xe(t),o=r.mode?`, { mode: "${r.mode}" }`:"";let s=`${r.builder}("${e}"${o})`;r.typeAnnotation&&(s+=`.$type<${r.typeAnnotation}>()`);const i=At(t,n);return i!==void 0&&(s+=`.references((): AnySQLiteColumn => ${i}._id)`),r.notNull&&(s+=".notNull()"),s},Qr=e=>{const t=e.unique?"uniqueIndex":"index",n=e.fields.map(r=>(f(r,"drizzle index field"),`t.${r}`)).join(", ");return` ${Y(e.name)}: ${t}(${JSON.stringify(e.name)}).on(${n}),`},Vr=(e,t)=>{f(e.name,"table name");const n=[' _id: text("_id").primaryKey(),',' _creationTime: integer("_creationTime").notNull(),',...Object.entries(e.shape).map(([o,s])=>` ${o}: ${Kr(o,s,t)},`)].join(`
|
|
2399
2408
|
`),r=e.indexes.length>0?`, (t) => ({
|
|
2400
|
-
${e.indexes.map(o=>
|
|
2409
|
+
${e.indexes.map(o=>Qr(o)).join(`
|
|
2401
2410
|
`)}
|
|
2402
2411
|
})`:"";return`export const ${e.name} = sqliteTable("${e.name}", {
|
|
2403
2412
|
${n}
|
|
2404
|
-
}${r});`},
|
|
2405
|
-
`;const n=ae(t),r=new Set(e.map(
|
|
2413
|
+
}${r});`},Hr=e=>e.typeAnnotation?.includes('Id<"')??!1,Gr=(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=Xe(a);n.add(c.builder),s=s||Hr(c),o=o||At(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}},pt=(e,t=!1)=>{if(e.length===0)return`${$}export {};
|
|
2414
|
+
`;const n=ae(t),r=new Set(e.map(g=>g.name)),{columns:o,indexes:s,needsAnyColumn:i,needsId:a}=Gr(e,r),c=[...s,...o].toSorted((g,y)=>g.localeCompare(y)),d=e.map(g=>Vr(g,r)).join(`
|
|
2406
2415
|
|
|
2407
|
-
`),
|
|
2416
|
+
`),p=[i?`import type { AnySQLiteColumn } from "${n.serverDrizzle}";
|
|
2408
2417
|
`:"",a?`import type { Id } from "./dataModel.js";
|
|
2409
2418
|
`:""].join("");return`${$}import { ${c.join(", ")} } from "${n.serverDrizzle}";
|
|
2410
|
-
${
|
|
2419
|
+
${p}
|
|
2411
2420
|
${d}
|
|
2412
|
-
`},
|
|
2421
|
+
`},bo=(e,t=!1)=>{const n=e.tables.filter(o=>o.shardMode==="global"),r=e.tables.filter(o=>o.shardMode!=="global");return{global:E(pt(n,t),Je),shard:E(pt(r,t),Je)}},yo=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(`
|
|
2413
2422
|
`),r=n.length>0?`
|
|
2414
2423
|
${n}
|
|
2415
|
-
`:"",o=[...t.entries()].map(([i,a])=>{const c=a.map(d=>{const
|
|
2424
|
+
`:"",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(`
|
|
2416
2425
|
`);return` ${JSON.stringify(i)}: [
|
|
2417
2426
|
${c}
|
|
2418
2427
|
],`}).join(`
|
|
@@ -2443,7 +2452,7 @@ export const LUNORA_CRON_TRIGGERS: ReadonlyArray<string> = [${r}];
|
|
|
2443
2452
|
* looks up \`event.cron\` here and dispatches every job in the list.
|
|
2444
2453
|
*/
|
|
2445
2454
|
export const LUNORA_CRONS: Record<string, ReadonlyArray<LunoraCronJob>> = {${s}};
|
|
2446
|
-
`},
|
|
2455
|
+
`},wo=e=>{const t=[...e].toSorted((r,o)=>r.name.localeCompare(o.name)).map(r=>{const o=[`name: ${JSON.stringify(r.name)}`,`table: ${JSON.stringify(r.table)}`];return r.field!==void 0&&o.push(`field: ${JSON.stringify(r.field)}`),r.dimensions!==void 0&&o.push(`dimensions: ${JSON.stringify(r.dimensions)}`),r.metric!==void 0&&o.push(`metric: ${JSON.stringify(r.metric)}`),r.metadata!==void 0&&o.push(`metadata: ${JSON.stringify(r.metadata)}`),` { ${o.join(", ")} },`}).join(`
|
|
2447
2456
|
`),n=t.length>0?`
|
|
2448
2457
|
${t}
|
|
2449
2458
|
`:"";return`${$}/**
|
|
@@ -2467,4 +2476,4 @@ export interface LunoraVectorIndex {
|
|
|
2467
2476
|
* \`createWorker({ vectorIntrospector })\` to back the studio's vector browser.
|
|
2468
2477
|
*/
|
|
2469
2478
|
export const LUNORA_VECTOR_INDEXES: ReadonlyArray<LunoraVectorIndex> = [${n}];
|
|
2470
|
-
`},
|
|
2479
|
+
`},ko=e=>[...new Set(e.map(t=>t.cron))];export{oo as A,Nn as C,$ as G,Yn as U,so as a,lo as b,po as c,yo as d,mo as e,ao as f,bo as g,uo as h,co as i,fo as j,wo as k,ho as l,ko as m,gr as n,go as o,io as p};
|