@lunora/codegen 1.0.0-alpha.61 → 1.0.0-alpha.63
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 +20 -3
- package/dist/index.d.ts +20 -3
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{FLAGS_FILENAME-DW5oGq1q.mjs → FLAGS_FILENAME-C1GWerCB.mjs} +1 -1
- package/dist/packem_shared/GENERATED_HEADER-Sl8NoQFl.mjs +1 -0
- package/dist/packem_shared/MUTATORS_FILENAME-BWPAtQ2T.mjs +1 -0
- package/dist/packem_shared/{NOTIFY_FILENAME-C-c7Lg-U.mjs → NOTIFY_FILENAME-DP6qvFBX.mjs} +1 -1
- package/dist/packem_shared/{OPENRPC_VERSION-B_EyUGlr.mjs → OPENRPC_VERSION-BcivFYIX.mjs} +1 -1
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-CthmqJlJ.mjs +3 -0
- package/dist/packem_shared/SHAPES_FILENAME-maut3z1K.mjs +1 -0
- package/dist/packem_shared/{buildOpenApiDocument-f291wyY3.mjs → buildOpenApiDocument-BJudKDP_.mjs} +1 -1
- package/dist/packem_shared/{discoverAuthApiCalls-DOfSQqVK.mjs → discoverAuthApiCalls-Ba6W92HB.mjs} +1 -1
- package/dist/packem_shared/discoverCrons-2nUpw6do.mjs +1 -0
- package/dist/packem_shared/discoverFunctions-zrIQk7J8.mjs +1 -0
- package/dist/packem_shared/{discoverHttpRoutes-BOWz6y_n.mjs → discoverHttpRoutes-Bf_T_03b.mjs} +1 -1
- package/dist/packem_shared/{discoverInserts-BtteTyNy.mjs → discoverInserts-DveVeP5h.mjs} +1 -1
- package/dist/packem_shared/{discoverMaskProcedures-COPmwMBm.mjs → discoverMaskProcedures-BkBquCFR.mjs} +1 -1
- package/dist/packem_shared/discoverMigrations-T2xb-1rn.mjs +1 -0
- package/dist/packem_shared/{discoverNondeterministicCalls-Dmgc4QBx.mjs → discoverNondeterministicCalls-BymnOR9k.mjs} +1 -1
- package/dist/packem_shared/{discoverQueries-CcfuGKHh.mjs → discoverQueries-DNRA-G2a.mjs} +1 -1
- package/dist/packem_shared/{discoverR2sqlCalls-CjZKvg-N.mjs → discoverR2sqlCalls-YEjvGcEq.mjs} +1 -1
- package/dist/packem_shared/{discoverRlsMetadata-BXmNOgry.mjs → discoverRlsMetadata-DO3qlLXX.mjs} +1 -1
- package/dist/packem_shared/{discoverSandboxUsage-CDdBqWcM.mjs → discoverSandboxUsage-JwrmSN9l.mjs} +1 -1
- package/dist/packem_shared/{discoverStorageRulesMetadata-b71cJJHz.mjs → discoverStorageRulesMetadata-CCztRKjw.mjs} +1 -1
- package/dist/packem_shared/{emit-Cz-5gRp0.mjs → emit-Bp0nOR_O.mjs} +201 -180
- package/dist/packem_shared/{emitApp-DbpB1vA1.mjs → emitApp-BzO6O7Lx.mjs} +7 -7
- package/dist/packem_shared/module-specifiers-8FEEiUcv.mjs +1 -0
- package/package.json +3 -3
- package/dist/packem_shared/GENERATED_HEADER-4TxGhJDQ.mjs +0 -1
- package/dist/packem_shared/MUTATORS_FILENAME-BKKPROzu.mjs +0 -1
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-B-b-ZgwS.mjs +0 -3
- package/dist/packem_shared/SHAPES_FILENAME-DTkSJSsg.mjs +0 -1
- package/dist/packem_shared/discoverCrons-B09_uEuL.mjs +0 -1
- package/dist/packem_shared/discoverFunctions-BdibLQmc.mjs +0 -1
- package/dist/packem_shared/discoverMigrations-iGMlp9YJ.mjs +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{agentComponent as
|
|
1
|
+
import{agentComponent as Ge}from"@lunora/agent/component";import{LunoraError as X}from"@lunora/errors";import{n as v}from"./paths-BmX5O1sG.mjs";const Ve=[{contextProperty:"access",key:"access",moduleSpecifier:"@lunora/cloudflare-access"},{appMethod:{configKey:"ai",doc:"Override the Workers AI binding backing `ctx.ai` (defaults to `env.AI`).",method:"ai"},contextProperty:"ai",key:"ai",moduleSpecifier:"@lunora/ai"},{appMethod:{configKey:"analytics",doc:"Override the Analytics Engine dataset backing `ctx.analytics` (defaults to `env.ANALYTICS`).",method:"analytics"},contextProperty:"analytics",key:"analytics",moduleSpecifier:"@lunora/bindings/analytics",serverCtxField:{field:`
|
|
2
2
|
/** Analytics Engine telemetry sink. Fire-and-forget and sampled; do not read it back in-handler. */
|
|
3
3
|
readonly analytics: import("@lunora/bindings/analytics").AnalyticsClient;`,tier:"every"}},{appMethod:{configKey:"browser",doc:"Override the Browser Rendering binding backing `ctx.browser` (defaults to `env.BROWSER`).",method:"browser"},contextProperty:"browser",key:"browser",moduleSpecifier:"@lunora/browser",serverCtxField:{field:`
|
|
4
4
|
/** Browser Rendering (screenshots/PDF/scrape). Non-deterministic — available only in actions. */
|
|
@@ -15,38 +15,38 @@ import{agentComponent as Je}from"@lunora/agent/component";import{LunoraError as
|
|
|
15
15
|
/**
|
|
16
16
|
* R2 SQL over Apache Iceberg tables (window functions, DISTINCT, set operations). Non-deterministic — available only in actions. Reads here are NOT tracked by Lunora live queries.
|
|
17
17
|
*/
|
|
18
|
-
readonly r2sql: import("@lunora/bindings/r2sql").R2SqlClient;`,tier:"action"}},{contextProperty:"scheduler",key:"scheduler",moduleSpecifier:"@lunora/scheduler"},{contextProperty:"storage",key:"storage",moduleSpecifier:"@lunora/storage"},{appMethod:{configKey:"vectors",doc:"Wire the Vectorize index map backing `ctx.vectors`.",method:"vectors"},contextProperty:"vectors",key:"vectors",moduleSpecifier:"@lunora/bindings/vectors"},{contextProperty:"workflows",key:"workflows",moduleSpecifier:"@lunora/workflow"}],
|
|
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"}],Ut=Ve,Kt=new Map(Ut.flatMap(e=>e.serverCtxField?[[e.key,e.serverCtxField]]:[])),rr=Ve.flatMap(e=>"appMethod"in e?[{appMethod:e.appMethod,key:e.key}]:[]),He=/^(?:"(?:[^"\\]|\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4}))*"|'[^'\\]*'|-?\d+(?:\.\d+)?|true|false|null)$/u,Qt=new Set(["any","bigint","boolean","date","id","null","number","storage","string","timestamp"]),ze=e=>e.column!==void 0,Jt=(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
23
|
`}},Gt=(e,t)=>{const n=e.literalValue?.trim();if(!(n===void 0||!He.test(n)))return{out:t,pre:`if (${t} !== ${n}) return DEFER;
|
|
24
|
-
`}},De=(e,t,n)=>{if(!ze(e)&&!(e.hasRefinement||e.sourceText!==void 0)){if(
|
|
24
|
+
`}},De=(e,t,n)=>{if(!ze(e)&&!(e.hasRefinement||e.sourceText!==void 0)){if(Qt.has(e.kind))return e.kind==="any"?{out:t,pre:""}:{out:t,pre:Jt(e.kind,t)};switch(e.kind){case"array":return Vt(e,t,n);case"literal":return Gt(e,t);case"object":return zt(e,t,n);default:return}}},Vt=(e,t,n)=>{const{inner:r}=e;if(!r)return;const a=n.next(),o=`__arr${String(a)}`,s=`__i${String(a)}`,i=`__e${String(a)}`,l=De(r,i,n);if(!l)return;const u=`if (!Array.isArray(${t})) return DEFER;
|
|
25
25
|
const ${o} = new Array(${t}.length);
|
|
26
26
|
for (let ${s} = 0; ${s} < ${t}.length; ${s}++) {
|
|
27
27
|
const ${i} = ${t}[${s}];
|
|
28
28
|
${l.pre}${o}[${s}] = ${l.out};
|
|
29
29
|
}
|
|
30
|
-
`;return{out:o,pre:u}},
|
|
30
|
+
`;return{out:o,pre:u}},Ht=(e,t,n,r)=>{const a=JSON.stringify(e);if(t.kind==="optional"){if(t.hasRefinement||t.sourceText!==void 0||ze(t))return;const{inner:s}=t;if(!s)return;const i=De(s,n,r);if(!i)return;const l=r.next(),u=`__has${String(l)}`,p=`__val${String(l)}`,b=`let ${u} = false;
|
|
31
31
|
let ${p};
|
|
32
32
|
if (${n} !== undefined) {
|
|
33
33
|
${i.pre}${p} = ${i.out};
|
|
34
34
|
${u} = true;
|
|
35
35
|
}
|
|
36
|
-
`;return{entry:`...(${u} ? { ${
|
|
37
|
-
${
|
|
38
|
-
`;return{out:s,pre:i}},
|
|
36
|
+
`;return{entry:`...(${u} ? { ${a}: ${p} } : {})`,pre:b}}const o=De(t,n,r);if(o)return{entry:`${a}: ${o.out}`,pre:o.pre}},Xe=(e,t,n)=>{let r="";const a=[];for(const o of Object.keys(e)){const s=e[o];if(!s)return;const i=Ht(o,s,t(o),n);if(!i)return;r+=i.pre,a.push(i.entry)}return{entries:a.join(", "),pre:r}},zt=(e,t,n)=>{const r=e.shape??{},a=Xe(r,l=>`${t}[${JSON.stringify(l)}]`,n);if(!a)return;const o=n.next(),s=`__obj${String(o)}`,i=`if (typeof ${t} !== "object" || ${t} === null || Array.isArray(${t})) return DEFER;
|
|
37
|
+
${a.pre}const ${s} = { ${a.entries} };
|
|
38
|
+
`;return{out:s,pre:i}},Xt=e=>{let t=0;const n=Xe(e,r=>`source[${JSON.stringify(r)}]`,{next:()=>(t+=1,t)});if(n)return`(source) => {
|
|
39
39
|
if (typeof source !== "object" || source === null || Array.isArray(source)) return DEFER;
|
|
40
40
|
${n.pre}return { ${n.entries} };
|
|
41
41
|
}`},k=`// GENERATED by @lunora/codegen — do not edit.
|
|
42
42
|
// Run \`lunora codegen\` to regenerate.
|
|
43
43
|
|
|
44
|
-
`,V=(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"},Ye=/^[A-Za-z_$][\w$]*$/u,
|
|
44
|
+
`,V=(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"},Ye=/^[A-Za-z_$][\w$]*$/u,Yt=/^[\w./-]+$/u,m=(e,t)=>{if(!Ye.test(e))throw new X("INTERNAL",`@lunora/codegen: ${t} is not a valid JS identifier: ${JSON.stringify(e)}`)},Ce=e=>e.charAt(0).toUpperCase()+e.slice(1),A=e=>Ye.test(e)?e:JSON.stringify(e),Zt={any:"unknown",bigint:"bigint",boolean:"boolean",bytes:"ArrayBuffer",date:"number",from:"unknown",geoPoint:"{ lat: number; lng: number }",null:"null",number:"number",storage:"string",string:"string",timestamp:"number"},en=e=>{if(e===void 0)return"unknown";if(!He.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},T=e=>{const t=Zt[e.kind];if(t!==void 0)return t;switch(e.kind){case"array":return`Array<${e.inner?T(e.inner):"unknown"}>`;case"id":{const n=e.tableName??"_unknown_";return m(n,"v.id() table name"),`Id<"${n}">`}case"literal":return en(e.literalValue);case"object":return e.shape?`{ ${Object.entries(e.shape).map(([n,r])=>`${A(n)}: ${T(r)}`).join("; ")} }`:"Record<string, unknown>";case"optional":return`${e.inner?T(e.inner):"unknown"} | undefined`;case"record":{const n=e.keyType?T(e.keyType):"string",r=e.valueType?T(e.valueType):"unknown";return`Record<${n}, ${r}>`}case"union":return e.members&&e.members.length>0?e.members.map(n=>T(n)).join(" | "):"never";default:return"unknown"}},he=e=>{const t=Object.entries(e);return t.length===0?"{}":`{ ${t.map(([n,r])=>{const a=A(n);if(r.kind==="optional"){const o=r.inner?T(r.inner):"unknown";return`${a}?: ${o}`}return`${a}: ${T(r)}`}).join("; ")} }`},tn=e=>e.kind==="optional"||!!e.column?.hasDefault,nn=e=>{m(e.name,"table name");const t=Object.entries(e.shape).map(([r,a])=>{const o=a.kind==="optional"&&a.inner?a.inner:a,s=T(o),i=A(r);return tn(a)?` ${i}?: ${s};`:` ${i}: ${s};`}).join(`
|
|
45
45
|
`),n=t?`
|
|
46
46
|
${t}
|
|
47
47
|
`:"";return`export interface Insert_${e.name} {
|
|
48
48
|
_id?: Id<"${e.name}">;
|
|
49
|
-
_creationTime?: number;${n}}`},
|
|
49
|
+
_creationTime?: number;${n}}`},ar=(e,t=!1)=>{const n=V(t);for(const c of e.tables)m(c.name,"table name");const r=e.tables.map(c=>`"${c.name}"`).join(" | ")||"never",a=e.tables.filter(c=>c.extensionKey===void 0).map(c=>`"${c.name}"`).join(" | ")||"never",o=e.tables.map(c=>{const g=Object.entries(c.shape).map(([R,S])=>{const x=A(R);if(S.kind==="optional"){const _=S.inner?T(S.inner):"unknown";return` ${x}?: ${_};`}return` ${x}: ${T(S)};`}).join(`
|
|
50
50
|
`),f=g?`
|
|
51
51
|
${g}
|
|
52
52
|
`:"";return`export interface Doc_${c.name} {
|
|
@@ -58,10 +58,10 @@ ${g}
|
|
|
58
58
|
`),l=e.tables.map(c=>{const g=c.shardMode==="global"?"":c.searchIndexes.map(f=>JSON.stringify(f.name)).join(" | ");return` ${c.name}: ${g||"never"};`}).join(`
|
|
59
59
|
`),u=e.tables.map(c=>{const g=c.rankIndexes.map(f=>JSON.stringify(f.name)).join(" | ");return` ${c.name}: ${g||"never"};`}).join(`
|
|
60
60
|
`),p=e.tables.map(c=>{const g=c.shardMode==="global"?"":(c.geoIndexes??[]).map(f=>JSON.stringify(f.name)).join(" | ");return` ${c.name}: ${g||"never"};`}).join(`
|
|
61
|
-
`),b=e.vectorIndexes.map(c=>JSON.stringify(c.name)).join(" | ")||"never",w=e.tables.map(c=>
|
|
61
|
+
`),b=e.vectorIndexes.map(c=>JSON.stringify(c.name)).join(" | ")||"never",w=e.tables.map(c=>nn(c)).join(`
|
|
62
62
|
|
|
63
|
-
`)
|
|
64
|
-
`),d=e.tables.map(c=>{const g=c.relations.map(f=>(m(f.table,"relation target table"),` ${
|
|
63
|
+
`),$=e.tables.map(c=>` ${c.name}: Insert_${c.name};`).join(`
|
|
64
|
+
`),d=e.tables.map(c=>{const g=c.relations.map(f=>(m(f.table,"relation target table"),` ${A(f.name)}: ${f.kind==="one"?"OneRelation":"ManyRelation"}<"${f.table}">;`)).join(`
|
|
65
65
|
`);return g?` ${c.name}: {
|
|
66
66
|
${g}
|
|
67
67
|
};`:` ${c.name}: {};`}).join(`
|
|
@@ -97,7 +97,7 @@ export type {
|
|
|
97
97
|
WhereOperators,
|
|
98
98
|
} from "${n.serverDataModel}";
|
|
99
99
|
|
|
100
|
-
export type TableName = ${
|
|
100
|
+
export type TableName = ${r};
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
103
|
* The tables **this app declared** — every {@link TableName} except those an add-on
|
|
@@ -114,7 +114,7 @@ export type TableName = ${a};
|
|
|
114
114
|
* const EXPORTED: readonly AppTableName[] = ["nodes", "tagColors"];
|
|
115
115
|
* \`\`\`
|
|
116
116
|
*/
|
|
117
|
-
export type AppTableName = ${
|
|
117
|
+
export type AppTableName = ${a};
|
|
118
118
|
|
|
119
119
|
export type Id<TName extends string> = string & { readonly __table: TName };
|
|
120
120
|
|
|
@@ -164,7 +164,7 @@ ${w}
|
|
|
164
164
|
|
|
165
165
|
/** Per-table insert shape, accepted by \`ctx.db.<table>.insert(...)\`. */
|
|
166
166
|
export interface InsertModel {
|
|
167
|
-
${
|
|
167
|
+
${$}
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
export type Insert<T extends keyof DataModel> = InsertModel[T];
|
|
@@ -234,11 +234,11 @@ export interface OrmWriter extends OrmReader {
|
|
|
234
234
|
replace: <T extends keyof DataModel>(table: T, id: Id<T>) => OrmReplaceBuilder<T>;
|
|
235
235
|
update: <T extends keyof DataModel>(table: T, id: Id<T>) => OrmUpdateBuilder<T>;
|
|
236
236
|
}
|
|
237
|
-
`},
|
|
238
|
-
`);return` ${
|
|
237
|
+
`},rn=/import\("(?<spec>(?:\.\.?\/)*_generated\/[^"]+)"\)/gu,an=/^(?:\.\.?\/)*_generated\//u,on=/\.[A-Za-z]\w*$/u,_e=e=>e.replaceAll(rn,(t,n)=>{const r=n.replace(an,"./");return`import("${on.test(r)?r:`${r}.js`}")`}),sn=/import\("@lunora\/(?<pkg>client|do|runtime|server|values)(?<subpath>\/[^"]*)?"\)/gu,Ze=(e,t)=>t?e.replaceAll(sn,(n,r,a)=>`import("lunorash/${r}${a??""}")`):e,Ie=e=>["Doc","Id"].filter(t=>new RegExp(String.raw`\b${t}<`,"u").test(e)),Qe=e=>{const t=new Map;for(const r of e){const a=t.get(r.filePath)??[];a.push(r),t.set(r.filePath,a)}const n=([r,a])=>{const o=a.toSorted((s,i)=>s.exportName.localeCompare(i.exportName)).map(s=>{const i=he(s.args),l=_e(s.returnType);return` ${s.exportName}: FunctionReference<"${s.kind}", ${i}, ${l}>;`}).join(`
|
|
238
|
+
`);return` ${A(v(r))}: {
|
|
239
239
|
${o}
|
|
240
|
-
};`};return[...t.entries()].toSorted(([
|
|
241
|
-
`)},
|
|
240
|
+
};`};return[...t.entries()].toSorted(([r],[a])=>r.localeCompare(a)).map(r=>n(r)).join(`
|
|
241
|
+
`)},ln=(e,t)=>{if(e.length===0&&t.length===0)return{block:"",importLine:""};const n=[];let r="";if(e.length>0&&(r+="\n/** Params type carried by a `defineWorkflow` definition (its phantom `__params`). */\ntype WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params } ? (unknown extends Params ? Record<string, unknown> : Params) : Record<string, unknown>;\n"),r+=`
|
|
242
242
|
/** A typed reference to a durable workflow, addressable for \`cronJobs()\` targets. Mirrors \`@lunora/scheduler\`'s \`WorkflowReference\` structurally. */
|
|
243
243
|
export interface WorkflowReference<Params = Record<string, unknown>> {
|
|
244
244
|
readonly isLunoraWorkflow: true;
|
|
@@ -246,9 +246,9 @@ export interface WorkflowReference<Params = Record<string, unknown>> {
|
|
|
246
246
|
readonly binding: string;
|
|
247
247
|
readonly name: string;
|
|
248
248
|
}
|
|
249
|
-
`,e.length>0){const
|
|
250
|
-
`),s=
|
|
251
|
-
`);
|
|
249
|
+
`,e.length>0){const a=[...e].toSorted((i,l)=>i.exportName.localeCompare(l.exportName)),o=a.map(i=>` ${i.exportName}: WorkflowReference<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${i.exportName}>>;`).join(`
|
|
250
|
+
`),s=a.map(i=>` ${i.exportName}: { isLunoraWorkflow: true, binding: ${JSON.stringify(i.bindingName)}, name: ${JSON.stringify(i.exportName)} },`).join(`
|
|
251
|
+
`);r+=`
|
|
252
252
|
/** This project's durable workflows, addressable as typed references (e.g. \`crons.daily("digest", …, workflows.digestPipeline, params)\`). */
|
|
253
253
|
export interface WorkflowsRef {
|
|
254
254
|
${o}
|
|
@@ -258,9 +258,9 @@ export const workflows: WorkflowsRef = {
|
|
|
258
258
|
${s}
|
|
259
259
|
};
|
|
260
260
|
`,n.push(`import type * as lunoraWorkflowDefinitions from "../workflows.js";
|
|
261
|
-
`)}if(t.length>0){const
|
|
262
|
-
`),s=
|
|
263
|
-
`);
|
|
261
|
+
`)}if(t.length>0){const a=[...t].toSorted((i,l)=>i.exportName.localeCompare(l.exportName)),o=a.map(i=>` ${i.exportName}: WorkflowReference<AgentRunInput>;`).join(`
|
|
262
|
+
`),s=a.map(i=>` ${i.exportName}: { isLunoraWorkflow: true, binding: ${JSON.stringify(i.bindingName)}, name: ${JSON.stringify(i.name)} },`).join(`
|
|
263
|
+
`);r+=`
|
|
264
264
|
/** This project's durable agents, addressable as typed references for \`cronJobs()\` — each fire starts a fresh agent run (e.g. \`crons.daily("sweep", …, agents.support, { input, threadKey })\`). */
|
|
265
265
|
export interface AgentsRef {
|
|
266
266
|
${o}
|
|
@@ -270,7 +270,7 @@ export const agents: AgentsRef = {
|
|
|
270
270
|
${s}
|
|
271
271
|
};
|
|
272
272
|
`,n.push(`import type { AgentRunInput } from "@lunora/agent";
|
|
273
|
-
`)}return{block:
|
|
273
|
+
`)}return{block:r,importLine:n.join("")}},dn=()=>Object.keys(Ge().functions).toSorted((e,t)=>e.localeCompare(t)),et=e=>new Set(e.filter(t=>v(t.filePath)==="agents").map(t=>t.exportName)),cn=()=>new Set(Object.entries(Ge().functions).filter(([,e])=>e.visibility==="internal").map(([e])=>e)),un=(e,t)=>{const n={importLine:"",lines:"",prelude:""};if(e.length===0)return n;const r=et(t),a=cn(),o=t.find(i=>v(i.filePath)==="agents"&&a.has(i.exportName));if(o)throw new X("INTERNAL",`@lunora/codegen: "agents:${o.exportName}" is reserved for the durable agent loop's internal dispatch — rename the "${o.exportName}" export in ${o.filePath}`);const s=dn().filter(i=>!r.has(i));return s.length===0?n:{importLine:`import { agentComponent } from "@lunora/agent/component";
|
|
274
274
|
`,lines:s.map(i=>` "agents:${i}": lunoraAgentRuntimeFunctions.${i} as unknown as RegisteredLunoraFunction,`).join(`
|
|
275
275
|
`),prelude:`
|
|
276
276
|
/**
|
|
@@ -279,44 +279,44 @@ ${s}
|
|
|
279
279
|
* subscribe to the public queries (\`agents:agentMessages\` is the live thread view).
|
|
280
280
|
*/
|
|
281
281
|
const lunoraAgentRuntimeFunctions = agentComponent().functions;
|
|
282
|
-
`}},
|
|
283
|
-
`,lines:' "sandbox:invoke": lunoraSandbox.invoke as unknown as RegisteredLunoraFunction,',prelude:"\n/**\n * The `@lunora/agent` sandbox dispatcher — auto-registered because `lunora/`\n * imports a sandbox tool (`browserTool`/`containerTool`). The batteries-included\n * tools dispatch to this internal action, which runs on an action ctx carrying\n * `ctx.browser` + `ctx.containers` (the durable tool step itself has neither).\n */\nconst lunoraSandbox = sandboxComponent();\n"}},
|
|
284
|
-
`);return` ${
|
|
282
|
+
`}},pn=(e,t)=>{if(!e)return{importLine:"",lines:"",prelude:""};const n=t.find(r=>v(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";
|
|
283
|
+
`,lines:' "sandbox:invoke": lunoraSandbox.invoke as unknown as RegisteredLunoraFunction,',prelude:"\n/**\n * The `@lunora/agent` sandbox dispatcher — auto-registered because `lunora/`\n * imports a sandbox tool (`browserTool`/`containerTool`). The batteries-included\n * tools dispatch to this internal action, which runs on an action ctx carrying\n * `ctx.browser` + `ctx.containers` (the durable tool step itself has neither).\n */\nconst lunoraSandbox = sandboxComponent();\n"}},hn=(e,t)=>{if(e.length===0)return[];const n=et(t),r=[{args:{key:{kind:"string"},limit:{inner:{kind:"number"},kind:"optional"}},exportName:"agentMessages",filePath:"agents",kind:"query",returnType:"Record<string, unknown>[]"},{args:{decision:{kind:"union",members:[{kind:"literal",literalValue:'"approve"'},{kind:"literal",literalValue:'"reject"'}]},instanceId:{kind:"string"},note:{inner:{kind:"string"},kind:"optional"},threadKey:{kind:"string"},toolCallId:{kind:"string"}},exportName:"agentResolveApproval",filePath:"agents",kind:"mutation",returnType:"{ resolved: boolean }"},{args:{agent:{kind:"string"},input:{kind:"string"},threadKey:{kind:"string"},title:{inner:{kind:"string"},kind:"optional"}},exportName:"agentRun",filePath:"agents",kind:"mutation",returnType:"{ id: string; threadKey: string }"},{args:{key:{kind:"string"}},exportName:"agentState",filePath:"agents",kind:"query",returnType:"Record<string, unknown> | undefined"},{args:{key:{kind:"string"}},exportName:"agentThread",filePath:"agents",kind:"query",returnType:"Record<string, unknown> | undefined"}];for(const a of e)a.voice&&r.push({args:{threadKey:{kind:"string"}},exportName:`${a.exportName}Voice`,filePath:"agents",kind:"stream",returnType:"Record<string, unknown>"});return r.filter(a=>!n.has(a.exportName))},gn=(e,t)=>{if(e.length===0)return[];const n=new Set(t.filter(r=>v(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}))},mn=e=>{const t=e.filter(s=>s.stream);if(t.length===0)return{block:"",body:""};const n=new Map;for(const s of t){const i=n.get(s.filePath)??[];i.push(s),n.set(s.filePath,i)}const r=[...n.entries()].toSorted(([s],[i])=>s.localeCompare(i)),a=r.map(([s,i])=>{const l=i.map(u=>{const p=_e(u.chunkType??"unknown");return` ${A(u.exportName)}: HttpStreamRef<${p}, ${he(u.searchParams)}, ${he(u.params)}>;`}).join(`
|
|
284
|
+
`);return` ${A(v(s))}: {
|
|
285
285
|
${l}
|
|
286
286
|
};`}).join(`
|
|
287
|
-
`),o=
|
|
288
|
-
`);return` ${
|
|
287
|
+
`),o=r.map(([s,i])=>{const l=i.map(u=>` ${A(u.exportName)}: { method: ${JSON.stringify(u.method)}, path: ${JSON.stringify(u.path)} },`).join(`
|
|
288
|
+
`);return` ${A(v(s))}: {
|
|
289
289
|
${l}
|
|
290
290
|
},`}).join(`
|
|
291
291
|
`);return{block:`
|
|
292
292
|
/** This project's HTTP-SSE stream routes (\`httpRoute.<verb>(path).stream()\`), addressable as typed references for \`client.httpStream\` / \`useHttpStream\`. */
|
|
293
293
|
export interface HttpStreamsRef {
|
|
294
|
-
${
|
|
294
|
+
${a}
|
|
295
295
|
}
|
|
296
296
|
|
|
297
297
|
export const httpStreams: HttpStreamsRef = {
|
|
298
298
|
${o}
|
|
299
299
|
};
|
|
300
|
-
`,body:
|
|
301
|
-
${
|
|
302
|
-
${
|
|
303
|
-
import type { ${
|
|
304
|
-
`:"",c=u?`
|
|
305
|
-
${u}
|
|
300
|
+
`,body:a}},or=e=>{const{agents:t=[],functions:n,httpRoutes:r=[],mutators:a=[],useUmbrella:o=!1,workflows:s=[]}=e,i=V(o),l=[...n.filter(x=>x.visibility!=="internal"),...hn(t,n),...gn(a,n)],u=n.filter(x=>x.visibility==="internal"),p=Qe(l),b=Qe(u),w=mn(r),$=`${p}
|
|
301
|
+
${b}
|
|
302
|
+
${w.body}`,d=Ie($),c=d.length>0?`
|
|
303
|
+
import type { ${d.join(", ")} } from "./dataModel.js";
|
|
306
304
|
`:"",g=p?`
|
|
307
305
|
${p}
|
|
308
|
-
`:"",f=
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
306
|
+
`:"",f=b?`
|
|
307
|
+
${b}
|
|
308
|
+
`:"",R=ln(s,t),S=w.block===""?"FunctionReference":"FunctionReference, HttpStreamRef";return Ze(`${k}import { anyApi } from "${i.serverTypes}";
|
|
309
|
+
import type { ${S} } from "${i.client}";
|
|
310
|
+
${R.importLine}${c}
|
|
311
|
+
export interface ApiTypes {${g}}
|
|
312
312
|
|
|
313
313
|
export const api = anyApi as unknown as ApiTypes;
|
|
314
314
|
|
|
315
315
|
/** Internal functions — callable only server-side via \`ctx.run*\`, never from a client. */
|
|
316
|
-
export interface InternalApiTypes {${
|
|
316
|
+
export interface InternalApiTypes {${f}}
|
|
317
317
|
|
|
318
318
|
export const internal = anyApi as unknown as InternalApiTypes;
|
|
319
|
-
${
|
|
319
|
+
${R.block}${w.block}`,o)},ir=e=>e?`${k}import { createSeedClient as createSeedClientBase } from "@lunora/seed";
|
|
320
320
|
import type { SeedClient, SeedClientOptions } from "@lunora/seed";
|
|
321
321
|
|
|
322
322
|
import schema from "../schema.js";
|
|
@@ -333,7 +333,7 @@ import type { InsertModel } from "./dataModel.js";
|
|
|
333
333
|
* const { posts } = await seed.posts((x) => x([10, 20]));
|
|
334
334
|
*/
|
|
335
335
|
export const createSeedClient = (options?: SeedClientOptions): SeedClient<InsertModel> => createSeedClientBase<InsertModel>(schema, options);
|
|
336
|
-
`:"",
|
|
336
|
+
`:"",sr=(e,t,n=!1)=>{if(e.length===0||!t)return"";const r=V(n),a=l=>l.table===void 0?"Row":`Doc<${JSON.stringify(l.table)}> & Row`,o=e.map(l=>{m(l.exportName,"shape export name");const u=a(l),p=he(l.args),b=Object.keys(l.args).length>0,w=b?` args: ${p};`:` args?: ${p};`,$=b?`(args: ${p}) => void`:`(args?: ${p}) => void`,d=`${l.exportName}CollectionOptions`;return`/** Options for the \`${l.exportName}\` shape binding. */
|
|
337
337
|
export interface ${Ce(d)} {
|
|
338
338
|
${w}
|
|
339
339
|
/**
|
|
@@ -373,21 +373,21 @@ export const ${l.exportName}CollectionOptions = (options: ${Ce(d)}): LunoraColle
|
|
|
373
373
|
/** Live collection for the \`${l.exportName}\` shape, with its sync controls. */
|
|
374
374
|
export const ${l.exportName}Collection = (
|
|
375
375
|
options: ${Ce(d)},
|
|
376
|
-
): { checkpoints: CheckpointRegistry; collection: Collection<${u}, string>; scope: ${
|
|
376
|
+
): { checkpoints: CheckpointRegistry; collection: Collection<${u}, string>; scope: ${$} } => {
|
|
377
377
|
const { checkpoints, config, scope } = ${l.exportName}CollectionOptions(options);
|
|
378
378
|
|
|
379
379
|
return { checkpoints, collection: createCollection(config), scope };
|
|
380
380
|
};`}).join(`
|
|
381
381
|
|
|
382
382
|
`),s=Ie(o),i=s.length>0?`import type { ${s.join(", ")} } from "./dataModel.js";
|
|
383
|
-
`:"";return`${k}import type { LunoraClient, SubscriptionError } from "${
|
|
383
|
+
`:"";return`${k}import type { LunoraClient, SubscriptionError } from "${r.client}";
|
|
384
384
|
import { lunoraCollectionOptions } from "@lunora/db/collections";
|
|
385
385
|
import type { CheckpointRegistry, LunoraCollectionOptions, Row } from "@lunora/db";
|
|
386
386
|
import type { Collection } from "@tanstack/db";
|
|
387
387
|
import { createCollection } from "@tanstack/db";
|
|
388
388
|
${i}
|
|
389
389
|
${o}
|
|
390
|
-
`},
|
|
390
|
+
`},fn=(e,t)=>`lunora_${v(e)}_${String(t)}`,bn=`const callRegistered = async <R>(context: CallerCtx, functionPath: string, args: Record<string, unknown> | undefined): Promise<R> => {
|
|
391
391
|
const registered = LUNORA_FUNCTIONS[functionPath];
|
|
392
392
|
|
|
393
393
|
if (!registered) {
|
|
@@ -395,40 +395,40 @@ ${o}
|
|
|
395
395
|
}
|
|
396
396
|
|
|
397
397
|
return (await registered.handler(context, args ?? {})) as R;
|
|
398
|
-
};`,
|
|
399
|
-
`),i=e.map(d=>` "${
|
|
400
|
-
`),l=t.map(d=>` ${JSON.stringify(d.id)}: ${
|
|
401
|
-
`),u=n.map(d=>` "${
|
|
402
|
-
`),p=
|
|
403
|
-
`),b=n.map(d=>`${
|
|
404
|
-
`)
|
|
398
|
+
};`,yn=(e,t,n=[],r=[])=>{const a=new Map,o=d=>{a.has(d)||a.set(d,fn(d,a.size))};for(const d of e)o(d.filePath);for(const d of t)o(d.filePath);for(const d of n)o(d.filePath);for(const d of r)o(d.filePath);const s=[...a.entries()].map(([d,c])=>{if(!Yt.test(d))throw new X("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(d)}`);return`import * as ${c} from "../${d}.js";`}).join(`
|
|
399
|
+
`),i=e.map(d=>` "${v(d.filePath)}:${d.exportName}": ${a.get(d.filePath)??""}.${d.exportName} as unknown as RegisteredLunoraFunction,`).join(`
|
|
400
|
+
`),l=t.map(d=>` ${JSON.stringify(d.id)}: ${a.get(d.filePath)??""}.${d.exportName} as unknown as RegisteredDataMigration,`).join(`
|
|
401
|
+
`),u=n.map(d=>` "${v(d.filePath)}:${d.exportName}": ${a.get(d.filePath)??""}.${d.exportName} as unknown as RegisteredLunoraFunction,`).join(`
|
|
402
|
+
`),p=r.map(d=>` "${d.exportName}": ${a.get(d.filePath)??""}.${d.exportName} as unknown as RegisteredShape,`).join(`
|
|
403
|
+
`),b=n.map(d=>`${v(d.filePath)}:${d.exportName}`),w=[i,u].filter(d=>d.length>0).join(`
|
|
404
|
+
`),$=e.map(d=>{if(d.lifecycle||Object.keys(d.args).length===0)return;const c=Xt(d.args);return c===void 0?void 0:`installCompiledValidatorMap(${a.get(d.filePath)??""}.${d.exportName}.args, ${c});`}).filter(d=>d!==void 0).join(`
|
|
405
405
|
`);return{dispatchBody:w.length>0?`
|
|
406
406
|
${w}
|
|
407
407
|
`:"",importBlock:s.length>0?`${s}
|
|
408
408
|
|
|
409
|
-
`:"",installBlock
|
|
409
|
+
`:"",installBlock:$,migrationBody:l.length>0?`
|
|
410
410
|
${l}
|
|
411
411
|
`:"",mutatorPaths:b,shapeBody:p.length>0?`
|
|
412
412
|
${p}
|
|
413
|
-
`:""}},
|
|
414
|
-
`);return` ${
|
|
413
|
+
`:""}},wn=e=>{const t=new Map;for(const a of e){const o=t.get(a.filePath)??[];o.push(a),t.set(a.filePath,o)}const n=[...t.entries()].toSorted(([a],[o])=>a.localeCompare(o)),r=n.map(([a,o])=>{const s=o.map(i=>{const l=he(i.args),u=l==="{}"?"?":"",p=_e(i.returnType);return i.kind==="stream"?` ${i.exportName}: (args${u}: ${l}) => Promise<AsyncIterable<${p}>>;`:` ${i.exportName}: (args${u}: ${l}) => Promise<${p}>;`}).join(`
|
|
414
|
+
`);return` ${A(v(a))}: {
|
|
415
415
|
${s}
|
|
416
416
|
};`}).join(`
|
|
417
|
-
`);return{implementation:n.map(([
|
|
418
|
-
`);return` ${
|
|
417
|
+
`);return{implementation:n.map(([a,o])=>{const s=v(a),i=o.map(l=>` ${l.exportName}: (args) => callRegistered(context, "${s}:${l.exportName}", args),`).join(`
|
|
418
|
+
`);return` ${A(s)}: {
|
|
419
419
|
${i}
|
|
420
420
|
},`}).join(`
|
|
421
|
-
`),types:
|
|
422
|
-
`:"",ee=
|
|
421
|
+
`),types:r}},xn=(e,t=[])=>{const n=new Set;for(const r of e.tables)for(const a of Object.values(r.shape)){const o=a.kind==="optional"&&a.inner?a.inner:a;o.kind==="storage"&&typeof o.bucket=="string"&&o.bucket!==""&&n.add(o.bucket)}for(const r of t)r!==""&&r!=="default"&&n.add(r);return["default",...[...n].toSorted((r,a)=>r.localeCompare(a))]},lr=({agents:e=[],containers:t=[],env:n,hasAccessFacade:r=!1,hasAi:a=!1,hasAnalytics:o=!1,hasBrowser:s=!1,hasFlags:i=!1,hasHyperdrive:l=!1,hasImages:u=!1,hasKv:p=!1,hasNotify:b=!1,hasPayments:w=!1,hasPipelines:$=!1,hasR2sql:d=!1,hasX402:c=!1,identity:g,queues:f=[],schema:R,storageRuleBuckets:S=[],useUmbrella:x=!1,workflows:_=[]}={})=>{const y=V(x),Y=xn(R??{tables:[]},S).map(h=>JSON.stringify(h)).join(" | "),Z=a?`import type { LunoraAi } from "@lunora/ai";
|
|
422
|
+
`:"",ee=a?`
|
|
423
423
|
readonly ai: LunoraAi;`:"",I=w?`import type { LunoraPayment } from "@lunora/payment";
|
|
424
424
|
`:"",j=w?`
|
|
425
|
-
readonly payments: LunoraPayment;`:"",
|
|
425
|
+
readonly payments: LunoraPayment;`:"",N=c?`import type { X402Pay } from "@lunora/x402/pay";
|
|
426
426
|
`:"",W=c?`
|
|
427
427
|
readonly x402: X402Pay;`:"",L=t.length>0?`import type { ContainerAccessor } from "@lunora/container";
|
|
428
428
|
`:"",te=t.length>0?`
|
|
429
429
|
readonly containers: {${t.map(h=>`
|
|
430
430
|
readonly ${h.exportName}: ContainerAccessor;`).join("")}
|
|
431
|
-
};`:"",H=[...
|
|
431
|
+
};`:"",H=[...a?[" /** Workers AI binding (the conventional `env.AI`), narrowing `ctx.ai`. */\n readonly AI?: unknown;"]:[],...t.map(h=>(m(h.bindingName,`container binding "${h.bindingName}"`),` /** Durable Object namespace for the \`${h.exportName}\` container. */
|
|
432
432
|
readonly ${h.bindingName}?: unknown;`)),..._.map(h=>(m(h.bindingName,`workflow binding "${h.bindingName}"`),` /** Workflow binding for the \`${h.exportName}\` workflow. */
|
|
433
433
|
readonly ${h.bindingName}?: unknown;`)),...f.map(h=>(m(h.bindingName,`queue binding "${h.bindingName}"`),` /** Queue producer binding for the \`${h.exportName}\` queue. */
|
|
434
434
|
readonly ${h.bindingName}?: unknown;`)),...e.map(h=>(m(h.bindingName,`agent binding "${h.bindingName}"`),` /** Workflow binding for the \`${h.exportName}\` agent. */
|
|
@@ -451,7 +451,7 @@ ${H}`:""}
|
|
|
451
451
|
}
|
|
452
452
|
|
|
453
453
|
/** Alias for {@link CloudflareBindings} — the typed shape of \`env\`. */
|
|
454
|
-
export type Env = CloudflareBindings;`,P=(h,Te)=>Te?
|
|
454
|
+
export type Env = CloudflareBindings;`,P=(h,Te)=>Te?Kt.get(h)?.field??"":"",U=P("kv",p),E=P("analytics",o),K=P("hyperdrive",l),ne=P("browser",s),re=P("images",u),ae=P("pipelines",$),Q=P("r2sql",d),M=r?`
|
|
455
455
|
/** Verified Cloudflare Access identity — a synchronous facade over the resolved claims (email / groups / hasGroup / claims). Anonymous when no Access token is present. */
|
|
456
456
|
readonly access: import("@lunora/cloudflare-access/context").AccessFacade;`:"",q=i?`
|
|
457
457
|
/** Feature-flag evaluation (OpenFeature). Reads are memoized per request; evaluations never throw — a provider error resolves to the supplied default. */
|
|
@@ -508,7 +508,7 @@ type NarrowedAuth = Omit<QueryCtxBase["auth"], "getIdentity"> & { getIdentity: (
|
|
|
508
508
|
`:"",Oe=n?`
|
|
509
509
|
|
|
510
510
|
/** This app's declared env contract (\`defineEnv\` in \`lunora/env.ts\`) — the validated, coercion-aware shape of \`ctx.env\`. */
|
|
511
|
-
export type LunoraEnv = ReturnType<typeof lunoraEnvContract.${n.exportName}>;`:"",de=n?' | "env"':"",ce=n?"\n /** Validated, typed environment declared by `defineEnv` in `lunora/env.ts` — parsed & coercion-aware config values (`ctx.env.STRIPE_KEY`); a missing or invalid value throws at read time. */\n readonly env: LunoraEnv;":"";return`${k}import { createPolicyDsl, initLunora, v as vBase } from "${y.server}";
|
|
511
|
+
export type LunoraEnv = ReturnType<typeof lunoraEnvContract.${n.exportName}>;`:"",de=n?' | "env"':"",ce=n?"\n /** Validated, typed environment declared by `defineEnv` in `lunora/env.ts` — parsed & coercion-aware config values (`ctx.env.STRIPE_KEY`); a missing or invalid value throws at read time. */\n readonly env: LunoraEnv;":"";return`${k}import { createPolicyDsl, defineMutator as defineMutatorBase, initLunora, v as vBase } from "${y.server}";
|
|
512
512
|
import type {
|
|
513
513
|
ActionBuilder,
|
|
514
514
|
ActionCtx as ActionCtxBase,
|
|
@@ -521,15 +521,18 @@ import type {
|
|
|
521
521
|
InternalQueryBuilder,
|
|
522
522
|
MutationBuilder,
|
|
523
523
|
MutationCtx as MutationCtxBase,
|
|
524
|
+
MutatorDefinition,
|
|
524
525
|
QueryBuilder,
|
|
525
526
|
QueryCtx as QueryCtxBase,
|
|
526
527
|
ReadOnlyStorage,
|
|
528
|
+
RegisteredMutator,
|
|
527
529
|
Storage as StorageBase,
|
|
528
530
|
TableReader,
|
|
531
|
+
Validator,
|
|
529
532
|
} from "${y.server}";
|
|
530
533
|
|
|
531
534
|
import type { DataModel, DatabaseReaderFacade, DatabaseWriterFacade, Doc, Id as IdOfTable, OrmReader, OrmWriter, Relations, TableName } from "./dataModel.js";
|
|
532
|
-
${Z}${I}${
|
|
535
|
+
${Z}${I}${N}${L}${z}${we}${ke}${$e}${Ne}
|
|
533
536
|
export type { AppTableName, DataModel, Doc, Id, TableName } from "./dataModel.js";
|
|
534
537
|
|
|
535
538
|
/** Storage buckets this schema declares (\`v.storage("name")\`), narrowing \`ctx.storage.bucket(name)\`. */
|
|
@@ -632,6 +635,24 @@ export const internalMutation = lunoraBuilders.internalMutation as unknown as In
|
|
|
632
635
|
/** \`internalAction\` builder bound to this project's typed {@link ActionCtx} — never exposed on \`api\`. */
|
|
633
636
|
export const internalAction = lunoraBuilders.internalAction as unknown as InternalActionBuilder<ActionCtx, EmptyArgs>;
|
|
634
637
|
|
|
638
|
+
/**
|
|
639
|
+
* \`defineMutator\` bound to this project's typed {@link MutationCtx} — declare
|
|
640
|
+
* custom mutators (\`lunora/mutators.ts\`) with it instead of importing from
|
|
641
|
+
* \`${y.server}\`, and the authoritative \`server\` impl's \`ctx\` carries the
|
|
642
|
+
* schema-typed \`ctx.db\` (\`ctx.db.query("nodes")\` resolves \`Doc<"nodes">\`,
|
|
643
|
+
* \`ctx.db.patch(id, …)\` takes an \`Id<"nodes">\`) with no hand-written ctx type and
|
|
644
|
+
* no \`as unknown as\` cast. Runtime-identical to the package export; only the
|
|
645
|
+
* context type narrows, so discovery finds a mutator authored either way.
|
|
646
|
+
* @example
|
|
647
|
+
* export const setText = defineMutator({
|
|
648
|
+
* args: { id: v.id("nodes"), text: v.string() },
|
|
649
|
+
* server: async (ctx, args) => { await ctx.db.patch(args.id, { text: args.text }); },
|
|
650
|
+
* });
|
|
651
|
+
*/
|
|
652
|
+
export const defineMutator = defineMutatorBase as unknown as <Args extends Record<string, Validator> = Record<string, Validator>, ClientTx = unknown, R = unknown>(
|
|
653
|
+
definition: MutatorDefinition<Args, MutationCtx, ClientTx, R>,
|
|
654
|
+
) => RegisteredMutator<Args, MutationCtx, ClientTx, R>;
|
|
655
|
+
|
|
635
656
|
/**
|
|
636
657
|
* \`definePolicy\` bound to THIS schema's {@link DataModel} + {@link Relations}.
|
|
637
658
|
* Import it from here (\`./_generated/server\`) instead of \`@lunora/server\` to get
|
|
@@ -659,12 +680,12 @@ export const definePolicy = createPolicyDsl<DataModel, Relations${Re}>();
|
|
|
659
680
|
export const v = vBase as unknown as Omit<typeof vBase, "id"> & {
|
|
660
681
|
id: <T extends TableName>(table: T) => ColumnValidator<IdOfTable<T>, IdOfTable<T>>;
|
|
661
682
|
};
|
|
662
|
-
`},
|
|
663
|
-
`);let
|
|
664
|
-
${
|
|
683
|
+
`},kn=e=>{const t={connect:[],disconnect:[]};for(const n of e)n.lifecycle&&t[n.lifecycle].push(`${v(n.filePath)}:${n.exportName}`);return t},dr=e=>{const{agents:t=[],functions:n,migrations:r=[],mutators:a=[],shapes:o=[],useUmbrella:s=!1,usesSandbox:i=!1}=e,l=n.length>0,u=V(s),{dispatchBody:p,importBlock:b,installBlock:w,migrationBody:$,mutatorPaths:d,shapeBody:c}=yn(n,r,a,o),g=un(t,n),f=pn(i,n),R=[g.lines,f.lines].filter(C=>C.length>0).join(`
|
|
684
|
+
`);let S=p;R.length>0&&(S=p.length>0?`${p.trimEnd()}
|
|
685
|
+
${R}
|
|
665
686
|
`:`
|
|
666
|
-
${
|
|
667
|
-
`);const
|
|
687
|
+
${R}
|
|
688
|
+
`);const x=kn(n),_=o.length>0?`import type { RegisteredShape } from "${u.server}";
|
|
668
689
|
`:"",y=o.length>0?`
|
|
669
690
|
/**
|
|
670
691
|
* Replication-shape registry — one entry per \`defineShape\` in \`lunora/shapes.ts\`.
|
|
@@ -688,14 +709,14 @@ export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${d.map(C=>JSO
|
|
|
688
709
|
* parser as a zero-allocation fast path; anything it can't model is deferred.
|
|
689
710
|
*/
|
|
690
711
|
${w}
|
|
691
|
-
`:"",I=
|
|
712
|
+
`:"",I=wn(n),j=I.types?`
|
|
692
713
|
${I.types}
|
|
693
|
-
`:"",
|
|
714
|
+
`:"",N=I.implementation?`
|
|
694
715
|
${I.implementation}
|
|
695
716
|
`:"",W=Ie(I.types),L=W.length>0?`import type { ${W.join(", ")} } from "./dataModel.js";
|
|
696
|
-
`:"",te=l?"context":"_context",H=l?`${
|
|
717
|
+
`:"",te=l?"context":"_context",H=l?`${bn}
|
|
697
718
|
|
|
698
|
-
`:"";return`${k}${b}${g.importLine}${f.importLine}${Z}${_}import { LunoraError } from "${u.server}";
|
|
719
|
+
`:"";return Ze(`${k}${b}${g.importLine}${f.importLine}${Z}${_}import { LunoraError } from "${u.server}";
|
|
699
720
|
import type { ActionCtx, MutationCtx, QueryCtx } from "./server.js";
|
|
700
721
|
${L}
|
|
701
722
|
/**
|
|
@@ -721,7 +742,7 @@ ${g.prelude}${f.prelude}
|
|
|
721
742
|
* Static dispatch table. The key matches the \`__lunoraRef\` the client
|
|
722
743
|
* emits (\`api[namespace][fn].__lunoraRef === "namespace:fn"\`).
|
|
723
744
|
*/
|
|
724
|
-
export const LUNORA_FUNCTIONS: Record<string, RegisteredLunoraFunction> = {${
|
|
745
|
+
export const LUNORA_FUNCTIONS: Record<string, RegisteredLunoraFunction> = {${S}};
|
|
725
746
|
${ee}${y}${Y}
|
|
726
747
|
/**
|
|
727
748
|
* Connection-lifecycle manifest: the function paths the generated ShardDO
|
|
@@ -730,8 +751,8 @@ ${ee}${y}${Y}
|
|
|
730
751
|
* DO runs every hook under the socket's verified identity via system dispatch.
|
|
731
752
|
*/
|
|
732
753
|
export const LUNORA_LIFECYCLE_HOOKS: { connect: readonly string[]; disconnect: readonly string[] } = {
|
|
733
|
-
connect: [${
|
|
734
|
-
disconnect: [${
|
|
754
|
+
connect: [${x.connect.map(C=>JSON.stringify(C)).join(", ")}],
|
|
755
|
+
disconnect: [${x.disconnect.map(C=>JSON.stringify(C)).join(", ")}],
|
|
735
756
|
};
|
|
736
757
|
|
|
737
758
|
/**
|
|
@@ -765,7 +786,7 @@ export type CallerCtx = ActionCtx | MutationCtx | QueryCtx;
|
|
|
765
786
|
export interface Caller {${j}}
|
|
766
787
|
|
|
767
788
|
${H}/** Build a {@link Caller} bound to \`context\` (typically a handler's \`ctx\`). */
|
|
768
|
-
export const createCaller = (${te}: CallerCtx): Caller => ({${
|
|
789
|
+
export const createCaller = (${te}: CallerCtx): Caller => ({${N}});
|
|
769
790
|
|
|
770
791
|
/**
|
|
771
792
|
* Single registered data migration, narrowed to the shape the per-shard runner
|
|
@@ -784,8 +805,8 @@ export interface RegisteredDataMigration {
|
|
|
784
805
|
* Registry of online data migrations keyed by \`defineMigration\`'s \`id\`. The
|
|
785
806
|
* shard DO's admin RPC and the CLI resolve migrations to run through this map.
|
|
786
807
|
*/
|
|
787
|
-
export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${
|
|
788
|
-
|
|
808
|
+
export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${$}};
|
|
809
|
+
`,s)},vn=e=>{const t={};for(const n of e.tables){const r={};for(const[a,o]of Object.entries(n.shape)){const s=o.kind==="optional"&&o.inner?o.inner:o;s.kind==="id"&&s.tableName!==void 0&&(r[a]=s.tableName)}Object.keys(r).length>0&&(t[n.name]=r)}return t},$n=e=>{const t={};for(const n of e.tables){const r=[];for(const[a,o]of Object.entries(n.shape))(o.kind==="optional"&&o.inner?o.inner:o).kind==="storage"&&r.push(a);r.length>0&&(t[n.name]=r)}return t},Sn=e=>{const t={};for(const n of e.tables){const r=[...n.indexes.map(a=>({fields:[...a.fields],name:a.name,type:"index",...a.unique===!0?{unique:!0}:{}})),...n.searchIndexes.map(a=>({fields:[a.field,...a.filterFields??[]],name:a.name,type:"search"})),...(n.geoIndexes??[]).map(a=>({fields:[a.field],name:a.name,type:"geo"})),...n.rankIndexes.map(a=>({fields:a.sortBy.map(o=>o.field),name:a.name,type:"rank"})),...n.vectorIndexes.map(a=>({fields:a.field===void 0?[]:[a.field],name:a.name,type:"vector"}))];r.length>0&&(t[n.name]=r)}return t},Rn=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},Nn=e=>{const t={};for(const n of e.tables){const r=[{name:"_id",optional:!1,pk:!0,type:"id"},{name:"_creationTime",optional:!1,type:"number"}];for(const[a,o]of Object.entries(n.shape)){const s=o.kind==="optional"||!!o.column?.hasDefault,i=o.kind==="optional"&&o.inner?o.inner:o,l={name:a,optional:s,type:i.kind};i.kind==="id"&&i.tableName!==void 0&&(l.ref=i.tableName),i.kind==="storage"&&(l.isStorage=!0),r.push(l)}t[n.name]=r}return t},On=e=>e?{importFragment:"serveRelationFanout, ",override:`
|
|
789
810
|
protected override async runRelationFanoutRead(functionPath: string, args: Record<string, unknown>): Promise<unknown> {
|
|
790
811
|
this.ensureMigrated();
|
|
791
812
|
|
|
@@ -793,7 +814,7 @@ export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${v}}
|
|
|
793
814
|
|
|
794
815
|
return serveRelationFanout(schema as unknown as SchemaLike, db, functionPath, args);
|
|
795
816
|
}
|
|
796
|
-
`}:{importFragment:"",override:""},
|
|
817
|
+
`}:{importFragment:"",override:""},Tn=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:`
|
|
797
818
|
const aiBinding = config.ai?.(env) ?? (env as Record<string, unknown>).AI;
|
|
798
819
|
// Correlate AI-Gateway-routed calls with the Lunora trace: thread the
|
|
799
820
|
// function path + trace id into createAi, which folds them into the
|
|
@@ -824,7 +845,7 @@ const aiStub: LunoraAi = {
|
|
|
824
845
|
${t}
|
|
825
846
|
}) as unknown as LunoraAi["workersai"],
|
|
826
847
|
};
|
|
827
|
-
`}},D={build:"",configField:"",contextField:"",importLines:[],stub:""},
|
|
848
|
+
`}},D={build:"",configField:"",contextField:"",importLines:[],stub:""},An=e=>{if(!e)return D;const t='throw new Error("ctx.kv: no KV binding found. Add a \\`kv_namespaces\\` binding (env.KV) to wrangler.jsonc, or pass \\`kv\\` to createShardDO().");';return{build:`
|
|
828
849
|
const kvBinding = config.kv?.(env) ?? (env as Record<string, unknown>).KV;
|
|
829
850
|
const kv: Kv = kvBinding ? createKv({ namespace: kvBinding as KVNamespaceLike }) : kvStub;
|
|
830
851
|
`,configField:`
|
|
@@ -850,7 +871,7 @@ const kvStub: Kv = {
|
|
|
850
871
|
${t}
|
|
851
872
|
},
|
|
852
873
|
};
|
|
853
|
-
`}},
|
|
874
|
+
`}},Ln=(e,t)=>e?{build:`
|
|
854
875
|
const flags: import("${t}").LunoraFlags = createFlags({
|
|
855
876
|
hooks: flagsConfig.hooks,
|
|
856
877
|
logger: flagsConfig.logger,
|
|
@@ -859,28 +880,28 @@ const kvStub: Kv = {
|
|
|
859
880
|
});
|
|
860
881
|
`,configField:`
|
|
861
882
|
flags?: (env: Record<string, unknown>) => import("${t}").Provider;`,contextField:`
|
|
862
|
-
flags,`,importLines:[`import { createFlags } from "${t}";`,'import flagsConfig from "../flags.js";'],stub:""}:D,
|
|
883
|
+
flags,`,importLines:[`import { createFlags } from "${t}";`,'import flagsConfig from "../flags.js";'],stub:""}:D,Cn=e=>e?{build:`
|
|
863
884
|
const { notify, push } = createNotify(notifyConfig, env, { log, metrics });
|
|
864
885
|
`,configField:"",contextField:`
|
|
865
886
|
notify,
|
|
866
|
-
push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:D,
|
|
887
|
+
push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:D,Dn=e=>e?{build:`
|
|
867
888
|
const envConfig = lunoraEnvContract.${e.exportName}(env);
|
|
868
889
|
`,configField:"",contextField:`
|
|
869
|
-
env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:D,
|
|
890
|
+
env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:D,_n=e=>e?{build:`
|
|
870
891
|
const access = accessFacade(identity, userId);
|
|
871
892
|
`,configField:"",contextField:`
|
|
872
|
-
access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:D,
|
|
893
|
+
access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:D,In=(e,t,n)=>{if(!t)return{constant:"",evaluateOverride:"",subscriptionOverride:""};const r=i=>`
|
|
873
894
|
const env = (this.env ?? {}) as Record<string, unknown>;
|
|
874
895
|
const flags: import("${n}").LunoraFlags = createFlags({
|
|
875
896
|
hooks: flagsConfig.hooks,
|
|
876
897
|
logger: flagsConfig.logger,
|
|
877
898
|
provider: () => config.flags?.(env) ?? flagsConfig.provider(env),
|
|
878
899
|
targetingKey: ${i},
|
|
879
|
-
});`,
|
|
900
|
+
});`,a=`
|
|
880
901
|
/** Statically-discovered feature flags (\`ctx.flags.<type>("key")\` reads) served via \`__lunora_admin__:listFlags\` + the reactive \`__lunora_flags__:\` channel. */
|
|
881
902
|
const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number" | "object" | "string" }> = ${JSON.stringify(e,void 0,4)};
|
|
882
903
|
`,o=`
|
|
883
|
-
protected override async evaluateFlags(context?: Record<string, unknown>): Promise<FlagsResult> {${
|
|
904
|
+
protected override async evaluateFlags(context?: Record<string, unknown>): Promise<FlagsResult> {${r("undefined")}
|
|
884
905
|
const evalContext = context as import("${n}").EvaluationContext | undefined;
|
|
885
906
|
const evaluations: FlagsResult["flags"] = [];
|
|
886
907
|
|
|
@@ -901,7 +922,7 @@ const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number"
|
|
|
901
922
|
return { configured: true, flags: evaluations };
|
|
902
923
|
}
|
|
903
924
|
`,s=`
|
|
904
|
-
protected override runFlagSubscriptionRead(_functionPath: string, args: Record<string, unknown>, identity?: { identity?: Record<string, unknown>; userId?: string }): Promise<unknown> {${
|
|
925
|
+
protected override runFlagSubscriptionRead(_functionPath: string, args: Record<string, unknown>, identity?: { identity?: Record<string, unknown>; userId?: string }): Promise<unknown> {${r("() => flagsConfig.identify?.({ identity: identity?.identity ?? null, userId: identity?.userId ?? null })")}
|
|
905
926
|
const key = typeof args.key === "string" ? args.key : "";
|
|
906
927
|
|
|
907
928
|
// SECURITY: the reactive channel is public (any socket, no auth). Serve
|
|
@@ -933,7 +954,7 @@ const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number"
|
|
|
933
954
|
|
|
934
955
|
return flags.boolean(key, typeof args.default === "boolean" ? args.default : false, context);
|
|
935
956
|
}
|
|
936
|
-
`;return{constant:
|
|
957
|
+
`;return{constant:a,evaluateOverride:o,subscriptionOverride:s}},Pn=e=>{if(!e)return D;const t='throw new Error("ctx.analytics: no Analytics Engine binding found. Add an \\`analytics_engine_datasets\\` binding (env.ANALYTICS) to wrangler.jsonc, or pass \\`analytics\\` to createShardDO().");';return{build:`
|
|
937
958
|
const analyticsBinding = config.analytics?.(env) ?? (env as Record<string, unknown>).ANALYTICS;
|
|
938
959
|
const analytics: AnalyticsClient = analyticsBinding ? createAnalytics(analyticsBinding as AnalyticsEngineDatasetLike) : analyticsStub;
|
|
939
960
|
`,configField:`
|
|
@@ -947,7 +968,7 @@ const analyticsStub: AnalyticsClient = {
|
|
|
947
968
|
${t}
|
|
948
969
|
},
|
|
949
970
|
};
|
|
950
|
-
`}},
|
|
971
|
+
`}},En=e=>{if(!e)return D;const t='throw new Error("ctx.images: no Images binding found. Add an \\`images\\` binding (env.IMAGES) to wrangler.jsonc, or pass \\`images\\` to createShardDO().");';return{build:`
|
|
951
972
|
const imagesBinding = config.images?.(env) ?? (env as Record<string, unknown>).IMAGES;
|
|
952
973
|
const images: Images = imagesBinding ? createImages({ binding: imagesBinding as ImagesBindingLike }) : imagesStub;
|
|
953
974
|
`,configField:`
|
|
@@ -961,7 +982,7 @@ const imagesStub: Images = {
|
|
|
961
982
|
${t}
|
|
962
983
|
},
|
|
963
984
|
};
|
|
964
|
-
`}},
|
|
985
|
+
`}},Fn=e=>e?{build:`
|
|
965
986
|
const sql: SqlClient = config.sql ? config.sql(env) : sqlStub;
|
|
966
987
|
`,configField:`
|
|
967
988
|
sql?: (env: Record<string, unknown>) => SqlClient;`,contextField:`
|
|
@@ -971,7 +992,7 @@ const sqlStub: SqlClient = {
|
|
|
971
992
|
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))\\\`.");
|
|
972
993
|
},
|
|
973
994
|
};
|
|
974
|
-
`}:D,
|
|
995
|
+
`}:D,Mn=e=>{if(!e)return D;const t="throw new Error(\"ctx.browser: provide a \\`browser\\` config thunk, e.g. \\`browser: (env) => createBrowser({ binding: env.BROWSER, launch })\\` with \\`import { launch } from '@cloudflare/playwright'\\`.\");";return{build:`
|
|
975
996
|
const browser: Browser = config.browser ? config.browser(env) : browserStub;
|
|
976
997
|
`,configField:`
|
|
977
998
|
browser?: (env: Record<string, unknown>) => Browser;`,contextField:`
|
|
@@ -993,7 +1014,7 @@ const browserStub: Browser = {
|
|
|
993
1014
|
${t}
|
|
994
1015
|
},
|
|
995
1016
|
};
|
|
996
|
-
`}},
|
|
1017
|
+
`}},qn=e=>{if(!e)return D;const t='throw new Error("ctx.r2sql: no R2 SQL credentials found. Set \\`R2_SQL_TOKEN\\`, \\`R2_SQL_ACCOUNT_ID\\` (or \\`CLOUDFLARE_ACCOUNT_ID\\`), and \\`R2_SQL_BUCKET\\` in your env/.dev.vars, or pass an \\`r2sql\\` config thunk to createShardDO().");';return{build:`
|
|
997
1018
|
const r2sqlEnv = env as Record<string, unknown>;
|
|
998
1019
|
const r2sqlAccountId = (r2sqlEnv.R2_SQL_ACCOUNT_ID ?? r2sqlEnv.CLOUDFLARE_ACCOUNT_ID) as string | undefined;
|
|
999
1020
|
const r2sqlToken = r2sqlEnv.R2_SQL_TOKEN as string | undefined;
|
|
@@ -1025,7 +1046,7 @@ const r2sqlStub: R2SqlClient = {
|
|
|
1025
1046
|
${t}
|
|
1026
1047
|
},
|
|
1027
1048
|
};
|
|
1028
|
-
`}},
|
|
1049
|
+
`}},Bn=e=>e?{build:`
|
|
1029
1050
|
const pipelinesBinding = config.pipelines?.(env) ?? (env as Record<string, unknown>).PIPELINES;
|
|
1030
1051
|
const pipelines: PipelineClient = pipelinesBinding ? createPipelines({ binding: pipelinesBinding as PipelineBindingLike }) : pipelinesStub;
|
|
1031
1052
|
`,configField:`
|
|
@@ -1035,14 +1056,14 @@ const pipelinesStub: PipelineClient = {
|
|
|
1035
1056
|
throw new Error("ctx.pipelines: no Pipelines binding found. Add a \\\`pipelines\\\` binding (env.PIPELINES) to wrangler.jsonc, or pass \\\`pipelines\\\` to createShardDO().");
|
|
1036
1057
|
},
|
|
1037
1058
|
};
|
|
1038
|
-
`}:D,
|
|
1059
|
+
`}:D,cr=(e,t)=>{if(e.length===0)return"";const n=t?`, ${JSON.stringify(t)}`:"",r=e.map(o=>(m(o.exportName,`container export "${o.exportName}"`),m(o.className,`container class "${o.className}"`),`/** Container DO for the \`${o.exportName}\` definition (binding \`${o.bindingName}\`). */
|
|
1039
1060
|
export class ${o.className} extends LunoraContainer {
|
|
1040
1061
|
public constructor(ctx: ConstructorParameters<typeof LunoraContainer>[0], env: Record<string, unknown>) {
|
|
1041
1062
|
super(ctx, env, ${o.exportName}, "${o.exportName}"${n});
|
|
1042
1063
|
}
|
|
1043
1064
|
}
|
|
1044
1065
|
`)).join(`
|
|
1045
|
-
`),
|
|
1066
|
+
`),a=e.map(o=>o.exportName).join(", ");return`${k}/**
|
|
1046
1067
|
* Container-enabled Durable Object classes for the containers declared in
|
|
1047
1068
|
* \`lunora/containers.ts\`. Re-export them from your worker entry — wrangler
|
|
1048
1069
|
* requires each \`containers[].class_name\` to be exported by the worker:
|
|
@@ -1056,11 +1077,11 @@ export class ${o.className} extends LunoraContainer {
|
|
|
1056
1077
|
*/
|
|
1057
1078
|
import { LunoraContainer } from "@lunora/container/do";
|
|
1058
1079
|
|
|
1059
|
-
import { ${
|
|
1080
|
+
import { ${a} } from "../containers.js";
|
|
1060
1081
|
|
|
1061
1082
|
export { ContainerProxy } from "@lunora/container/do";
|
|
1062
1083
|
|
|
1063
|
-
${
|
|
1084
|
+
${r}`},jn=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const r of e)m(r.exportName,`container export "${r.exportName}"`),m(r.bindingName,`container binding "${r.bindingName}"`);const n=e.map(r=>{const a=r.maxInstances===void 0?"":`, maxInstances: ${String(r.maxInstances)}`;return` { binding: "${r.bindingName}", exportName: "${r.exportName}"${a} },`}).join(`
|
|
1064
1085
|
`);return{build:`
|
|
1065
1086
|
const containers = createContainerContext(env, LUNORA_CONTAINERS, ${t?JSON.stringify(t):"undefined"}, this.getCurrentTraceparent());
|
|
1066
1087
|
`,contextField:`
|
|
@@ -1069,14 +1090,14 @@ ${a}`},Fn=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[]
|
|
|
1069
1090
|
const LUNORA_CONTAINERS: ReadonlyArray<ContainerBindingSpec> = [
|
|
1070
1091
|
${n}
|
|
1071
1092
|
];
|
|
1072
|
-
`}},
|
|
1073
|
-
export class ${
|
|
1093
|
+
`}},ur=e=>{if(e.length===0)return"";const t=e.map(r=>(m(r.exportName,`workflow export "${r.exportName}"`),m(r.className,`workflow class "${r.className}"`),`/** WorkflowEntrypoint for the \`${r.exportName}\` definition (binding \`${r.bindingName}\`). */
|
|
1094
|
+
export class ${r.className} extends LunoraWorkflow<WorkflowParamsOf<typeof ${r.exportName}>, WorkflowOutputOf<typeof ${r.exportName}>> {
|
|
1074
1095
|
public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
1075
|
-
super(ctx, env, ${
|
|
1096
|
+
super(ctx, env, ${r.exportName}, "${r.exportName}");
|
|
1076
1097
|
}
|
|
1077
1098
|
}
|
|
1078
1099
|
`)).join(`
|
|
1079
|
-
`),n=e.map(
|
|
1100
|
+
`),n=e.map(r=>r.exportName).join(", ");return`${k}/**
|
|
1080
1101
|
* WorkflowEntrypoint classes for the workflows declared in
|
|
1081
1102
|
* \`lunora/workflows.ts\`. Re-export them from your worker entry — wrangler
|
|
1082
1103
|
* requires each \`workflows[].class_name\` to be exported by the worker:
|
|
@@ -1097,21 +1118,21 @@ type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params
|
|
|
1097
1118
|
/** Output type carried by a \`defineWorkflow\` definition (its phantom \`__output\`), so each entrypoint keeps the authored return type. */
|
|
1098
1119
|
type WorkflowOutputOf<Definition> = Definition extends { __output?: infer Output } ? Output : unknown;
|
|
1099
1120
|
|
|
1100
|
-
${t}`},
|
|
1101
|
-
export class ${
|
|
1121
|
+
${t}`},pr=e=>{if(e.length===0)return"";const t=e.filter(a=>a.voice).length>0,n=e.map(a=>{m(a.exportName,`agent export "${a.exportName}"`),m(a.className,`agent class "${a.className}"`);const o=`/** WorkflowEntrypoint for the \`${a.exportName}\` agent (binding \`${a.bindingName}\`). */
|
|
1122
|
+
export class ${a.className} extends LunoraWorkflow<AgentRunInput, AgentRunResult> {
|
|
1102
1123
|
public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
1103
|
-
super(ctx, env, compileAgentWorkflow(${
|
|
1124
|
+
super(ctx, env, compileAgentWorkflow(${a.exportName}, "${a.exportName}"), "${a.exportName}");
|
|
1104
1125
|
}
|
|
1105
1126
|
}
|
|
1106
|
-
`;if(!
|
|
1107
|
-
/** Voice-session Durable Object for the \`${
|
|
1127
|
+
`;if(!a.voice)return o;const s=a.voiceClassName??"",i=a.voiceBindingName??"";m(s,`agent voice class "${s}"`);const l=`
|
|
1128
|
+
/** Voice-session Durable Object for the \`${a.exportName}\` agent (binding \`${i}\`). */
|
|
1108
1129
|
export class ${s} extends VoiceSessionDO {
|
|
1109
1130
|
public constructor(ctx: ConstructorParameters<typeof VoiceSessionDO>[0], env: Record<string, unknown>) {
|
|
1110
|
-
super(ctx, env, ${
|
|
1131
|
+
super(ctx, env, ${a.exportName}, "${a.exportName}");
|
|
1111
1132
|
}
|
|
1112
1133
|
}
|
|
1113
1134
|
`;return`${o}${l}`}).join(`
|
|
1114
|
-
`),
|
|
1135
|
+
`),r=e.map(a=>a.exportName).join(", ");return`${k}/**
|
|
1115
1136
|
* WorkflowEntrypoint classes for the agents declared in \`lunora/agents.ts\`.
|
|
1116
1137
|
* Each \`defineAgent\` compiles a replay-safe tool-loop onto a Cloudflare
|
|
1117
1138
|
* Workflow. Re-export them from your worker entry — wrangler requires each
|
|
@@ -1123,9 +1144,9 @@ import LunoraWorkflow from "@lunora/workflow/do";
|
|
|
1123
1144
|
${t?'import { compileAgentWorkflow, VoiceSessionDO } from "@lunora/agent";':'import { compileAgentWorkflow } from "@lunora/agent";'}
|
|
1124
1145
|
import type { AgentRunInput, AgentRunResult } from "@lunora/agent";
|
|
1125
1146
|
|
|
1126
|
-
import { ${
|
|
1147
|
+
import { ${r} } from "../agents.js";
|
|
1127
1148
|
|
|
1128
|
-
${n}`},
|
|
1149
|
+
${n}`},hr=e=>{const t=e.filter(a=>a.mode==="push");if(t.length===0)return"";for(const a of t)m(a.exportName,`queue export "${a.exportName}"`);const n=t.map(a=>a.exportName).join(", "),r=t.map(a=>` ${JSON.stringify(a.name)}: { definition: ${a.exportName}, exportName: ${JSON.stringify(a.exportName)} },`).join(`
|
|
1129
1150
|
`);return`${k}/**
|
|
1130
1151
|
* Push-consumer registry for the queues declared in \`lunora/queues.ts\`. The
|
|
1131
1152
|
* composed worker's \`queue(batch, env, ctx)\` entry routes each delivered batch
|
|
@@ -1138,9 +1159,9 @@ import { ${n} } from "../queues.js";
|
|
|
1138
1159
|
|
|
1139
1160
|
/** Stable wrangler queue name → { definition, exportName } for batch routing. */
|
|
1140
1161
|
export const LUNORA_QUEUE_REGISTRY: QueueRegistry = {
|
|
1141
|
-
${
|
|
1162
|
+
${r}
|
|
1142
1163
|
};
|
|
1143
|
-
`},
|
|
1164
|
+
`},Wn=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`workflow export "${n.exportName}"`),m(n.bindingName,`workflow binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}" },`).join(`
|
|
1144
1165
|
`);return{build:`
|
|
1145
1166
|
const workflows = createWorkflowContext(env, LUNORA_WORKFLOWS);
|
|
1146
1167
|
`,contextField:`
|
|
@@ -1149,7 +1170,7 @@ ${a}
|
|
|
1149
1170
|
const LUNORA_WORKFLOWS: ReadonlyArray<WorkflowBindingSpec> = [
|
|
1150
1171
|
${t}
|
|
1151
1172
|
];
|
|
1152
|
-
`}},
|
|
1173
|
+
`}},Un=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`queue export "${n.exportName}"`),m(n.bindingName,`queue binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}", name: ${JSON.stringify(n.name)} },`).join(`
|
|
1153
1174
|
`);return{build:`
|
|
1154
1175
|
const queues = createQueueContext(env, LUNORA_QUEUES);
|
|
1155
1176
|
`,contextField:`
|
|
@@ -1158,7 +1179,7 @@ ${t}
|
|
|
1158
1179
|
const LUNORA_QUEUES: ReadonlyArray<QueueBindingSpec> = [
|
|
1159
1180
|
${t}
|
|
1160
1181
|
];
|
|
1161
|
-
`}},
|
|
1182
|
+
`}},Kn=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`agent export "${n.exportName}"`),m(n.bindingName,`agent binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}"${n.publicRun===!0?", publicRun: true":""} },`).join(`
|
|
1162
1183
|
`);return{build:`
|
|
1163
1184
|
const agents = createAgentContext(env, LUNORA_AGENTS);
|
|
1164
1185
|
`,contextField:`
|
|
@@ -1167,21 +1188,21 @@ ${t}
|
|
|
1167
1188
|
const LUNORA_AGENTS: ReadonlyArray<AgentBindingSpec> = [
|
|
1168
1189
|
${t}
|
|
1169
1190
|
];
|
|
1170
|
-
`}},
|
|
1191
|
+
`}},Qn=e=>{if(e.length===0)return{constant:"",override:""};const t={workflows:e.map(n=>({binding:n.bindingName,className:n.className,exportName:n.exportName,name:n.name}))};return{constant:`
|
|
1171
1192
|
/** Read-only declared-workflow metadata (discovered from \`lunora/workflows.ts\`) served via \`__lunora_admin__:listWorkflows\` for the studio's workflows view. */
|
|
1172
1193
|
const LUNORA_WORKFLOWS_INFO: WorkflowsResult = ${JSON.stringify(t,void 0,4)};
|
|
1173
1194
|
`,override:`
|
|
1174
1195
|
protected override workflowsMetadata(): WorkflowsResult {
|
|
1175
1196
|
return LUNORA_WORKFLOWS_INFO;
|
|
1176
1197
|
}
|
|
1177
|
-
`}},
|
|
1198
|
+
`}},Jn=e=>{if(e.length===0)return{constant:"",override:""};const t={queues:e.map(n=>({binding:n.bindingName,...n.tuning.deadLetterQueue===void 0?{}:{deadLetterQueue:n.tuning.deadLetterQueue},exportName:n.exportName,mode:n.mode,name:n.name}))};return{constant:`
|
|
1178
1199
|
/** Read-only declared-queue metadata (discovered from \`lunora/queues.ts\`) served via \`__lunora_admin__:listQueues\` for the studio's queues view. */
|
|
1179
1200
|
const LUNORA_QUEUES_INFO: QueuesResult = ${JSON.stringify(t,void 0,4)};
|
|
1180
1201
|
`,override:`
|
|
1181
1202
|
protected override queuesMetadata(): QueuesResult {
|
|
1182
1203
|
return LUNORA_QUEUES_INFO;
|
|
1183
1204
|
}
|
|
1184
|
-
`}},
|
|
1205
|
+
`}},Gn=e=>{if(!e)return{build:"",configField:"",contextField:"",imports:[],stub:""};const t='throw new Error("ctx.payments: no payment configured. Pass \\`payment\\` to createShardDO().");';return{imports:['import type { LunoraDatabaseLike as LunoraPaymentDbLike, LunoraPayment, PaymentsFromContextOptions } from "@lunora/payment";','import { paymentsFromContext } from "@lunora/payment";'],build:`
|
|
1185
1206
|
const payments: LunoraPayment = config.payment
|
|
1186
1207
|
? paymentsFromContext({ auth: { userId: userId ?? null }, db: db as unknown as LunoraPaymentDbLike }, config.payment(env))
|
|
1187
1208
|
: paymentStub;
|
|
@@ -1217,7 +1238,7 @@ const paymentStub: LunoraPayment = {
|
|
|
1217
1238
|
${t}
|
|
1218
1239
|
},
|
|
1219
1240
|
} as unknown as LunoraPayment;
|
|
1220
|
-
`}},
|
|
1241
|
+
`}},Vn=e=>e?{imports:['import type { X402Pay, X402PayConfig } from "@lunora/x402/pay";','import { lazyX402Pay } from "@lunora/x402/pay";'],build:`
|
|
1221
1242
|
const x402: X402Pay = config.x402
|
|
1222
1243
|
? lazyX402Pay(config.x402(env), { getSecret: (name: string) => secrets.get(name) })
|
|
1223
1244
|
: x402Stub;
|
|
@@ -1229,7 +1250,7 @@ const x402Stub: X402Pay = {
|
|
|
1229
1250
|
throw new Error("ctx.x402: no pay rail configured. Pass \\\`x402\\\` to createShardDO().");
|
|
1230
1251
|
},
|
|
1231
1252
|
} as unknown as X402Pay;
|
|
1232
|
-
`}:{build:"",configField:"",contextField:"",imports:[],stub:""},
|
|
1253
|
+
`}:{build:"",configField:"",contextField:"",imports:[],stub:""},Hn=(e,t,n,r)=>["AdvisoryFinding","DatabaseWriterLike","DataMigrationLike",...r?["FlagsResult"]:[],"MaskPoliciesResult","MigrationRunResult",...n?["QueuesResult"]:[],"RunShardApplyCdcArgs","RunShardMigrationArgs","RlsPoliciesResult","RunShardRankBeforeArgs","RunShardRankPageArgs","RunShardWriteArgs","RunShardWriteResult","SchedulerLike","SchemaLike","ShardDOState","ShardRankPageResult","SqlExec","StorageRulesResult","StudioFeaturesResult","SystemReaderStorageLike","TelemetrySink",...t?["WorkflowsResult"]:[],...e?["WriteHook"]:[]],gr=({advisories:e=[],agents:t=[],containers:n=[],env:r,flagKeys:a=[],hasAccessFacade:o=!1,hasAi:s=!1,hasAnalytics:i=!1,hasBrowser:l=!1,hasFlags:u=!1,hasHyperdrive:p=!1,hasImages:b=!1,hasKv:w=!1,hasNotify:$=!1,hasPayments:d=!1,hasPipelines:c=!1,hasR2sql:g=!1,hasX402:f=!1,maskMetadata:R,mutators:S=[],queues:x=[],rlsMetadata:_,schema:y,shapes:Y=[],storageRules:Z,studioFeatures:ee,useUmbrella:I=!1,workflows:j=[]})=>{const N=V(I),W=S.length>0,L=Y.length>0,{build:te,configField:H,contextField:C,stub:P}=Tn(s),U=_n(o),E=An(w),K=Ln(u,N.flags),ne=In(a,u,N.flags),re=Cn($),ae=Dn(r),Q=Pn(i),M=En(b),q=Fn(p),B=Mn(l),F=qn(g),z=Bn(c),{build:ye,contextField:ge,importLines:me,specs:oe}=Un(x),{build:we,contextField:xe,importLines:fe,specs:ie}=jn(n,y.jurisdiction),{build:ke,contextField:ve,importLines:be,specs:$e}=Wn(j),{build:Se,contextField:se,importLines:le,specs:Re}=Kn(t),{build:Ne,configField:Oe,contextField:de,imports:ce,stub:h}=Gn(d),{build:Te,configField:tt,imports:nt,stub:rt}=Vn(f),at=e,ot=_??{policies:[],roles:[]},it=R??{columns:[]},st=Z??{rules:[]},lt=ee??{analytics:!1,auth:!1,containers:!1,flags:!1,kv:!1,mail:!1,payments:!1,queues:!1,scheduler:!1,storage:!1,vectors:!1,workflows:!1},{constant:dt,override:ct}=Qn(j),{constant:ut,override:pt}=Jn(x),J=y.vectorIndexes.length>0,ue=y.tables.some(O=>O.shardMode==="global"),Ae=y.tables.some(O=>O.shardMode==="global"&&O.globalBackend==="hyperdrive"),Ee=y.tables.some(O=>O.shardMode==="global"&&O.globalBackend!=="hyperdrive"),G=y.tables.some(O=>O.externalSource!==void 0);if(Ee&&Ae)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 Le=y.tables.length>0,ht=vn(y),gt=Sn(y),mt=Nn(y),ft=$n(y),Fe=Rn(y),Me=Hn(J,j.length>0,x.length>0,u);L&&Me.push("WhereInput");const qe=On(ue),bt=L?`
|
|
1233
1254
|
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 {
|
|
1234
1255
|
const shape = LUNORA_SHAPES[name];
|
|
1235
1256
|
|
|
@@ -1282,15 +1303,15 @@ const x402Stub: X402Pay = {
|
|
|
1282
1303
|
|
|
1283
1304
|
return { columns: shape.columns, effectiveWhere, global: isGlobal, table: shape.table };
|
|
1284
1305
|
}
|
|
1285
|
-
`:"",
|
|
1306
|
+
`:"",yt=W?`
|
|
1286
1307
|
protected override isCustomMutator(functionPath: string): boolean {
|
|
1287
1308
|
return LUNORA_MUTATOR_PATHS.has(functionPath);
|
|
1288
1309
|
}
|
|
1289
|
-
`:"",
|
|
1290
|
-
vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",
|
|
1291
|
-
d1?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:""
|
|
1292
|
-
hyperdriveGlobal?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:""
|
|
1293
|
-
sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",
|
|
1310
|
+
`:"",wt=L?"\n/** Per-table RLS read policies (hoisted from `.use(rls(...))` chains) the shape resolver AND-merges into each `defineShape` predicate so partial replication honours read policies. */\nconst LUNORA_RLS_READ_REGISTRY = buildRlsReadRegistry(Object.values(LUNORA_FUNCTIONS));\n":"",xt=L?"assertShapeShardable, ":"",pe=[`import type { ${Me.join(", ")} } from "${N.do}";`,`import { applyCdcChanges, ${xt}createShardCtxDb, ${G?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}runDataMigration, runShardMigrations, ${qe.importFragment}ShardDO as ShardDOBase } from "${N.do}";`,...G?[`import type { ExternalSourceLike, SourceClientLike } from "${N.do}";`]:[],L?`import { asBucketStorage, buildRlsReadRegistry, composeShapeReadWhere, createSecrets, LunoraError } from "${N.server}";`:`import { asBucketStorage, createSecrets, LunoraError } from "${N.server}";`];Le&&pe.push(`import { bindOrm, bindTableFacade } from "${N.server}";`),J&&pe.push('import type { SchemaLike as VectorSchemaLike, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";','import { createContextVectors, createVectors, createVectorSyncHook } from "@lunora/bindings/vectors";'),s&&pe.push('import type { AiBindingLike, LunoraAi } from "@lunora/ai";','import { createAi } from "@lunora/ai";'),pe.push(...U.importLines,...E.importLines,...K.importLines,...re.importLines,...ae.importLines,...Q.importLines,...M.importLines,...q.importLines,...B.importLines,...F.importLines,...z.importLines,...fe,...be,...me,...le,...ce,...nt,"",'import schema from "../schema.js";',`import { ${["LUNORA_FUNCTIONS","LUNORA_LIFECYCLE_HOOKS","LUNORA_MIGRATIONS",...W?["LUNORA_MUTATOR_PATHS"]:[],...L?["LUNORA_SHAPES"]:[]].join(", ")} } from "./functions.js";`);const kt=J?`
|
|
1311
|
+
vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",vt=Ee?`
|
|
1312
|
+
d1?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",$t=Ae?`
|
|
1313
|
+
hyperdriveGlobal?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",St=G?`
|
|
1314
|
+
sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",Rt=ue?'\nconst globalDbStub: DatabaseWriterLike = {\n aggregate: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n count: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n delete: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findFirst: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findFirstOrThrow: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findMany: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n get: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n groupBy: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n insert: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n normalizeId: () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n patch: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n query: () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n rank: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n rankPage: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n replace: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n};\n':"",Nt=J?`
|
|
1294
1315
|
const vectorsStub: VectorSearchLike = {
|
|
1295
1316
|
deleteByIds: async () => {
|
|
1296
1317
|
throw new Error("ctx.vectors: no vectors configured. Pass \`vectors\` to createShardDO().");
|
|
@@ -1308,7 +1329,7 @@ const vectorsStub: VectorSearchLike = {
|
|
|
1308
1329
|
throw new Error("ctx.vectors: no vectors configured. Pass \`vectors\` to createShardDO().");
|
|
1309
1330
|
},
|
|
1310
1331
|
};
|
|
1311
|
-
`:"",
|
|
1332
|
+
`:"",Ot=J?`
|
|
1312
1333
|
let vectors: VectorSearchLike;
|
|
1313
1334
|
let onWrite: WriteHook | undefined;
|
|
1314
1335
|
|
|
@@ -1323,7 +1344,7 @@ const vectorsStub: VectorSearchLike = {
|
|
|
1323
1344
|
}
|
|
1324
1345
|
`:"",Be=ue?`
|
|
1325
1346
|
globalDb,`:"",je=`
|
|
1326
|
-
auth: { identity: identity ?? null, userId: userId ?? null },`,
|
|
1347
|
+
auth: { identity: identity ?? null, userId: userId ?? null },`,Tt=J?`{${je}
|
|
1327
1348
|
broadcast: (delta) => {
|
|
1328
1349
|
this.recordChangedTable(delta.table);
|
|
1329
1350
|
},
|
|
@@ -1348,10 +1369,10 @@ const vectorsStub: VectorSearchLike = {
|
|
|
1348
1369
|
schema: schema as unknown as SchemaLike,
|
|
1349
1370
|
sql: this.sql as SqlExec,
|
|
1350
1371
|
storage,${Be}
|
|
1351
|
-
}`,
|
|
1352
|
-
vectors,`:"",
|
|
1353
|
-
orm: bindOrm(facade),`:"",
|
|
1354
|
-
`:"",
|
|
1372
|
+
}`,At=J?`
|
|
1373
|
+
vectors,`:"",Lt=Le?`
|
|
1374
|
+
orm: bindOrm(facade),`:"",Ct="",We=Ae?"config.hyperdriveGlobal":"config.d1",Dt=ue?` const globalDb: DatabaseWriterLike = ${We}?.(env, { identity, userId }) ?? globalDbStub;
|
|
1375
|
+
`:"",_t=L&&ue?`
|
|
1355
1376
|
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 }>> {
|
|
1356
1377
|
const env = this.env as Record<string, unknown>;
|
|
1357
1378
|
const globalDb: DatabaseWriterLike = ${We}?.(env, identity) ?? globalDbStub;
|
|
@@ -1381,10 +1402,10 @@ const vectorsStub: VectorSearchLike = {
|
|
|
1381
1402
|
|
|
1382
1403
|
return rows;
|
|
1383
1404
|
}
|
|
1384
|
-
`:"",
|
|
1405
|
+
`:"",It=G?`
|
|
1385
1406
|
const sourceClientCache = new WeakMap<object, Map<string, SourceClientLike>>();
|
|
1386
1407
|
const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
|
|
1387
|
-
`:"",
|
|
1408
|
+
`:"",Pt=G?`
|
|
1388
1409
|
protected override async pollExternalSources(): Promise<number | undefined> {
|
|
1389
1410
|
const env = (this.env ?? {}) as Record<string, unknown>;
|
|
1390
1411
|
const sourced = Object.entries((schema as unknown as SchemaLike).tables)
|
|
@@ -1485,10 +1506,10 @@ const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
|
|
|
1485
1506
|
|
|
1486
1507
|
return nextDueAt;
|
|
1487
1508
|
}
|
|
1488
|
-
`:"",Ue=Fe.length>0,
|
|
1509
|
+
`:"",Ue=Fe.length>0,Et=G||Ue?`
|
|
1489
1510
|
public constructor(state: ShardDOState, env: unknown) {
|
|
1490
1511
|
super(state, env);
|
|
1491
|
-
${
|
|
1512
|
+
${G?`
|
|
1492
1513
|
const autoSourced = Object.values((schema as unknown as SchemaLike).tables).some((definition) => {
|
|
1493
1514
|
const source = (definition as { externalSource?: ExternalSourceLike }).externalSource;
|
|
1494
1515
|
|
|
@@ -1503,21 +1524,21 @@ ${J?`
|
|
|
1503
1524
|
void this.scheduleTtlSweep();
|
|
1504
1525
|
}
|
|
1505
1526
|
`:""} }
|
|
1506
|
-
`:"",
|
|
1527
|
+
`:"",Ft=Le?`
|
|
1507
1528
|
const facade = db as unknown as Record<string, ReturnType<typeof bindTableFacade>>;
|
|
1508
|
-
${y.tables.map(
|
|
1529
|
+
${y.tables.map(O=>` facade[${JSON.stringify(O.name)}] = bindTableFacade(db, ${JSON.stringify(O.name)});`).join(`
|
|
1509
1530
|
`)}
|
|
1510
|
-
`:"",
|
|
1531
|
+
`:"",Mt=`${U.build}${E.build}${K.build}${Q.build}${ae.build}
|
|
1511
1532
|
const secrets = createSecrets(env);
|
|
1512
|
-
`,
|
|
1513
|
-
secrets,`,
|
|
1533
|
+
`,qt=`${U.contextField}${E.contextField}${K.contextField}${re.contextField}${Q.contextField}${ae.contextField}
|
|
1534
|
+
secrets,`,Bt=re.build,Ke=b||p||l||g||c||f,jt=Ke?`
|
|
1514
1535
|
// ActionCtx-only helpers (external, non-deterministic I/O): constructed
|
|
1515
1536
|
// and attached only for an \`action\` so query/mutation ctx never carry them.
|
|
1516
1537
|
if (isAction) {
|
|
1517
1538
|
${M.build}${q.build}${B.build}${F.build}${z.build}${Te}${[...b?[" ctx.images = images;"]:[],...p?[" ctx.sql = sql;"]:[],...l?[" ctx.browser = browser;"]:[],...g?[" ctx.r2sql = r2sql;"]:[],...c?[" ctx.pipelines = pipelines;"]:[],...f?[" ctx.x402 = x402;"]:[]].join(`
|
|
1518
1539
|
`)}
|
|
1519
1540
|
}
|
|
1520
|
-
`:"",
|
|
1541
|
+
`:"",Wt=Ke?` const isAction = LUNORA_FUNCTIONS[options.functionPath ?? ""]?.kind === "action";
|
|
1521
1542
|
`:"";return`${k}${pe.join(`
|
|
1522
1543
|
`)}
|
|
1523
1544
|
|
|
@@ -1528,42 +1549,42 @@ interface FunctionReference {
|
|
|
1528
1549
|
}
|
|
1529
1550
|
|
|
1530
1551
|
/** Foreign-key columns per table (\`v.id("target")\` fields) for the data browser. */
|
|
1531
|
-
const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(
|
|
1552
|
+
const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(ht,void 0,4)};
|
|
1532
1553
|
|
|
1533
1554
|
/** Declared indexes per table (secondary, search, geo, rank, vector) for the schema viewer. */
|
|
1534
|
-
const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(
|
|
1555
|
+
const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(gt,void 0,4)};
|
|
1535
1556
|
|
|
1536
1557
|
/** Columns per table (typed, with PK/FK markers) for the studio's schema diagram, served via \`__lunora_admin__:describeTable\`. */
|
|
1537
|
-
const LUNORA_TABLE_COLUMNS: Record<string, Array<{ isStorage?: boolean; name: string; optional: boolean; pk?: boolean; ref?: string; type: string }>> = ${JSON.stringify(
|
|
1558
|
+
const LUNORA_TABLE_COLUMNS: Record<string, Array<{ isStorage?: boolean; name: string; optional: boolean; pk?: boolean; ref?: string; type: string }>> = ${JSON.stringify(mt,void 0,4)};
|
|
1538
1559
|
|
|
1539
1560
|
/** Storage-key columns per table (\`v.storage(...)\` fields) for the file browser's records↔files join. */
|
|
1540
|
-
const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify(
|
|
1561
|
+
const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify(ft,void 0,4)};
|
|
1541
1562
|
|
|
1542
1563
|
/** Declarative TTL policies (\`.ttl(field, { after? })\`) the DO alarm sweep auto-expires rows for. */
|
|
1543
1564
|
const LUNORA_TTL_SWEEPS: Array<{ after?: number; field: string; softDeleteField?: string; table: string }> = ${JSON.stringify(Fe,void 0,4)};
|
|
1544
1565
|
|
|
1545
1566
|
/** Static schema advisories (computed by @lunora/advisor at codegen time) served via \`__lunora_admin__:getAdvisories\`. */
|
|
1546
|
-
const LUNORA_ADVISORIES: AdvisoryFinding[] = ${JSON.stringify(
|
|
1567
|
+
const LUNORA_ADVISORIES: AdvisoryFinding[] = ${JSON.stringify(at,void 0,4)};
|
|
1547
1568
|
|
|
1548
1569
|
/** Read-only RLS metadata (policies + roles discovered from \`.use(rls(...))\` chains) served via \`__lunora_admin__:rlsPolicies\` for the studio's RLS inspector. */
|
|
1549
|
-
const LUNORA_RLS_METADATA: RlsPoliciesResult = ${JSON.stringify(
|
|
1570
|
+
const LUNORA_RLS_METADATA: RlsPoliciesResult = ${JSON.stringify(ot,void 0,4)};
|
|
1550
1571
|
|
|
1551
1572
|
/** 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. */
|
|
1552
|
-
const LUNORA_MASK_METADATA: MaskPoliciesResult = ${JSON.stringify(
|
|
1573
|
+
const LUNORA_MASK_METADATA: MaskPoliciesResult = ${JSON.stringify(it,void 0,4)};
|
|
1553
1574
|
|
|
1554
1575
|
/** Read-only storage access-rule metadata (discovered from \`.use(storageRules(...))\` chains) served via \`__lunora_admin__:storageRules\` for the studio's access-rules view. */
|
|
1555
|
-
const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(
|
|
1576
|
+
const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(st,void 0,4)};
|
|
1556
1577
|
|
|
1557
1578
|
/** 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. */
|
|
1558
|
-
const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(
|
|
1559
|
-
${ne.constant}${
|
|
1579
|
+
const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(lt,void 0,4)};
|
|
1580
|
+
${ne.constant}${wt}${dt}${ut}${ie}${$e}${oe}${Re}
|
|
1560
1581
|
export interface ShardDOConfig {
|
|
1561
1582
|
/** Opt into change-data-capture: records a post-image to \`__cdc_log\` on every write (backs streaming export + replay-PITR). */
|
|
1562
1583
|
cdc?: boolean;
|
|
1563
1584
|
/** Optional telemetry sink. When supplied, each \`ctx.log.*\` call is forwarded to \`sink.onLog\`. Pass the SAME sink you give \`createWorker({ observability })\` (which drives \`onRpc\`) to route both RPC and log events. */
|
|
1564
1585
|
observability?: (env: Record<string, unknown>) => TelemetrySink | undefined;
|
|
1565
1586
|
scheduler?: (env: Record<string, unknown>) => unknown;
|
|
1566
|
-
storage?: (env: Record<string, unknown>) => unknown;${
|
|
1587
|
+
storage?: (env: Record<string, unknown>) => unknown;${kt}${H}${E.configField}${K.configField}${Q.configField}${M.configField}${q.configField}${B.configField}${F.configField}${z.configField}${Oe}${tt}${vt}${$t}${St}
|
|
1567
1588
|
}
|
|
1568
1589
|
|
|
1569
1590
|
const schedulerStub = {
|
|
@@ -1601,7 +1622,7 @@ const storageStub = {
|
|
|
1601
1622
|
throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
|
|
1602
1623
|
},
|
|
1603
1624
|
};
|
|
1604
|
-
${
|
|
1625
|
+
${Rt}${It}${Nt}${P}${E.stub}${K.stub}${Q.stub}${M.stub}${q.stub}${B.stub}${F.stub}${z.stub}${h}${rt}${Ct}
|
|
1605
1626
|
// Bound in-process \`ctx.run*\` composition depth so a self- or cyclically-
|
|
1606
1627
|
// referencing call fails loudly with a clear error instead of overflowing the
|
|
1607
1628
|
// stack. Tracked across the awaited handler chain (one DO invocation is
|
|
@@ -1638,7 +1659,7 @@ const dispatchRun = async (expected: FunctionKind, functionPath: string, args: R
|
|
|
1638
1659
|
* from the worker entry so wrangler binds it by name.
|
|
1639
1660
|
*/
|
|
1640
1661
|
export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOState, env: unknown) => ShardDOBase =>
|
|
1641
|
-
class extends ShardDOBase {${
|
|
1662
|
+
class extends ShardDOBase {${Et}
|
|
1642
1663
|
private migrated = false;
|
|
1643
1664
|
|
|
1644
1665
|
public override async handleRpc(functionPath: string, args: Record<string, unknown>): Promise<unknown> {
|
|
@@ -1714,7 +1735,7 @@ ${qe.override}
|
|
|
1714
1735
|
iterator: (signal) => (registered.handler as (context: unknown, args: Record<string, unknown>, signal: AbortSignal) => AsyncIterable<unknown>)(this.buildCtx({ functionPath }), args, signal),
|
|
1715
1736
|
};
|
|
1716
1737
|
}
|
|
1717
|
-
${
|
|
1738
|
+
${yt}${bt}${_t}${Pt}
|
|
1718
1739
|
protected override lifecycleHookPaths(event: "connect" | "disconnect"): readonly string[] {
|
|
1719
1740
|
return LUNORA_LIFECYCLE_HOOKS[event];
|
|
1720
1741
|
}
|
|
@@ -1754,7 +1775,7 @@ ${bt}${ft}${Dt}${It}
|
|
|
1754
1775
|
protected override studioFeatures(): StudioFeaturesResult {
|
|
1755
1776
|
return LUNORA_STUDIO_FEATURES;
|
|
1756
1777
|
}
|
|
1757
|
-
${ne.evaluateOverride}${ne.subscriptionOverride}${
|
|
1778
|
+
${ne.evaluateOverride}${ne.subscriptionOverride}${ct}${pt}
|
|
1758
1779
|
protected override advisories(): AdvisoryFinding[] {
|
|
1759
1780
|
return LUNORA_ADVISORIES;
|
|
1760
1781
|
}
|
|
@@ -1976,7 +1997,7 @@ ${ne.evaluateOverride}${ne.subscriptionOverride}${dt}${ut}
|
|
|
1976
1997
|
// dispatch path) fall back to the per-request fields as before.
|
|
1977
1998
|
const userId = options.identity ? options.identity.userId : this.getCurrentUserId();
|
|
1978
1999
|
const identity = options.identity ? options.identity.identity : this.getCurrentIdentity();
|
|
1979
|
-
${
|
|
2000
|
+
${Ot}${te}${Mt}${we}${ke}${ye}${Se}
|
|
1980
2001
|
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
1981
2002
|
// Build the storage adapter once and share it between \`ctx.storage\`
|
|
1982
2003
|
// and \`ctx.db.system._storage\` so both read the same R2 binding. The
|
|
@@ -2003,13 +2024,13 @@ ${Nt}${te}${Ft}${we}${ke}${ye}${Se}
|
|
|
2003
2024
|
// so both write to the same trace.
|
|
2004
2025
|
const span = this.makeDispatchSpan(traceAnchor, observability);
|
|
2005
2026
|
|
|
2006
|
-
${
|
|
2027
|
+
${Dt} // \`ctx.db\`, wrapped in automatic instrumentation: by default this
|
|
2007
2028
|
// adds aggregate counters (call count, total time, per-operation
|
|
2008
2029
|
// breakdown) to the wide event rather than a span per call, so a
|
|
2009
2030
|
// handler making hundreds of queries stays readable. See
|
|
2010
2031
|
// \`instrumentDatabase\` for the \`"spans"\` / \`"off"\` levels.
|
|
2011
|
-
const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${
|
|
2012
|
-
${
|
|
2032
|
+
const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${Tt}), logFunctionPath, traceAnchor, observability);
|
|
2033
|
+
${Ft}${Ne}
|
|
2013
2034
|
|
|
2014
2035
|
// \`ctx.trace\` / \`ctx.metrics\`: spans and measurements to the same sink.
|
|
2015
2036
|
// The trace anchor is threaded explicitly for the same reason \`identity\`
|
|
@@ -2017,7 +2038,7 @@ ${Et}${Ne}
|
|
|
2017
2038
|
// writing mutation's trace from the shared per-request field.
|
|
2018
2039
|
const trace = this.makeTracer(logFunctionPath, observability, traceAnchor);
|
|
2019
2040
|
const metrics = this.makeMetrics(logFunctionPath, observability);
|
|
2020
|
-
${
|
|
2041
|
+
${Bt}
|
|
2021
2042
|
// \`ctx.now\`: the wall-clock instant (epoch ms) this function began,
|
|
2022
2043
|
// captured ONCE so the whole handler body sees a single stable value.
|
|
2023
2044
|
// Query/mutation handlers must be deterministic (they may be re-run on
|
|
@@ -2040,13 +2061,13 @@ ${qt}
|
|
|
2040
2061
|
ip: this.getCurrentIp(),
|
|
2041
2062
|
log,
|
|
2042
2063
|
metrics,
|
|
2043
|
-
now,${
|
|
2064
|
+
now,${Lt}
|
|
2044
2065
|
scheduler,
|
|
2045
2066
|
span,
|
|
2046
2067
|
storage,
|
|
2047
|
-
trace,${
|
|
2068
|
+
trace,${At}${C}${qt}${de}${xe}${ve}${ge}${se}
|
|
2048
2069
|
};
|
|
2049
|
-
${
|
|
2070
|
+
${Wt}${jt}
|
|
2050
2071
|
ctx.runAction = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("action", reference.__lunoraRef, fnArgs, ctx);
|
|
2051
2072
|
ctx.runMutation = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("mutation", reference.__lunoraRef, fnArgs, ctx);
|
|
2052
2073
|
ctx.runQuery = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("query", reference.__lunoraRef, fnArgs, ctx);
|
|
@@ -2054,21 +2075,21 @@ ${jt}${Bt}
|
|
|
2054
2075
|
return ctx;
|
|
2055
2076
|
}
|
|
2056
2077
|
};
|
|
2057
|
-
`},Pe=e=>{switch(e.kind){case"array":case"object":case"record":case"union":return{builder:"text",mode:"json",notNull:!0,typeAnnotation:
|
|
2058
|
-
`),
|
|
2059
|
-
${e.indexes.map(
|
|
2078
|
+
`},Pe=e=>{switch(e.kind){case"array":case"object":case"record":case"union":return{builder:"text",mode:"json",notNull:!0,typeAnnotation:T(e)};case"bigint":return{builder:"blob",mode:"bigint",notNull:!0};case"boolean":return{builder:"integer",mode:"boolean",notNull:!0};case"bytes":return{builder:"blob",mode:"buffer",notNull:!0};case"date":case"timestamp":return{builder:"integer",notNull:!0};case"id":return{builder:"text",notNull:!0};case"literal":{const t=e.literalValue??"";return t.startsWith('"')||t.startsWith("'")?{builder:"text",notNull:!0}:t==="true"||t==="false"?{builder:"integer",mode:"boolean",notNull:!0}:t==="null"?{builder:"text",notNull:!0}:{builder:"real",notNull:!0}}case"null":return{builder:"text",notNull:!0};case"number":return{builder:"real",notNull:!0};case"optional":return{...e.inner?Pe(e.inner):{builder:"text",notNull:!1},notNull:!1};case"storage":case"string":return{builder:"text",notNull:!0};default:return{builder:"text",notNull:!0}}},zn=(e,t,n)=>{m(e,"drizzle column name");const r=Pe(t),a=t.kind==="optional"&&t.inner?t.inner:t,o=r.mode?`, { mode: "${r.mode}" }`:"";let s=`${r.builder}("${e}"${o})`;return r.typeAnnotation&&(s+=`.$type<${r.typeAnnotation}>()`),a.kind==="id"&&a.tableName&&n.has(a.tableName)&&(s+=`.references(() => ${a.tableName}._id)`),r.notNull&&(s+=".notNull()"),s},Xn=e=>{m(e.name,"drizzle index name");const t=e.unique?"uniqueIndex":"index",n=e.fields.map(r=>(m(r,"drizzle index field"),`t.${r}`)).join(", ");return` ${e.name}: ${t}("${e.name}").on(${n}),`},Yn=(e,t)=>{m(e.name,"table name");const n=[' _id: text("_id").primaryKey(),',' _creationTime: integer("_creationTime").notNull(),',...Object.entries(e.shape).map(([a,o])=>` ${a}: ${zn(a,o,t)},`)].join(`
|
|
2079
|
+
`),r=e.indexes.length>0?`, (t) => ({
|
|
2080
|
+
${e.indexes.map(a=>Xn(a)).join(`
|
|
2060
2081
|
`)}
|
|
2061
2082
|
})`:"";return`export const ${e.name} = sqliteTable("${e.name}", {
|
|
2062
2083
|
${n}
|
|
2063
|
-
}${
|
|
2064
|
-
`;const n=V(t),{columns:
|
|
2084
|
+
}${r});`},Zn=e=>{const t=new Set,n=new Set;t.add("text"),t.add("integer"),t.add("sqliteTable");for(const r of e){for(const a of Object.values(r.shape)){const o=Pe(a);t.add(o.builder)}for(const a of r.indexes)n.add(a.unique?"uniqueIndex":"index")}return{columns:[...t].toSorted((r,a)=>r.localeCompare(a)),indexes:[...n].toSorted((r,a)=>r.localeCompare(a))}},Je=(e,t=!1)=>{if(e.length===0)return`${k}export {};
|
|
2085
|
+
`;const n=V(t),{columns:r,indexes:a}=Zn(e),o=[...a,...r].toSorted((l,u)=>l.localeCompare(u)),s=new Set(e.map(l=>l.name)),i=e.map(l=>Yn(l,s)).join(`
|
|
2065
2086
|
|
|
2066
2087
|
`);return`${k}import { ${o.join(", ")} } from "${n.serverDrizzle}";
|
|
2067
2088
|
|
|
2068
2089
|
${i}
|
|
2069
|
-
`},
|
|
2070
|
-
`),r
|
|
2071
|
-
${
|
|
2090
|
+
`},mr=(e,t=!1)=>{const n=e.tables.filter(a=>a.shardMode==="global"),r=e.tables.filter(a=>a.shardMode!=="global");return{global:Je(n,t),shard:Je(r,t)}},fr=e=>{const t=[],n=new Map;for(const i of e){const l=n.get(i.cron);l?l.push(i):(n.set(i.cron,[i]),t.push(i.cron))}const r=t.map(i=>` ${JSON.stringify(i)},`).join(`
|
|
2091
|
+
`),a=r.length>0?`
|
|
2092
|
+
${r}
|
|
2072
2093
|
`:"",o=[...n.entries()].map(([i,l])=>{const u=l.map(p=>{const b=p.workflow?`workflow: ${JSON.stringify(p.workflow.binding)}`:`functionPath: ${JSON.stringify(p.functionPath)}`;return` { name: ${JSON.stringify(p.name)}, ${b}, args: ${JSON.stringify(p.args)} },`}).join(`
|
|
2073
2094
|
`);return` ${JSON.stringify(i)}: [
|
|
2074
2095
|
${u}
|
|
@@ -2093,14 +2114,14 @@ export interface LunoraCronJob {
|
|
|
2093
2114
|
* Deduplicated cron schedules — mirror of wrangler's \`triggers.crons\`. The
|
|
2094
2115
|
* Lunora vite plugin keeps \`wrangler.jsonc\` in sync with this array.
|
|
2095
2116
|
*/
|
|
2096
|
-
export const LUNORA_CRON_TRIGGERS: ReadonlyArray<string> = [${
|
|
2117
|
+
export const LUNORA_CRON_TRIGGERS: ReadonlyArray<string> = [${a}];
|
|
2097
2118
|
|
|
2098
2119
|
/**
|
|
2099
2120
|
* Dispatcher map keyed by cron expression. The Worker's \`scheduled()\` handler
|
|
2100
2121
|
* looks up \`event.cron\` here and dispatches every job in the list.
|
|
2101
2122
|
*/
|
|
2102
2123
|
export const LUNORA_CRONS: Record<string, ReadonlyArray<LunoraCronJob>> = {${s}};
|
|
2103
|
-
`},
|
|
2124
|
+
`},br=e=>{const t=[...e].toSorted((r,a)=>r.name.localeCompare(a.name)).map(r=>{const a=[`name: ${JSON.stringify(r.name)}`,`table: ${JSON.stringify(r.table)}`];return r.field!==void 0&&a.push(`field: ${JSON.stringify(r.field)}`),r.dimensions!==void 0&&a.push(`dimensions: ${JSON.stringify(r.dimensions)}`),r.metric!==void 0&&a.push(`metric: ${JSON.stringify(r.metric)}`),r.metadata!==void 0&&a.push(`metadata: ${JSON.stringify(r.metadata)}`),` { ${a.join(", ")} },`}).join(`
|
|
2104
2125
|
`),n=t.length>0?`
|
|
2105
2126
|
${t}
|
|
2106
2127
|
`:"";return`${k}/**
|
|
@@ -2124,4 +2145,4 @@ export interface LunoraVectorIndex {
|
|
|
2124
2145
|
* \`createWorker({ vectorIntrospector })\` to back the studio's vector browser.
|
|
2125
2146
|
*/
|
|
2126
2147
|
export const LUNORA_VECTOR_INDEXES: ReadonlyArray<LunoraVectorIndex> = [${n}];
|
|
2127
|
-
`},
|
|
2148
|
+
`},yr=e=>{const t=new Set,n=[];for(const r of e)t.has(r.cron)||(t.add(r.cron),n.push(r.cron));return n};export{pr as B,ar as H,gr as J,ur as M,$n as X,cr as _,Ut as a,dr as b,sr as c,rr as d,mr as e,lr as h,hr as j,ir as l,br as n,yr as r,or as s,fr as t,k as w};
|