@lunora/codegen 1.0.0-alpha.92 → 1.0.0-alpha.93
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.mjs +1 -1
- package/dist/packem_shared/AGENTS_FILENAME-Dk-k250h.mjs +1 -0
- package/dist/packem_shared/CONTAINERS_FILENAME-DQpyhY6c.mjs +1 -0
- package/dist/packem_shared/FLAGS_FILENAME-Boqm0YCP.mjs +1 -0
- package/dist/packem_shared/GENERATED_HEADER-CzjybmTV.mjs +1 -0
- package/dist/packem_shared/LUNORA_ERROR_CODES-zfAI2OFs.mjs +1 -0
- package/dist/packem_shared/{MUTATORS_FILENAME-DY3rgWGl.mjs → MUTATORS_FILENAME-Cp_JxLSz.mjs} +1 -1
- package/dist/packem_shared/NOTIFY_FILENAME-DwyJ5I4Q.mjs +1 -0
- package/dist/packem_shared/OPENRPC_VERSION-5uSsJTUF.mjs +3 -0
- package/dist/packem_shared/QUEUES_FILENAME-QpMZsde0.mjs +1 -0
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-Be67eKv7.mjs +9 -0
- package/dist/packem_shared/{SHAPES_FILENAME-BdLj5-mD.mjs → SHAPES_FILENAME-WxXOsYfe.mjs} +1 -1
- package/dist/packem_shared/SchemaSnapshotParseError-BkgxjBPQ.mjs +16 -0
- package/dist/packem_shared/WORKFLOWS_FILENAME-Dz80zqeT.mjs +1 -0
- package/dist/packem_shared/buildOpenApiDocument-C-oA9yKS.mjs +3 -0
- package/dist/packem_shared/discover-ast-7ABwvTVn.mjs +1 -0
- package/dist/packem_shared/discover-queries-i4Vd2si7.mjs +1 -0
- package/dist/packem_shared/discoverAuthApiCalls-XfNbxqlq.mjs +1 -0
- package/dist/packem_shared/discoverCrons-RlATa0_t.mjs +1 -0
- package/dist/packem_shared/discoverFunctions-4TNKUv7P.mjs +1 -0
- package/dist/packem_shared/discoverHttpRoutes-DQivLBqT.mjs +1 -0
- package/dist/packem_shared/discoverInserts-D6szWzrV.mjs +1 -0
- package/dist/packem_shared/discoverMaskProcedures-BBPqLXA5.mjs +1 -0
- package/dist/packem_shared/discoverMigrations-rbjxflR8.mjs +1 -0
- package/dist/packem_shared/discoverNondeterministicCalls-Bxr652Rz.mjs +1 -0
- package/dist/packem_shared/discoverQueries-uFtLDmn_.mjs +1 -0
- package/dist/packem_shared/discoverR2sqlCalls-DMxG6gHr.mjs +1 -0
- package/dist/packem_shared/discoverRlsMetadata-B63ARnKG.mjs +1 -0
- package/dist/packem_shared/discoverSandboxUsage-DBM98vVh.mjs +1 -0
- package/dist/packem_shared/discoverSchema-BNr7PVcZ.mjs +1 -0
- package/dist/packem_shared/discoverStorageRulesMetadata-_40MGqRX.mjs +1 -0
- package/dist/packem_shared/{emit-DMvG162j.mjs → emit-QxfTfRoJ.mjs} +300 -561
- package/dist/packem_shared/{emitApp--dJ6EnFn.mjs → emitApp-Bh5Jv_9U.mjs} +3 -2
- package/dist/packem_shared/formatAdvisories-CQvIhQ04.mjs +2 -0
- package/dist/packem_shared/parse-validator-CusS8QwU.mjs +1 -0
- package/package.json +9 -9
- package/dist/packem_shared/AGENTS_FILENAME-BesaDYkL.mjs +0 -1
- package/dist/packem_shared/CONTAINERS_FILENAME-CFwdyaCI.mjs +0 -1
- package/dist/packem_shared/FLAGS_FILENAME-CHaH6obH.mjs +0 -1
- package/dist/packem_shared/GENERATED_HEADER-CUBdTCVk.mjs +0 -1
- package/dist/packem_shared/LUNORA_ERROR_CODES-Um9hC1gr.mjs +0 -1
- package/dist/packem_shared/NOTIFY_FILENAME-CDvoTY3Y.mjs +0 -1
- package/dist/packem_shared/OPENRPC_VERSION-aq5eyIkd.mjs +0 -3
- package/dist/packem_shared/QUEUES_FILENAME-CSE6i-ld.mjs +0 -1
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-ChA6rpGP.mjs +0 -9
- package/dist/packem_shared/SchemaSnapshotParseError-BJkhTEpi.mjs +0 -16
- package/dist/packem_shared/WORKFLOWS_FILENAME-ClsYRKXp.mjs +0 -1
- package/dist/packem_shared/buildOpenApiDocument-Bw3MChvT.mjs +0 -3
- package/dist/packem_shared/discover-ast-CezKqEhE.mjs +0 -1
- package/dist/packem_shared/discover-queries-BmZeJ--u.mjs +0 -1
- package/dist/packem_shared/discoverAuthApiCalls-BgL6nj03.mjs +0 -1
- package/dist/packem_shared/discoverCrons-WJscxQFl.mjs +0 -1
- package/dist/packem_shared/discoverFunctions-BgGmxEqW.mjs +0 -1
- package/dist/packem_shared/discoverHttpRoutes-eW8RbVOr.mjs +0 -1
- package/dist/packem_shared/discoverInserts-BCz6zpI0.mjs +0 -1
- package/dist/packem_shared/discoverMaskProcedures-DLfQRsQc.mjs +0 -1
- package/dist/packem_shared/discoverMigrations-Cbc4W765.mjs +0 -1
- package/dist/packem_shared/discoverNondeterministicCalls-x9IhWxPP.mjs +0 -1
- package/dist/packem_shared/discoverQueries-Cf0LGoQG.mjs +0 -1
- package/dist/packem_shared/discoverR2sqlCalls--MSfSeDm.mjs +0 -1
- package/dist/packem_shared/discoverRlsMetadata-DTRS0ROc.mjs +0 -1
- package/dist/packem_shared/discoverSandboxUsage-BDyeyuYo.mjs +0 -1
- package/dist/packem_shared/discoverSchema-DSJSX4Ss.mjs +0 -1
- package/dist/packem_shared/discoverStorageRulesMetadata-Cic97L-2.mjs +0 -1
- package/dist/packem_shared/formatAdvisories-BCEfzLT0.mjs +0 -2
- package/dist/packem_shared/parse-validator-CkLxY-Mr.mjs +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{agentComponent as
|
|
1
|
+
import{agentComponent as rt}from"@lunora/agent/component";import{LunoraError as te}from"@lunora/errors";import{serializeSchemaSnapshot as hn,hashSchemaSnapshot as mn}from"./SCHEMA_SNAPSHOT_VERSION-CFhF_hmg.mjs";import{n as R}from"./paths-BmX5O1sG.mjs";const at=[{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 tt}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"}],
|
|
19
|
-
`;case"boolean":return`if (typeof ${
|
|
20
|
-
`;case"date":case"number":case"timestamp":return`if (typeof ${
|
|
21
|
-
`;case"null":return`if (${
|
|
22
|
-
`;default:return`if (typeof ${
|
|
23
|
-
`}},
|
|
24
|
-
`}},
|
|
25
|
-
const ${o} = new Array(${
|
|
26
|
-
for (let ${i} = 0; ${i} < ${
|
|
27
|
-
const ${s} = ${
|
|
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"}],gn=at,fn=new Map(gn.flatMap(e=>e.serverCtxField?[[e.key,e.serverCtxField]]:[])),Pr=at.flatMap(e=>"appMethod"in e?[{appMethod:e.appMethod,key:e.key}]:[]),ot=/^(?:"(?:[^"\\]|\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4}))*"|'[^'\\]*'|-?\d+(?:\.\d+)?|true|false|null)$/u,yn=new Set(["any","bigint","boolean","date","id","null","number","storage","string","timestamp"]),it=e=>e.column!==void 0,bn=(e,n)=>{switch(e){case"bigint":return`if (typeof ${n} !== "bigint") return DEFER;
|
|
19
|
+
`;case"boolean":return`if (typeof ${n} !== "boolean") return DEFER;
|
|
20
|
+
`;case"date":case"number":case"timestamp":return`if (typeof ${n} !== "number" || !Number.isFinite(${n})) return DEFER;
|
|
21
|
+
`;case"null":return`if (${n} !== null) return DEFER;
|
|
22
|
+
`;default:return`if (typeof ${n} !== "string") return DEFER;
|
|
23
|
+
`}},wn=(e,n)=>{const t=e.literalValue?.trim();if(!(t===void 0||!ot.test(t)))return{out:n,pre:`if (${n} !== ${t}) return DEFER;
|
|
24
|
+
`}},We=(e,n,t)=>{if(!it(e)&&!(e.hasRefinement||e.sourceText!==void 0)){if(yn.has(e.kind))return e.kind==="any"?{out:n,pre:""}:{out:n,pre:bn(e.kind,n)};switch(e.kind){case"array":return xn(e,n,t);case"literal":return wn(e,n);case"object":return vn(e,n,t);default:return}}},xn=(e,n,t)=>{const{inner:r}=e;if(!r)return;const a=t.next(),o=`__arr${String(a)}`,i=`__i${String(a)}`,s=`__e${String(a)}`,d=We(r,s,t);if(!d)return;const u=`if (!Array.isArray(${n})) return DEFER;
|
|
25
|
+
const ${o} = new Array(${n}.length);
|
|
26
|
+
for (let ${i} = 0; ${i} < ${n}.length; ${i}++) {
|
|
27
|
+
const ${s} = ${n}[${i}];
|
|
28
28
|
${d.pre}${o}[${i}] = ${d.out};
|
|
29
29
|
}
|
|
30
|
-
`;return{out:o,pre:u}},
|
|
31
|
-
let ${
|
|
32
|
-
if (${
|
|
33
|
-
${s.pre}${
|
|
30
|
+
`;return{out:o,pre:u}},kn=(e,n,t,r)=>{const a=JSON.stringify(e);if(n.kind==="optional"){if(n.hasRefinement||n.sourceText!==void 0||it(n))return;const{inner:i}=n;if(!i)return;const s=We(i,t,r);if(!s)return;const d=r.next(),u=`__has${String(d)}`,h=`__val${String(d)}`,g=`let ${u} = false;
|
|
31
|
+
let ${h};
|
|
32
|
+
if (${t} !== undefined) {
|
|
33
|
+
${s.pre}${h} = ${s.out};
|
|
34
34
|
${u} = true;
|
|
35
35
|
}
|
|
36
|
-
`;return{entry:`...(${u} ? { ${a}: ${
|
|
36
|
+
`;return{entry:`...(${u} ? { ${a}: ${h} } : {})`,pre:g}}const o=We(n,t,r);if(o)return{entry:`${a}: ${o.out}`,pre:o.pre}},st=(e,n,t)=>{let r="";const a=[];for(const o of Object.keys(e)){const i=e[o];if(!i)return;const s=kn(o,i,n(o),t);if(!s)return;r+=s.pre,a.push(s.entry)}return{entries:a.join(", "),pre:r}},vn=(e,n,t)=>{const r=e.shape??{},a=st(r,d=>`${n}[${JSON.stringify(d)}]`,t);if(!a)return;const o=t.next(),i=`__obj${String(o)}`,s=`if (typeof ${n} !== "object" || ${n} === null || Array.isArray(${n})) return DEFER;
|
|
37
37
|
${a.pre}const ${i} = { ${a.entries} };
|
|
38
|
-
`;return{out:i,pre:s}}
|
|
38
|
+
`;return{out:i,pre:s}},$n=e=>{let n=0;const t=st(e,r=>`source[${JSON.stringify(r)}]`,{next:()=>(n+=1,n)});if(t)return`(source) => {
|
|
39
39
|
if (typeof source !== "object" || source === null || Array.isArray(source)) return DEFER;
|
|
40
|
-
${
|
|
40
|
+
${t.pre}return { ${t.entries} };
|
|
41
41
|
}`},S=`// GENERATED by @lunora/codegen — do not edit.
|
|
42
42
|
// Run \`lunora codegen\` to regenerate.
|
|
43
43
|
|
|
44
|
-
`,
|
|
45
|
-
`),n
|
|
46
|
-
${
|
|
44
|
+
`,ne=(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"},lt=/^[A-Za-z_$][\w$]*$/u,Sn=/^[\w./-]+$/u,m=(e,n)=>{if(!lt.test(e))throw new te("INTERNAL",`@lunora/codegen: ${n} is not a valid JS identifier: ${JSON.stringify(e)}`)},qe=e=>e.charAt(0).toUpperCase()+e.slice(1),_=e=>lt.test(e)?e:JSON.stringify(e),Rn={any:"unknown",bigint:"bigint",boolean:"boolean",bytes:"ArrayBuffer",date:"number",geoPoint:"{ lat: number; lng: number }",null:"null",number:"number",storage:"string",string:"string",timestamp:"number"},Nn=e=>{if(e===void 0)return"unknown";if(!ot.test(e))throw new te("INTERNAL",`@lunora/codegen: v.literal() argument is not a parseable string/number/boolean/null literal: ${JSON.stringify(e)}`);return e},N=e=>{const n=Rn[e.kind];if(n!==void 0)return n;switch(e.kind){case"array":return`Array<${e.inner?N(e.inner):"unknown"}>`;case"from":return e.tsType??"unknown";case"id":{const t=e.tableName??"_unknown_";return m(t,"v.id() table name"),`Id<"${t}">`}case"literal":return Nn(e.literalValue);case"object":return e.shape?`{ ${Object.entries(e.shape).map(([t,r])=>dt(t,r)).join("; ")} }`:"Record<string, unknown>";case"optional":return`${e.inner?N(e.inner):"unknown"} | undefined`;case"record":{const t=e.keyType?N(e.keyType):"string",r=e.valueType?N(e.valueType):"unknown";return`Record<${t}, ${r}>`}case"union":return e.members&&e.members.length>0?e.members.map(t=>N(t)).join(" | "):"never";default:return"unknown"}},dt=(e,n)=>{const t=_(e);if(n.kind==="optional"){const r=n.inner?N(n.inner):"unknown";return`${t}?: ${r}`}return`${t}: ${N(n)}`},we=e=>{const n=Object.entries(e);return n.length===0?"{}":`{ ${n.map(([t,r])=>dt(t,r)).join("; ")} }`},ct=e=>e.kind==="optional"||!!e.column?.hasDefault,re=e=>e.kind==="optional"&&e.inner?e.inner:e,An=e=>{m(e.name,"table name");const n=Object.entries(e.shape).map(([r,a])=>{const o=re(a),i=N(o),s=_(r);return ct(a)?` ${s}?: ${i};`:` ${s}: ${i};`}).join(`
|
|
45
|
+
`),t=n?`
|
|
46
|
+
${n}
|
|
47
47
|
`:"";return`export interface Insert_${e.name} {
|
|
48
48
|
_id?: Id<"${e.name}">;
|
|
49
|
-
_creationTime?: number;${
|
|
49
|
+
_creationTime?: number;${t}}`},Ue="schema",Er=e=>{for(const c of e.tables)m(c.name,"table name");const n=e.tables.map(c=>`"${c.name}"`).join(" | ")||"never",t=e.tables.filter(c=>c.extensionKey===void 0).map(c=>`"${c.name}"`).join(" | ")||"never",r=e.tables.map(c=>{const l=Object.entries(c.shape).map(([x,k])=>{const v=_(x);if(k.kind==="optional"){const L=k.inner?N(k.inner):"unknown";return` ${v}?: ${L};`}return` ${v}: ${N(k)};`}).join(`
|
|
50
50
|
`),f=l?`
|
|
51
51
|
${l}
|
|
52
52
|
`:"";return`export interface Doc_${c.name} {
|
|
@@ -58,14 +58,14 @@ ${l}
|
|
|
58
58
|
`),i=e.tables.map(c=>{const l=c.searchIndexes.map(f=>JSON.stringify(f.name)).join(" | ");return` ${c.name}: ${l||"never"};`}).join(`
|
|
59
59
|
`),s=e.tables.map(c=>{const l=c.rankIndexes.map(f=>JSON.stringify(f.name)).join(" | ");return` ${c.name}: ${l||"never"};`}).join(`
|
|
60
60
|
`),d=e.tables.map(c=>{const l=c.shardMode==="global"?"":(c.geoIndexes??[]).map(f=>JSON.stringify(f.name)).join(" | ");return` ${c.name}: ${l||"never"};`}).join(`
|
|
61
|
-
`),u=e.vectorIndexes.map(c=>JSON.stringify(c.name)).join(" | ")||"never",
|
|
61
|
+
`),u=e.vectorIndexes.map(c=>JSON.stringify(c.name)).join(" | ")||"never",h=e.tables.map(c=>An(c)).join(`
|
|
62
62
|
|
|
63
63
|
`),g=e.tables.map(c=>` ${c.name}: Insert_${c.name};`).join(`
|
|
64
|
-
`),
|
|
64
|
+
`),y=e.tables.map(c=>{const l=c.relations.map(f=>(m(f.table,"relation target table"),` ${_(f.name)}: ${f.kind==="one"?"OneRelation":"ManyRelation"}<"${f.table}">;`)).join(`
|
|
65
65
|
`);return l?` ${c.name}: {
|
|
66
66
|
${l}
|
|
67
67
|
};`:` ${c.name}: {};`}).join(`
|
|
68
|
-
`);return D(`${S}export type TableName = ${
|
|
68
|
+
`);return D(`${S}export type TableName = ${n};
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
71
|
* The tables **this app declared** — every {@link TableName} except those an add-on
|
|
@@ -82,7 +82,7 @@ ${l}
|
|
|
82
82
|
* const EXPORTED: readonly AppTableName[] = ["nodes", "tagColors"];
|
|
83
83
|
* \`\`\`
|
|
84
84
|
*/
|
|
85
|
-
export type AppTableName = ${
|
|
85
|
+
export type AppTableName = ${t};
|
|
86
86
|
|
|
87
87
|
export type Id<TName extends string> = string & { readonly __table: TName };
|
|
88
88
|
|
|
@@ -128,7 +128,7 @@ export type GeoIndexName<T extends keyof DataModel> = GeoIndexNamesByTable[T];
|
|
|
128
128
|
/** Union of declared vector index names. \`never\` when none are declared. */
|
|
129
129
|
export type VectorIndexName = ${u};
|
|
130
130
|
|
|
131
|
-
${
|
|
131
|
+
${h}
|
|
132
132
|
|
|
133
133
|
/** Per-table insert shape, accepted by \`ctx.db.<table>.insert(...)\`. */
|
|
134
134
|
export interface InsertModel {
|
|
@@ -154,14 +154,14 @@ export interface ManyRelation<Target extends keyof DataModel> {
|
|
|
154
154
|
|
|
155
155
|
/** Per-table relation map keyed by accessor name. \`{}\` for tables with none. */
|
|
156
156
|
export interface Relations {
|
|
157
|
-
${
|
|
157
|
+
${y}
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
-
`,
|
|
161
|
-
`);return` ${
|
|
162
|
-
${
|
|
163
|
-
};`};return
|
|
164
|
-
`)},
|
|
160
|
+
`,Ue)},Tn=/import\("(?<spec>(?:\.\.?\/)*_generated\/[^"]+)"\)/gu,ut=/^(?:\.\.?\/)*_generated\//u,pt=/\.[A-Za-z]\w*$/u,On=e=>e.replaceAll(Tn,(n,t)=>{const r=t.replace(ut,"./");return`import("${pt.test(r)?r:`${r}.js`}")`}),Ln=/import\("(?<spec>\.\.?\/[^"]+)"\)/gu,Cn=/^(?:\.\.?\/)+/u,In=e=>{const n=[];for(const t of e.split("/"))if(!(t===""||t===".")){if(t===".."&&n.length>0&&n.at(-1)!==".."){n.pop();continue}n.push(t)}return n.join("/")},_n=(e,n)=>e.replaceAll(Ln,(t,r)=>{if(ut.test(r.replace(Cn,"")))return t;const a=n.includes("/")?n.slice(0,n.lastIndexOf("/")):"",o=`../${In(`${a}/${r}`)}`;return`import("${pt.test(o)?o:`${o}.js`}")`}),D=(e,n)=>On(_n(e,n)),Dn=["client","do","errors","flags","observability","platform","ratelimit","runtime","server","values"],Pn=new RegExp(String.raw`import\("@lunora/(?<pkg>${Dn.join("|")})(?<subpath>/[^"]*)?"\)`,"gu"),En={flags:new Set(["/web"]),platform:new Set},ht=(e,n)=>n?e.replaceAll(Pn,(t,r,a)=>{const o=En[r];return a&&o&&!o.has(a)?t:`import("lunorash/${r}${a??""}")`}):e,Ke=e=>["Doc","Id"].filter(n=>new RegExp(String.raw`\b${n}<`,"u").test(e)),Mn=e=>e.output===void 0||e.output.kind==="any"?e.returnType:N(e.output),Qe=e=>{const n=new Map;for(const t of e){const r=n.get(t.filePath)??[];r.push(t),n.set(t.filePath,r)}return[...n.entries()].toSorted(([t],[r])=>t.localeCompare(r))},tt=e=>{const n=([t,r])=>{const a=r.toSorted((o,i)=>o.exportName.localeCompare(i.exportName)).map(o=>{const i=D(we(o.args),o.filePath),s=D(Mn(o),o.filePath);return` ${o.exportName}: FunctionReference<"${o.kind}", ${i}, ${s}>;`}).join(`
|
|
161
|
+
`);return` ${_(R(t))}: {
|
|
162
|
+
${a}
|
|
163
|
+
};`};return Qe(e).map(t=>n(t)).join(`
|
|
164
|
+
`)},Fn=(e,n)=>{if(e.length===0&&n.length===0)return{block:"",importLine:""};const t=[];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+=`
|
|
165
165
|
/** A typed reference to a durable workflow, addressable for \`cronJobs()\` targets. Mirrors \`@lunora/scheduler\`'s \`WorkflowReference\` structurally. */
|
|
166
166
|
export interface WorkflowReference<Params = Record<string, unknown>> {
|
|
167
167
|
readonly isLunoraWorkflow: true;
|
|
@@ -180,8 +180,8 @@ ${o}
|
|
|
180
180
|
export const workflows: WorkflowsRef = {
|
|
181
181
|
${i}
|
|
182
182
|
};
|
|
183
|
-
`,
|
|
184
|
-
`)}if(
|
|
183
|
+
`,t.push(`import type * as lunoraWorkflowDefinitions from "../workflows.js";
|
|
184
|
+
`)}if(n.length>0){const a=[...n].toSorted((s,d)=>s.exportName.localeCompare(d.exportName)),o=a.map(s=>` ${s.exportName}: WorkflowReference<AgentRunInput>;`).join(`
|
|
185
185
|
`),i=a.map(s=>` ${s.exportName}: { isLunoraWorkflow: true, binding: ${JSON.stringify(s.bindingName)}, name: ${JSON.stringify(s.name)} },`).join(`
|
|
186
186
|
`);r+=`
|
|
187
187
|
/** 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 })\`). */
|
|
@@ -192,8 +192,8 @@ ${o}
|
|
|
192
192
|
export const agents: AgentsRef = {
|
|
193
193
|
${i}
|
|
194
194
|
};
|
|
195
|
-
`,
|
|
196
|
-
`)}return{block:r,importLine:
|
|
195
|
+
`,t.push(`import type { AgentRunInput } from "@lunora/agent";
|
|
196
|
+
`)}return{block:r,importLine:t.join("")}},Bn=()=>Object.keys(rt().functions).toSorted((e,n)=>e.localeCompare(n)),mt=e=>new Set(e.filter(n=>R(n.filePath)==="agents").map(n=>n.exportName)),jn=()=>new Set(Object.entries(rt().functions).filter(([,e])=>e.visibility==="internal").map(([e])=>e)),qn=(e,n)=>{const t={importLine:"",lines:"",prelude:""};if(e.length===0)return t;const r=mt(n),a=jn(),o=n.find(s=>R(s.filePath)==="agents"&&a.has(s.exportName));if(o)throw new te("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 i=Bn().filter(s=>!r.has(s));return i.length===0?t:{importLine:`import { agentComponent } from "@lunora/agent/component";
|
|
197
197
|
`,lines:i.map(s=>` "agents:${s}": lunoraAgentRuntimeFunctions.${s} as unknown as RegisteredLunoraFunction,`).join(`
|
|
198
198
|
`),prelude:`
|
|
199
199
|
/**
|
|
@@ -202,33 +202,33 @@ ${i}
|
|
|
202
202
|
* subscribe to the public queries (\`agents:agentMessages\` is the live thread view).
|
|
203
203
|
*/
|
|
204
204
|
const lunoraAgentRuntimeFunctions = agentComponent().functions;
|
|
205
|
-
`}},
|
|
206
|
-
`,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"}},
|
|
207
|
-
`);return` ${
|
|
208
|
-
${
|
|
205
|
+
`}},Wn=(e,n)=>{if(!e)return{importLine:"",lines:"",prelude:""};const t=n.find(r=>R(r.filePath)==="sandbox"&&r.exportName==="invoke");if(t)throw new te("INTERNAL",`@lunora/codegen: "sandbox:invoke" is reserved for the batteries-included sandbox tool dispatcher (browserTool/containerTool) — rename the "invoke" export in ${t.filePath}`);return{importLine:`import { sandboxComponent } from "@lunora/agent/component";
|
|
206
|
+
`,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"}},Un=(e,n)=>{if(e.length===0)return[];const t=mt(n),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=>!t.has(a.exportName))},Kn=(e,n)=>{if(e.length===0)return[];const t=new Set(n.filter(r=>R(r.filePath)==="mutators").map(r=>r.exportName));return e.filter(r=>!t.has(r.exportName)).map(r=>({args:r.args,exportName:r.exportName,filePath:r.filePath,kind:"mutation",returnType:r.returnType}))},Qn=e=>{const n=e.filter(o=>o.stream);if(n.length===0)return{block:"",body:""};const t=Qe(n),r=t.map(([o,i])=>{const s=i.map(d=>{const u=D(d.chunkType??"unknown",d.filePath),h=D(we(d.searchParams),d.filePath),g=D(we(d.params),d.filePath);return` ${_(d.exportName)}: HttpStreamRef<${u}, ${h}, ${g}>;`}).join(`
|
|
207
|
+
`);return` ${_(R(o))}: {
|
|
208
|
+
${s}
|
|
209
209
|
};`}).join(`
|
|
210
|
-
`),
|
|
211
|
-
`);return` ${
|
|
212
|
-
${
|
|
210
|
+
`),a=t.map(([o,i])=>{const s=i.map(d=>` ${_(d.exportName)}: { method: ${JSON.stringify(d.method)}, path: ${JSON.stringify(d.path)} },`).join(`
|
|
211
|
+
`);return` ${_(R(o))}: {
|
|
212
|
+
${s}
|
|
213
213
|
},`}).join(`
|
|
214
214
|
`);return{block:`
|
|
215
215
|
/** This project's HTTP-SSE stream routes (\`httpRoute.<verb>(path).stream()\`), addressable as typed references for \`client.httpStream\` / \`useHttpStream\`. */
|
|
216
216
|
export interface HttpStreamsRef {
|
|
217
|
-
${
|
|
217
|
+
${r}
|
|
218
218
|
}
|
|
219
219
|
|
|
220
220
|
export const httpStreams: HttpStreamsRef = {
|
|
221
|
-
${
|
|
221
|
+
${a}
|
|
222
222
|
};
|
|
223
|
-
`,body:
|
|
223
|
+
`,body:r}},Mr=e=>{const{agents:n=[],functions:t,httpRoutes:r=[],mutators:a=[],useUmbrella:o=!1,workflows:i=[]}=e,s=ne(o),d=[...t.filter($=>$.visibility!=="internal"),...Un(n,t),...Kn(a,t)],u=t.filter($=>$.visibility==="internal"),h=tt(d),g=tt(u),y=Qn(r),c=`${h}
|
|
224
224
|
${g}
|
|
225
|
-
${
|
|
225
|
+
${y.body}`,l=Ke(c),f=l.length>0?`
|
|
226
226
|
import type { ${l.join(", ")} } from "./dataModel.js";
|
|
227
|
-
`:"",x=
|
|
228
|
-
${
|
|
227
|
+
`:"",x=h?`
|
|
228
|
+
${h}
|
|
229
229
|
`:"",k=g?`
|
|
230
230
|
${g}
|
|
231
|
-
`:"",v=
|
|
231
|
+
`:"",v=Fn(i,n),L=`export interface ApiTypes {${x}}
|
|
232
232
|
|
|
233
233
|
export const api = anyApi as unknown as ApiTypes;
|
|
234
234
|
|
|
@@ -236,10 +236,10 @@ export const api = anyApi as unknown as ApiTypes;
|
|
|
236
236
|
export interface InternalApiTypes {${k}}
|
|
237
237
|
|
|
238
238
|
export const internal = anyApi as unknown as InternalApiTypes;
|
|
239
|
-
${v.block}${
|
|
240
|
-
`:"";return
|
|
241
|
-
${
|
|
242
|
-
${
|
|
239
|
+
${v.block}${y.block}`,M=[...L.includes("FunctionReference<")?["FunctionReference"]:[],...y.block===""?[]:["HttpStreamRef"]],C=M.length>0?`import type { ${M.join(", ")} } from "${s.client}";
|
|
240
|
+
`:"";return ht(`${S}import { anyApi } from "${s.client}";
|
|
241
|
+
${C}${v.importLine}${f}
|
|
242
|
+
${L}`,o)},Fr=e=>e?`${S}import { createSeedClient as createSeedClientBase } from "@lunora/seed";
|
|
243
243
|
import type { SeedClient, SeedClientOptions } from "@lunora/seed";
|
|
244
244
|
|
|
245
245
|
import schema from "../schema.js";
|
|
@@ -256,9 +256,9 @@ import type { InsertModel } from "./dataModel.js";
|
|
|
256
256
|
* const { posts } = await seed.posts((x) => x([10, 20]));
|
|
257
257
|
*/
|
|
258
258
|
export const createSeedClient = (options?: SeedClientOptions): SeedClient<InsertModel> => createSeedClientBase<InsertModel>(schema, options);
|
|
259
|
-
`:"",
|
|
260
|
-
export interface ${
|
|
261
|
-
${
|
|
259
|
+
`:"",Br=(e,n,t=!1)=>{if(e.length===0||!n)return"";const r=ne(t),a=d=>d.table===void 0?"Row":`Doc<${JSON.stringify(d.table)}> & Row`,o=e.map(d=>{m(d.exportName,"shape export name");const u=a(d),h=D(we(d.args),d.filePath),g=Object.keys(d.args).length>0,y=g?` args: ${h};`:` args?: ${h};`,c=g?`(args: ${h}) => void`:`(args?: ${h}) => void`,l=`${d.exportName}CollectionOptions`;return`/** Options for the \`${d.exportName}\` shape binding. */
|
|
260
|
+
export interface ${qe(l)} {
|
|
261
|
+
${y}
|
|
262
262
|
/**
|
|
263
263
|
* Share the optimistic-overlay gate with other collections + mutators on this
|
|
264
264
|
* shard. Defaults to the shared per-shard registry, which is almost always what
|
|
@@ -282,7 +282,7 @@ ${b}
|
|
|
282
282
|
* \`createCollection\`, plus the \`checkpoints\` registry to hand \`bindMutators\` and
|
|
283
283
|
* \`scope\` to re-point the subscription.
|
|
284
284
|
*/
|
|
285
|
-
export const ${d.exportName}CollectionOptions = (options: ${
|
|
285
|
+
export const ${d.exportName}CollectionOptions = (options: ${qe(l)}): LunoraCollectionOptions<${u}> =>
|
|
286
286
|
lunoraCollectionOptions<${u}>({
|
|
287
287
|
client: options.client,
|
|
288
288
|
...(options.checkpoints === undefined ? {} : { checkpoints: options.checkpoints }),
|
|
@@ -295,14 +295,14 @@ export const ${d.exportName}CollectionOptions = (options: ${Fe(l)}): LunoraColle
|
|
|
295
295
|
|
|
296
296
|
/** Live collection for the \`${d.exportName}\` shape, with its sync controls. */
|
|
297
297
|
export const ${d.exportName}Collection = (
|
|
298
|
-
options: ${
|
|
298
|
+
options: ${qe(l)},
|
|
299
299
|
): { checkpoints: CheckpointRegistry; collection: Collection<${u}, string>; scope: ${c} } => {
|
|
300
300
|
const { checkpoints, config, scope } = ${d.exportName}CollectionOptions(options);
|
|
301
301
|
|
|
302
302
|
return { checkpoints, collection: createCollection(config), scope };
|
|
303
303
|
};`}).join(`
|
|
304
304
|
|
|
305
|
-
`),i=
|
|
305
|
+
`),i=Ke(o),s=i.length>0?`import type { ${i.join(", ")} } from "./dataModel.js";
|
|
306
306
|
`:"";return`${S}import type { LunoraClient, SubscriptionError } from "${r.client}";
|
|
307
307
|
import { lunoraCollectionOptions } from "@lunora/db/collections";
|
|
308
308
|
import type { CheckpointRegistry, LunoraCollectionOptions, Row } from "@lunora/db";
|
|
@@ -310,7 +310,7 @@ import type { Collection } from "@tanstack/db";
|
|
|
310
310
|
import { createCollection } from "@tanstack/db";
|
|
311
311
|
${s}
|
|
312
312
|
${o}
|
|
313
|
-
`},
|
|
313
|
+
`},Vn=(e,n)=>`lunora_${R(e)}_${String(n)}`,Hn=`const callRegistered = async <R>(context: CallerCtx, functionPath: string, args: Record<string, unknown> | undefined): Promise<R> => {
|
|
314
314
|
const registered = LUNORA_FUNCTIONS[functionPath];
|
|
315
315
|
|
|
316
316
|
if (!registered) {
|
|
@@ -318,45 +318,45 @@ ${o}
|
|
|
318
318
|
}
|
|
319
319
|
|
|
320
320
|
return (await registered.handler(context, args ?? {})) as R;
|
|
321
|
-
};`,
|
|
321
|
+
};`,Jn=(e,n,t=[],r=[])=>{const a=new Map,o=l=>{a.has(l)||a.set(l,Vn(l,a.size))};for(const l of e)o(l.filePath);for(const l of n)o(l.filePath);for(const l of t)o(l.filePath);for(const l of r)o(l.filePath);const i=[...a.entries()].map(([l,f])=>{if(!Sn.test(l))throw new te("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(l)}`);return`import * as ${f} from "../${l}.js";`}).join(`
|
|
322
322
|
`),s=e.map(l=>` "${R(l.filePath)}:${l.exportName}": ${a.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredLunoraFunction,`).join(`
|
|
323
|
-
`),d=
|
|
324
|
-
`),u=
|
|
325
|
-
`),
|
|
326
|
-
`),g=
|
|
327
|
-
`),c=e.map(l=>{if(l.lifecycle||Object.keys(l.args).length===0)return;const f
|
|
328
|
-
`);return{dispatchBody:
|
|
329
|
-
${
|
|
323
|
+
`),d=n.map(l=>` ${JSON.stringify(l.id)}: ${a.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredDataMigration,`).join(`
|
|
324
|
+
`),u=t.map(l=>` "${R(l.filePath)}:${l.exportName}": ${a.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredLunoraFunction,`).join(`
|
|
325
|
+
`),h=r.map(l=>` "${l.exportName}": ${a.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredShape,`).join(`
|
|
326
|
+
`),g=t.map(l=>`${R(l.filePath)}:${l.exportName}`),y=[s,u].filter(l=>l.length>0).join(`
|
|
327
|
+
`),c=e.map(l=>{if(l.lifecycle||Object.keys(l.args).length===0)return;const f=$n(l.args);return f===void 0?void 0:`installCompiledValidatorMap(${a.get(l.filePath)??""}.${l.exportName}.args, ${f});`}).filter(l=>l!==void 0).join(`
|
|
328
|
+
`);return{dispatchBody:y.length>0?`
|
|
329
|
+
${y}
|
|
330
330
|
`:"",importBlock:i.length>0?`${i}
|
|
331
331
|
|
|
332
332
|
`:"",installBlock:c,migrationBody:d.length>0?`
|
|
333
333
|
${d}
|
|
334
|
-
`:"",mutatorPaths:g,shapeBody:
|
|
335
|
-
${
|
|
336
|
-
`:""}},
|
|
337
|
-
`);return` ${
|
|
338
|
-
${
|
|
334
|
+
`:"",mutatorPaths:g,shapeBody:h.length>0?`
|
|
335
|
+
${h}
|
|
336
|
+
`:""}},zn=e=>{const n=Qe(e),t=n.map(([r,a])=>{const o=a.map(i=>{const s=D(we(i.args),i.filePath),d=s==="{}"?"?":"",u=D(i.returnType,i.filePath);return i.kind==="stream"?` ${i.exportName}: (args${d}: ${s}) => Promise<AsyncIterable<${u}>>;`:` ${i.exportName}: (args${d}: ${s}) => Promise<${u}>;`}).join(`
|
|
337
|
+
`);return` ${_(R(r))}: {
|
|
338
|
+
${o}
|
|
339
339
|
};`}).join(`
|
|
340
|
-
`);return{implementation:n.map(([a
|
|
341
|
-
`);return` ${
|
|
342
|
-
${
|
|
340
|
+
`);return{implementation:n.map(([r,a])=>{const o=R(r),i=a.map(s=>` ${s.exportName}: (args) => callRegistered(context, "${o}:${s.exportName}", args),`).join(`
|
|
341
|
+
`);return` ${_(o)}: {
|
|
342
|
+
${i}
|
|
343
343
|
},`}).join(`
|
|
344
|
-
`),types:
|
|
345
|
-
`:"",
|
|
346
|
-
readonly ai: LunoraAi;`:"",
|
|
347
|
-
`:"",
|
|
348
|
-
readonly payments: LunoraPayment;`:"",
|
|
349
|
-
`:"",
|
|
350
|
-
readonly x402: X402Pay;`:"",T=
|
|
351
|
-
`:"",
|
|
352
|
-
readonly containers: {${
|
|
353
|
-
readonly ${
|
|
354
|
-
};`:"",O=[...a?[" /** Workers AI binding (the conventional `env.AI`), narrowing `ctx.ai`. */\n readonly AI?: unknown;"]:[],...
|
|
355
|
-
readonly ${
|
|
356
|
-
readonly ${
|
|
357
|
-
readonly ${
|
|
358
|
-
readonly ${
|
|
359
|
-
`),
|
|
344
|
+
`),types:t}},Gn=(e,n=[])=>{const t=new Set;for(const r of e.tables)for(const a of Object.values(r.shape)){const o=re(a);o.kind==="storage"&&typeof o.bucket=="string"&&o.bucket!==""&&t.add(o.bucket)}for(const r of n)r!==""&&r!=="default"&&t.add(r);return["default",...[...t].toSorted((r,a)=>r.localeCompare(a))]},jr=({agents:e=[],containers:n=[],env:t,hasAccessFacade:r=!1,hasAi:a=!1,hasAnalytics:o=!1,hasBrowser:i=!1,hasFlags:s=!1,hasHyperdrive:d=!1,hasImages:u=!1,hasKv:h=!1,hasNotify:g=!1,hasPayments:y=!1,hasPipelines:c=!1,hasR2sql:l=!1,hasX402:f=!1,identity:x,queues:k=[],schema:v,storageRuleBuckets:L=[],useUmbrella:M=!1,workflows:C=[]}={})=>{const $=ne(M),w=Gn(v??{tables:[]},L).map(p=>JSON.stringify(p)).join(" | "),F=a?`import type { LunoraAi } from "@lunora/ai";
|
|
345
|
+
`:"",ae=a?`
|
|
346
|
+
readonly ai: LunoraAi;`:"",B=y?`import type { LunoraPayment } from "@lunora/payment";
|
|
347
|
+
`:"",oe=y?`
|
|
348
|
+
readonly payments: LunoraPayment;`:"",ie=f?`import type { X402Pay } from "@lunora/x402/pay";
|
|
349
|
+
`:"",W=f?`
|
|
350
|
+
readonly x402: X402Pay;`:"",T=n.length>0?`import type { ContainerAccessor } from "@lunora/container";
|
|
351
|
+
`:"",Y=n.length>0?`
|
|
352
|
+
readonly containers: {${n.map(p=>`
|
|
353
|
+
readonly ${p.exportName}: ContainerAccessor;`).join("")}
|
|
354
|
+
};`:"",O=[...a?[" /** Workers AI binding (the conventional `env.AI`), narrowing `ctx.ai`. */\n readonly AI?: unknown;"]:[],...n.map(p=>(m(p.bindingName,`container binding "${p.bindingName}"`),` /** Durable Object namespace for the \`${p.exportName}\` container. */
|
|
355
|
+
readonly ${p.bindingName}?: unknown;`)),...C.map(p=>(m(p.bindingName,`workflow binding "${p.bindingName}"`),` /** Workflow binding for the \`${p.exportName}\` workflow. */
|
|
356
|
+
readonly ${p.bindingName}?: unknown;`)),...k.map(p=>(m(p.bindingName,`queue binding "${p.bindingName}"`),` /** Queue producer binding for the \`${p.exportName}\` queue. */
|
|
357
|
+
readonly ${p.bindingName}?: unknown;`)),...e.map(p=>(m(p.bindingName,`agent binding "${p.bindingName}"`),` /** Workflow binding for the \`${p.exportName}\` agent. */
|
|
358
|
+
readonly ${p.bindingName}?: unknown;`))].join(`
|
|
359
|
+
`),I=`
|
|
360
360
|
|
|
361
361
|
/**
|
|
362
362
|
* This project's Cloudflare bindings, as far as codegen can discover them from
|
|
@@ -374,21 +374,21 @@ ${O}`:""}
|
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
/** Alias for {@link CloudflareBindings} — the typed shape of \`env\`. */
|
|
377
|
-
export type Env = CloudflareBindings;`,
|
|
378
|
-
readonly vectors: VectorSearch<VectorIndexName>;`:"",
|
|
379
|
-
readonly vectors: VectorSearchReader<VectorIndexName>;`:"",
|
|
377
|
+
export type Env = CloudflareBindings;`,j=(p,Fe)=>Fe?fn.get(p)?.field??"":"",se=j("kv",h),le=j("analytics",o),Re=j("hyperdrive",d),Ne=j("browser",i),Ae=j("images",u),de=j("pipelines",c),V=j("r2sql",l),E=(v?.vectorIndexes.length??0)>0,H=E?' | "vectors"':"",Z=E?`
|
|
378
|
+
readonly vectors: VectorSearch<VectorIndexName>;`:"",ce=E?`
|
|
379
|
+
readonly vectors: VectorSearchReader<VectorIndexName>;`:"",J=E?`import type { VectorSearch, VectorSearchReader } from "${$.server}";
|
|
380
380
|
import type { VectorIndexName } from "./dataModel.js";
|
|
381
|
-
`:"",
|
|
381
|
+
`:"",U=r?`
|
|
382
382
|
/** Verified Cloudflare Access identity — a synchronous facade over the resolved claims (email / groups / hasGroup / claims). Anonymous when no Access token is present. */
|
|
383
|
-
readonly access: import("@lunora/cloudflare-access/context").AccessFacade;`:"",
|
|
383
|
+
readonly access: import("@lunora/cloudflare-access/context").AccessFacade;`:"",K=s?`
|
|
384
384
|
/** Feature-flag evaluation (OpenFeature). Reads are memoized per request; evaluations never throw — a provider error resolves to the supplied default. */
|
|
385
|
-
readonly flags: import("${$.flags}").LunoraFlags;`:"",
|
|
385
|
+
readonly flags: import("${$.flags}").LunoraFlags;`:"",Q=g?`
|
|
386
386
|
/** Multi-channel notifications (@lunora/notify): send / chat / inApp / webhook plus the push device sub-facade. Sends are external I/O — confine them to action handlers. */
|
|
387
387
|
readonly notify: import("@lunora/notify").LunoraNotify;
|
|
388
388
|
/** Device push sub-facade — the same object as ctx.notify.push (register / send / broadcast). Sends belong in action handlers. */
|
|
389
|
-
readonly push: import("@lunora/notify").LunoraPush;`:"",
|
|
389
|
+
readonly push: import("@lunora/notify").LunoraPush;`:"",q=C.length>0,ee=q?`import type { WorkflowHandle } from "@lunora/workflow";
|
|
390
390
|
import type * as lunoraWorkflowDefinitions from "../workflows.js";
|
|
391
|
-
`:"",
|
|
391
|
+
`:"",Te=q?`
|
|
392
392
|
|
|
393
393
|
/** Params type carried by a \`defineWorkflow\` definition (its phantom \`__params\`). */
|
|
394
394
|
type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params }
|
|
@@ -399,43 +399,43 @@ type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params
|
|
|
399
399
|
|
|
400
400
|
/** This project's declared workflows, addressable from \`ctx.workflows\` by their \`lunora/workflows.ts\` export name. */
|
|
401
401
|
export interface LunoraWorkflows {
|
|
402
|
-
${
|
|
402
|
+
${C.map(p=>` get(name: ${JSON.stringify(p.exportName)}): WorkflowHandle<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${p.exportName}>>;`).join(`
|
|
403
403
|
`)}
|
|
404
|
-
}`:"",
|
|
405
|
-
readonly workflows: LunoraWorkflows;`:"",
|
|
404
|
+
}`:"",xe=q?' | "workflows"':"",ke=q?`
|
|
405
|
+
readonly workflows: LunoraWorkflows;`:"",ue=k.length>0,Oe=ue?`import type { QueueProducer } from "@lunora/queue";
|
|
406
406
|
import type * as lunoraQueueDefinitions from "../queues.js";
|
|
407
|
-
`:"",
|
|
407
|
+
`:"",Le=ue?`
|
|
408
408
|
|
|
409
409
|
/** Message body type carried by a \`defineQueue\` definition (its phantom \`__lunoraBody\`). */
|
|
410
410
|
type QueueBodyOf<Definition> = Definition extends { __lunoraBody?: infer Body } ? (unknown extends Body ? unknown : NonNullable<Body>) : unknown;
|
|
411
411
|
|
|
412
412
|
/** This project's declared queues, addressable from \`ctx.queues\` by their \`lunora/queues.ts\` export name. */
|
|
413
413
|
export interface LunoraQueues {
|
|
414
|
-
${k.map(
|
|
414
|
+
${k.map(p=>` readonly ${p.exportName}: QueueProducer<QueueBodyOf<typeof lunoraQueueDefinitions.${p.exportName}>>;`).join(`
|
|
415
415
|
`)}
|
|
416
|
-
}`:"",
|
|
417
|
-
readonly queues: LunoraQueues;`:"",
|
|
418
|
-
`:"",
|
|
416
|
+
}`:"",ve=ue?`
|
|
417
|
+
readonly queues: LunoraQueues;`:"",pe=e.length>0,Ce=pe?`import type { AgentHandle } from "@lunora/agent";
|
|
418
|
+
`:"",Ie=pe?`
|
|
419
419
|
|
|
420
420
|
/** This project's declared agents, addressable from \`ctx.agents\` by their \`lunora/agents.ts\` export name. */
|
|
421
421
|
export interface LunoraAgents {
|
|
422
|
-
${e.map(
|
|
422
|
+
${e.map(p=>(m(p.exportName,`agent export "${p.exportName}"`),` readonly ${p.exportName}: AgentHandle;`)).join(`
|
|
423
423
|
`)}
|
|
424
|
-
}`:""
|
|
425
|
-
readonly agents: LunoraAgents;`:"",
|
|
424
|
+
}`:"",$e=pe?`
|
|
425
|
+
readonly agents: LunoraAgents;`:"",_e=x?`import type { InferIdentity } from "${$.server}";
|
|
426
426
|
import type * as lunoraIdentityContract from "../identity.js";
|
|
427
|
-
`:"",
|
|
427
|
+
`:"",De=x?`
|
|
428
428
|
|
|
429
429
|
/** This app's declared identity claim contract (\`defineIdentity\` in \`lunora/identity.ts\`) — the typed shape of \`ctx.auth.getIdentity()\`, the RLS policy \`ctx.auth.identity\`, and the \`authorizeShard\`/\`authorizeFanOut\` identity argument. */
|
|
430
430
|
export type Identity = InferIdentity<typeof lunoraIdentityContract.${x.exportName}>;
|
|
431
431
|
|
|
432
432
|
/** \`ctx.auth\` narrowed so \`getIdentity()\` resolves the declared {@link Identity} contract instead of the untyped claim bag. */
|
|
433
|
-
type NarrowedAuth = Omit<QueryCtxBase["auth"], "getIdentity"> & { getIdentity: () => Promise<Identity | null> };`:"",
|
|
434
|
-
readonly auth: NarrowedAuth;`:"",
|
|
435
|
-
`:"",
|
|
433
|
+
type NarrowedAuth = Omit<QueryCtxBase["auth"], "getIdentity"> & { getIdentity: () => Promise<Identity | null> };`:"",he=x?' | "auth"':"",me=x?`
|
|
434
|
+
readonly auth: NarrowedAuth;`:"",Pe=x?", Identity":"",Ee=t?`import type * as lunoraEnvContract from "../env.js";
|
|
435
|
+
`:"",Me=t?`
|
|
436
436
|
|
|
437
437
|
/** This app's declared env contract (\`defineEnv\` in \`lunora/env.ts\`) — the validated, coercion-aware shape of \`ctx.env\`. */
|
|
438
|
-
export type LunoraEnv = ReturnType<typeof lunoraEnvContract.${
|
|
438
|
+
export type LunoraEnv = ReturnType<typeof lunoraEnvContract.${t.exportName}>;`:"",ge=t?' | "env"':"",fe=t?"\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`${S}import { createPolicyDsl, defineMutator as defineMutatorBase, initLunora, v as vBase } from "${$.server}";
|
|
439
439
|
import type {
|
|
440
440
|
ActionBuilder,
|
|
441
441
|
ActionCtx as ActionCtxBase,
|
|
@@ -491,7 +491,7 @@ export type {
|
|
|
491
491
|
} from "${$.serverDataModel}";
|
|
492
492
|
|
|
493
493
|
import type { DataModel, Doc, GeoIndexNamesByTable, Id as IdOfTable, IndexNamesByTable, Insert, InsertModel, RankIndexNamesByTable, Relations, SearchIndexNamesByTable, TableName } from "./dataModel.js";
|
|
494
|
-
${
|
|
494
|
+
${J}${F}${B}${ie}${T}${ee}${Oe}${Ce}${_e}${Ee}
|
|
495
495
|
export type { AppTableName, DataModel, Doc, Id, TableName } from "./dataModel.js";
|
|
496
496
|
|
|
497
497
|
/**
|
|
@@ -551,7 +551,7 @@ export interface OrmWriter extends OrmReader {
|
|
|
551
551
|
}
|
|
552
552
|
|
|
553
553
|
/** Storage buckets this schema declares (\`v.storage("name")\`), narrowing \`ctx.storage.bucket(name)\`. */
|
|
554
|
-
export type StorageBucketName = ${w};${
|
|
554
|
+
export type StorageBucketName = ${w};${I}${Te}${Le}${Ie}${De}${Me}
|
|
555
555
|
|
|
556
556
|
/**
|
|
557
557
|
* Project-typed contexts. The base contexts from \`@lunora/server\` are
|
|
@@ -614,22 +614,22 @@ type AsIdTable<T extends string> = T extends TableName ? T : string extends T ?
|
|
|
614
614
|
*/
|
|
615
615
|
type TypedAsId = <T extends string>(tableName: AsIdTable<T>, id: string) => IdOfTable<T & TableName>;
|
|
616
616
|
|
|
617
|
-
export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"${H}${
|
|
617
|
+
export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"${H}${he}${ge}> {
|
|
618
618
|
readonly db: Omit<DatabaseReader, "asId" | "query" | "get"> & DatabaseReaderFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
|
|
619
619
|
readonly orm: OrmReader;
|
|
620
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${
|
|
620
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${ce}${U}${se}${K}${Q}${le}${fe}${me}
|
|
621
621
|
}
|
|
622
622
|
|
|
623
|
-
export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${H}${
|
|
623
|
+
export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${H}${xe}${he}${ge}> {
|
|
624
624
|
readonly db: Omit<DatabaseWriter, "asId" | "query" | "get"> & DatabaseWriterFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
|
|
625
625
|
readonly orm: OrmWriter;
|
|
626
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${
|
|
626
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${Z}${U}${se}${K}${Q}${le}${fe}${ke}${ve}${$e}${me}
|
|
627
627
|
}
|
|
628
628
|
|
|
629
|
-
export interface ActionCtx extends Omit<ActionCtxBase, "db" | "storage"${H}${
|
|
629
|
+
export interface ActionCtx extends Omit<ActionCtxBase, "db" | "storage"${H}${xe}${he}${ge}> {
|
|
630
630
|
readonly db: Omit<DatabaseWriter, "asId" | "query" | "get"> & DatabaseWriterFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
|
|
631
631
|
readonly orm: OrmWriter;
|
|
632
|
-
readonly storage: StorageBase<StorageBucketName>;${
|
|
632
|
+
readonly storage: StorageBase<StorageBucketName>;${Z}${U}${ae}${oe}${W}${Y}${se}${K}${Q}${Re}${Ne}${Ae}${le}${de}${V}${fe}${ke}${ve}${$e}${me}
|
|
633
633
|
}
|
|
634
634
|
|
|
635
635
|
/**
|
|
@@ -687,7 +687,7 @@ export const defineMutator = defineMutatorBase as unknown as <Args extends Recor
|
|
|
687
687
|
* Runtime-identical to \`@lunora/server\`'s \`definePolicy\`; only the types narrow,
|
|
688
688
|
* so the \`rls()\` chain discovers a policy authored either way the same.
|
|
689
689
|
*/
|
|
690
|
-
export const definePolicy = createPolicyDsl<DataModel, Relations${
|
|
690
|
+
export const definePolicy = createPolicyDsl<DataModel, Relations${Pe}>();
|
|
691
691
|
|
|
692
692
|
/**
|
|
693
693
|
* The validator builder \`v\`, with \`v.id(...)\` constrained to THIS schema's
|
|
@@ -704,12 +704,12 @@ export const definePolicy = createPolicyDsl<DataModel, Relations${Ie}>();
|
|
|
704
704
|
export const v = vBase as unknown as Omit<typeof vBase, "id"> & {
|
|
705
705
|
id: <T extends TableName>(table: T) => ColumnValidator<IdOfTable<T>, IdOfTable<T>>;
|
|
706
706
|
};
|
|
707
|
-
`},
|
|
708
|
-
`);let
|
|
707
|
+
`},Xn=e=>{const n={connect:[],disconnect:[]};for(const t of e)t.lifecycle&&n[t.lifecycle].push(`${R(t.filePath)}:${t.exportName}`);return n},qr=e=>{const{agents:n=[],functions:t,migrations:r=[],mutators:a=[],shapes:o=[],useUmbrella:i=!1,usesSandbox:s=!1}=e,d=t.length>0,u=ne(i),{dispatchBody:h,importBlock:g,installBlock:y,migrationBody:c,mutatorPaths:l,shapeBody:f}=Jn(t,r,a,o),x=qn(n,t),k=Wn(s,t),v=[x.lines,k.lines].filter(I=>I.length>0).join(`
|
|
708
|
+
`);let L=h;v.length>0&&(L=h.length>0?`${h.trimEnd()}
|
|
709
709
|
${v}
|
|
710
710
|
`:`
|
|
711
711
|
${v}
|
|
712
|
-
`);const
|
|
712
|
+
`);const M=Xn(t),C=o.length>0?`import type { RegisteredShape } from "${u.server}";
|
|
713
713
|
`:"",$=o.length>0?`
|
|
714
714
|
/**
|
|
715
715
|
* Replication-shape registry — one entry per \`defineShape\` in \`lunora/shapes.ts\`.
|
|
@@ -724,23 +724,23 @@ export const LUNORA_SHAPES: Record<string, RegisteredShape> = {${f}};
|
|
|
724
724
|
* ShardDO's \`isCustomMutator\` override routes through the client-watermark push
|
|
725
725
|
* protocol (\`x-lunora-client-id\`/\`x-lunora-client-seq\` ordering).
|
|
726
726
|
*/
|
|
727
|
-
export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${l.map(
|
|
728
|
-
`:"",
|
|
729
|
-
`:"",
|
|
727
|
+
export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${l.map(I=>JSON.stringify(I)).join(", ")}]);
|
|
728
|
+
`:"",F=y.length>0?`import { DEFER_VALIDATION as DEFER, installCompiledValidatorMap } from "${u.values}";
|
|
729
|
+
`:"",ae=y.length>0?`
|
|
730
730
|
/**
|
|
731
731
|
* AOT-compiled argument validators (Worker-safe, no \`eval\`). Each is installed
|
|
732
732
|
* onto its function's live \`.args\` object and consulted by the interpreted
|
|
733
733
|
* parser as a zero-allocation fast path; anything it can't model is deferred.
|
|
734
734
|
*/
|
|
735
|
-
${
|
|
736
|
-
`:"",
|
|
737
|
-
${
|
|
738
|
-
`:"",
|
|
739
|
-
${
|
|
740
|
-
`:"",
|
|
741
|
-
`:"",
|
|
742
|
-
|
|
743
|
-
`:"";return
|
|
735
|
+
${y}
|
|
736
|
+
`:"",B=zn(t),oe=B.types?`
|
|
737
|
+
${B.types}
|
|
738
|
+
`:"",ie=B.implementation?`
|
|
739
|
+
${B.implementation}
|
|
740
|
+
`:"",W=Ke(B.types),T=W.length>0?`import type { ${W.join(", ")} } from "./dataModel.js";
|
|
741
|
+
`:"",Y=d?"context":"_context",O=d?`${Hn}
|
|
742
|
+
|
|
743
|
+
`:"";return ht(`${S}${g}${x.importLine}${k.importLine}${F}${C}import { LunoraError } from "${u.server}";
|
|
744
744
|
import type { ActionCtx, MutationCtx, QueryCtx } from "./server.js";
|
|
745
745
|
${T}
|
|
746
746
|
/**
|
|
@@ -766,8 +766,8 @@ ${x.prelude}${k.prelude}
|
|
|
766
766
|
* Static dispatch table. The key matches the \`__lunoraRef\` the client
|
|
767
767
|
* emits (\`api[namespace][fn].__lunoraRef === "namespace:fn"\`).
|
|
768
768
|
*/
|
|
769
|
-
export const LUNORA_FUNCTIONS: Record<string, RegisteredLunoraFunction> = {${
|
|
770
|
-
${
|
|
769
|
+
export const LUNORA_FUNCTIONS: Record<string, RegisteredLunoraFunction> = {${L}};
|
|
770
|
+
${ae}${$}${w}
|
|
771
771
|
/**
|
|
772
772
|
* Connection-lifecycle manifest: the function paths the generated ShardDO
|
|
773
773
|
* dispatches when a client's WebSocket connects (\`connect\`) or disconnects
|
|
@@ -775,8 +775,8 @@ ${te}${$}${w}
|
|
|
775
775
|
* DO runs every hook under the socket's verified identity via system dispatch.
|
|
776
776
|
*/
|
|
777
777
|
export const LUNORA_LIFECYCLE_HOOKS: { connect: readonly string[]; disconnect: readonly string[] } = {
|
|
778
|
-
connect: [${
|
|
779
|
-
disconnect: [${
|
|
778
|
+
connect: [${M.connect.map(I=>JSON.stringify(I)).join(", ")}],
|
|
779
|
+
disconnect: [${M.disconnect.map(I=>JSON.stringify(I)).join(", ")}],
|
|
780
780
|
};
|
|
781
781
|
|
|
782
782
|
/**
|
|
@@ -807,10 +807,10 @@ export type CallerCtx = ActionCtx | MutationCtx | QueryCtx;
|
|
|
807
807
|
* with the supplied \`context\`, exactly like \`ctx.runQuery\`/\`runMutation\`/
|
|
808
808
|
* \`runAction\` but without re-stating the function path.
|
|
809
809
|
*/
|
|
810
|
-
export interface Caller {${
|
|
810
|
+
export interface Caller {${oe}}
|
|
811
811
|
|
|
812
812
|
${O}/** Build a {@link Caller} bound to \`context\` (typically a handler's \`ctx\`). */
|
|
813
|
-
export const createCaller = (${
|
|
813
|
+
export const createCaller = (${Y}: CallerCtx): Caller => ({${ie}});
|
|
814
814
|
|
|
815
815
|
/**
|
|
816
816
|
* Single registered data migration, narrowed to the shape the per-shard runner
|
|
@@ -830,7 +830,7 @@ export interface RegisteredDataMigration {
|
|
|
830
830
|
* shard DO's admin RPC and the CLI resolve migrations to run through this map.
|
|
831
831
|
*/
|
|
832
832
|
export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${c}};
|
|
833
|
-
`,i)},
|
|
833
|
+
`,i)},Yn=e=>{const n={};for(const t of e.tables){const r={};for(const[a,o]of Object.entries(t.shape)){const i=re(o);i.kind==="id"&&i.tableName!==void 0&&(r[a]=i.tableName)}Object.keys(r).length>0&&(n[t.name]=r)}return n},Zn=e=>{const n={};for(const t of e.tables){const r=[];for(const[a,o]of Object.entries(t.shape))re(o).kind==="storage"&&r.push(a);r.length>0&&(n[t.name]=r)}return n},er=e=>{const n={};for(const t of e.tables){const r=[...t.indexes.map(a=>({fields:[...a.fields],name:a.name,type:"index",...a.unique===!0?{unique:!0}:{}})),...t.searchIndexes.map(a=>({fields:[a.field,...a.filterFields??[]],name:a.name,type:"search"})),...(t.geoIndexes??[]).map(a=>({fields:[a.field],name:a.name,type:"geo"})),...t.rankIndexes.map(a=>({fields:a.sortBy.map(o=>o.field),name:a.name,type:"rank"})),...t.vectorIndexes.map(a=>({fields:a.field===void 0?[]:[a.field],name:a.name,type:"vector"}))];r.length>0&&(n[t.name]=r)}return n},tr=e=>{const n=[];for(const t of e.tables)!t.ttl||t.shardMode==="global"||n.push({...t.ttl.after===void 0?{}:{after:t.ttl.after},field:t.ttl.field,...t.softDelete?{softDeleteField:t.softDelete.field}:{},table:t.name});return n},nr=e=>{const n={};for(const t 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(t.shape)){const i=ct(o),s=re(o),d={name:a,optional:i,type:s.kind};s.kind==="id"&&s.tableName!==void 0&&(d.ref=s.tableName),s.kind==="storage"&&(d.isStorage=!0),r.push(d)}n[t.name]=r}return n},rr=e=>e?{importFragment:"serveRelationFanout, ",override:`
|
|
834
834
|
protected override async runRelationFanoutRead(functionPath: string, args: Record<string, unknown>): Promise<unknown> {
|
|
835
835
|
this.ensureMigrated();
|
|
836
836
|
|
|
@@ -838,7 +838,7 @@ export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${c}}
|
|
|
838
838
|
|
|
839
839
|
return serveRelationFanout(schema as unknown as SchemaLike, db, functionPath, args);
|
|
840
840
|
}
|
|
841
|
-
`}:{importFragment:"",override:""},
|
|
841
|
+
`}:{importFragment:"",override:""},ar=e=>{if(!e)return{build:"",configField:"",contextField:"",stub:""};const n='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:`
|
|
842
842
|
const aiBinding = config.ai?.(env) ?? (env as Record<string, unknown>).AI;
|
|
843
843
|
// Correlate AI-Gateway-routed calls with the Lunora trace: thread the
|
|
844
844
|
// function path + trace id into createAi, which folds them into the
|
|
@@ -855,68 +855,54 @@ export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${c}}
|
|
|
855
855
|
ai,`,stub:`
|
|
856
856
|
const aiStub: LunoraAi = {
|
|
857
857
|
embeddingModel: () => {
|
|
858
|
-
${
|
|
858
|
+
${n}
|
|
859
859
|
},
|
|
860
860
|
model: () => {
|
|
861
|
-
${
|
|
861
|
+
${n}
|
|
862
862
|
},
|
|
863
863
|
run: async () => {
|
|
864
|
-
${
|
|
864
|
+
${n}
|
|
865
865
|
},
|
|
866
866
|
// workersai is a callable-with-properties; a bare throwing arrow isn't
|
|
867
867
|
// structurally assignable, so cast it. Never invoked (the stub throws first).
|
|
868
868
|
workersai: (() => {
|
|
869
|
-
${
|
|
869
|
+
${n}
|
|
870
870
|
}) as unknown as LunoraAi["workersai"],
|
|
871
871
|
};
|
|
872
|
-
`}},
|
|
872
|
+
`}},A=(e,n,t,{cast:r="",sync:a=[]}={})=>{const o=t.map(i=>` ${i}: ${a.includes(i)?"":"async "}() => {
|
|
873
|
+
${n}
|
|
874
|
+
},`).join(`
|
|
875
|
+
`);return`
|
|
876
|
+
const ${e} = {
|
|
877
|
+
${o}
|
|
878
|
+
}${r};
|
|
879
|
+
`},P={build:"",configField:"",contextField:"",importLines:[],stub:""},or=e=>e?{build:`
|
|
873
880
|
const kvBinding = config.kv?.(env) ?? (env as Record<string, unknown>).KV;
|
|
874
881
|
const kv: Kv = kvBinding ? createKv({ namespace: kvBinding as KVNamespaceLike }) : kvStub;
|
|
875
882
|
`,configField:`
|
|
876
883
|
kv?: (env: Record<string, unknown>) => KVNamespaceLike;`,contextField:`
|
|
877
|
-
kv,`,importLines:['import type { Kv, KVNamespaceLike } from "@lunora/bindings/kv";','import { createKv } from "@lunora/bindings/kv";'],stub:`
|
|
878
|
-
const
|
|
879
|
-
delete: async () => {
|
|
880
|
-
${t}
|
|
881
|
-
},
|
|
882
|
-
get: async () => {
|
|
883
|
-
${t}
|
|
884
|
-
},
|
|
885
|
-
getRaw: async () => {
|
|
886
|
-
${t}
|
|
887
|
-
},
|
|
888
|
-
getWithMetadata: async () => {
|
|
889
|
-
${t}
|
|
890
|
-
},
|
|
891
|
-
list: async () => {
|
|
892
|
-
${t}
|
|
893
|
-
},
|
|
894
|
-
put: async () => {
|
|
895
|
-
${t}
|
|
896
|
-
},
|
|
897
|
-
};
|
|
898
|
-
`}},er=(e,t)=>e?{build:`
|
|
899
|
-
const flags: import("${t}").LunoraFlags = createFlags({
|
|
884
|
+
kv,`,importLines:['import type { Kv, KVNamespaceLike } from "@lunora/bindings/kv";','import { createKv } from "@lunora/bindings/kv";'],stub:A("kvStub: Kv",'throw new Error("ctx.kv: no KV binding found. Add a \\`kv_namespaces\\` binding (env.KV) to wrangler.jsonc, or pass \\`kv\\` to createShardDO().");',["delete","get","getRaw","getWithMetadata","list","put"])}:P,ir=(e,n)=>e?{build:`
|
|
885
|
+
const flags: import("${n}").LunoraFlags = createFlags({
|
|
900
886
|
hooks: flagsConfig.hooks,
|
|
901
887
|
logger: flagsConfig.logger,
|
|
902
888
|
provider: () => config.flags?.(env) ?? flagsConfig.provider(env),
|
|
903
889
|
targetingKey: () => flagsConfig.identify?.({ identity: identity ?? null, userId: userId ?? null }),
|
|
904
890
|
});
|
|
905
891
|
`,configField:`
|
|
906
|
-
flags?: (env: Record<string, unknown>) => import("${
|
|
907
|
-
flags,`,importLines:[`import { createFlags } from "${
|
|
892
|
+
flags?: (env: Record<string, unknown>) => import("${n}").Provider;`,contextField:`
|
|
893
|
+
flags,`,importLines:[`import { createFlags } from "${n}";`,'import flagsConfig from "../flags.js";'],stub:""}:P,sr=e=>e?{build:`
|
|
908
894
|
const { notify, push } = createNotify(notifyConfig, env, { log, metrics });
|
|
909
895
|
`,configField:"",contextField:`
|
|
910
896
|
notify,
|
|
911
|
-
push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:
|
|
897
|
+
push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:P,lr=e=>e?{build:`
|
|
912
898
|
const envConfig = lunoraEnvContract.${e.exportName}(env);
|
|
913
899
|
`,configField:"",contextField:`
|
|
914
|
-
env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:
|
|
900
|
+
env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:P,dr=e=>e?{build:`
|
|
915
901
|
const access = accessFacade(identity, userId);
|
|
916
902
|
`,configField:"",contextField:`
|
|
917
|
-
access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:
|
|
903
|
+
access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:P,cr=(e,n,t)=>{if(!n)return{constant:"",evaluateOverride:"",subscriptionOverride:""};const r=s=>`
|
|
918
904
|
const env = (this.env ?? {}) as Record<string, unknown>;
|
|
919
|
-
const flags: import("${
|
|
905
|
+
const flags: import("${t}").LunoraFlags = createFlags({
|
|
920
906
|
hooks: flagsConfig.hooks,
|
|
921
907
|
logger: flagsConfig.logger,
|
|
922
908
|
provider: () => config.flags?.(env) ?? flagsConfig.provider(env),
|
|
@@ -926,7 +912,7 @@ const kvStub: Kv = {
|
|
|
926
912
|
const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number" | "object" | "string" }> = ${JSON.stringify(e,void 0,4)};
|
|
927
913
|
`,o=`
|
|
928
914
|
protected override async evaluateFlags(context?: Record<string, unknown>): Promise<FlagsResult> {${r("undefined")}
|
|
929
|
-
const evalContext = context as import("${
|
|
915
|
+
const evalContext = context as import("${t}").EvaluationContext | undefined;
|
|
930
916
|
const evaluations: FlagsResult["flags"] = [];
|
|
931
917
|
|
|
932
918
|
for (const entry of LUNORA_FLAG_KEYS) {
|
|
@@ -973,78 +959,30 @@ const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number"
|
|
|
973
959
|
}
|
|
974
960
|
|
|
975
961
|
if (args.type === "object") {
|
|
976
|
-
return flags.object(key, (args.default ?? {}) as import("${
|
|
962
|
+
return flags.object(key, (args.default ?? {}) as import("${t}").JsonValue, context);
|
|
977
963
|
}
|
|
978
964
|
|
|
979
965
|
return flags.boolean(key, typeof args.default === "boolean" ? args.default : false, context);
|
|
980
966
|
}
|
|
981
|
-
`;return{constant:a,evaluateOverride:o,subscriptionOverride:i}},
|
|
967
|
+
`;return{constant:a,evaluateOverride:o,subscriptionOverride:i}},ur=e=>e?{build:`
|
|
982
968
|
const analyticsBinding = config.analytics?.(env) ?? (env as Record<string, unknown>).ANALYTICS;
|
|
983
969
|
const analytics: AnalyticsClient = analyticsBinding ? createAnalytics(analyticsBinding as AnalyticsEngineDatasetLike) : analyticsStub;
|
|
984
970
|
`,configField:`
|
|
985
971
|
analytics?: (env: Record<string, unknown>) => AnalyticsEngineDatasetLike;`,contextField:`
|
|
986
|
-
analytics,`,importLines:['import type { AnalyticsClient, AnalyticsEngineDatasetLike } from "@lunora/bindings/analytics";','import { createAnalytics } from "@lunora/bindings/analytics";'],stub:`
|
|
987
|
-
const analyticsStub: AnalyticsClient = {
|
|
988
|
-
track: () => {
|
|
989
|
-
${t}
|
|
990
|
-
},
|
|
991
|
-
writeDataPoint: () => {
|
|
992
|
-
${t}
|
|
993
|
-
},
|
|
994
|
-
};
|
|
995
|
-
`}},sr=e=>{if(!e)return _;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:`
|
|
972
|
+
analytics,`,importLines:['import type { AnalyticsClient, AnalyticsEngineDatasetLike } from "@lunora/bindings/analytics";','import { createAnalytics } from "@lunora/bindings/analytics";'],stub:A("analyticsStub: AnalyticsClient",'throw new Error("ctx.analytics: no Analytics Engine binding found. Add an \\`analytics_engine_datasets\\` binding (env.ANALYTICS) to wrangler.jsonc, or pass \\`analytics\\` to createShardDO().");',["track","writeDataPoint"],{sync:["track","writeDataPoint"]})}:P,pr=e=>e?{build:`
|
|
996
973
|
const imagesBinding = config.images?.(env) ?? (env as Record<string, unknown>).IMAGES;
|
|
997
974
|
const images: Images = imagesBinding ? createImages({ binding: imagesBinding as ImagesBindingLike }) : imagesStub;
|
|
998
975
|
`,configField:`
|
|
999
976
|
images?: (env: Record<string, unknown>) => ImagesBindingLike;`,contextField:`
|
|
1000
|
-
images,`,importLines:['import type { Images, ImagesBindingLike } from "@lunora/bindings/images";','import { createImages } from "@lunora/bindings/images";'],stub:`
|
|
1001
|
-
const imagesStub: Images = {
|
|
1002
|
-
info: async () => {
|
|
1003
|
-
${t}
|
|
1004
|
-
},
|
|
1005
|
-
transform: async () => {
|
|
1006
|
-
${t}
|
|
1007
|
-
},
|
|
1008
|
-
};
|
|
1009
|
-
`}},ir=e=>e?{build:`
|
|
977
|
+
images,`,importLines:['import type { Images, ImagesBindingLike } from "@lunora/bindings/images";','import { createImages } from "@lunora/bindings/images";'],stub:A("imagesStub: Images",'throw new Error("ctx.images: no Images binding found. Add an \\`images\\` binding (env.IMAGES) to wrangler.jsonc, or pass \\`images\\` to createShardDO().");',["info","transform"])}:P,hr=e=>e?{build:`
|
|
1010
978
|
const sql: SqlClient = config.sql ? config.sql(env) : sqlStub;
|
|
1011
979
|
`,configField:`
|
|
1012
980
|
sql?: (env: Record<string, unknown>) => SqlClient;`,contextField:`
|
|
1013
|
-
sql,`,importLines:['import type { SqlClient } from "@lunora/hyperdrive";'],stub:`
|
|
1014
|
-
const sqlStub: SqlClient = {
|
|
1015
|
-
query: async () => {
|
|
1016
|
-
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))\\\`.");
|
|
1017
|
-
},
|
|
1018
|
-
};
|
|
1019
|
-
`}:_,lr=e=>{if(!e)return _;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'\\`. Session reuse (connect/sessions) additionally needs those two exports passed the same way.\");";return{build:`
|
|
981
|
+
sql,`,importLines:['import type { SqlClient } from "@lunora/hyperdrive";'],stub:A("sqlStub: SqlClient",'throw new Error("ctx.sql: provide a \\`sql\\` config thunk that builds a SqlClient from your driver, e.g. \\`sql: (env) => fromPostgresJs(postgres(env.HYPERDRIVE.connectionString))\\`.");',["query"])}:P,mr=e=>e?{build:`
|
|
1020
982
|
const browser: Browser = config.browser ? config.browser(env) : browserStub;
|
|
1021
983
|
`,configField:`
|
|
1022
984
|
browser?: (env: Record<string, unknown>) => Browser;`,contextField:`
|
|
1023
|
-
browser,`,importLines:['import type { Browser } from "@lunora/browser";'],stub:`
|
|
1024
|
-
const browserStub: Browser = {
|
|
1025
|
-
connect: async () => {
|
|
1026
|
-
${t}
|
|
1027
|
-
},
|
|
1028
|
-
content: async () => {
|
|
1029
|
-
${t}
|
|
1030
|
-
},
|
|
1031
|
-
launch: async () => {
|
|
1032
|
-
${t}
|
|
1033
|
-
},
|
|
1034
|
-
pdf: async () => {
|
|
1035
|
-
${t}
|
|
1036
|
-
},
|
|
1037
|
-
scrape: async () => {
|
|
1038
|
-
${t}
|
|
1039
|
-
},
|
|
1040
|
-
screenshot: async () => {
|
|
1041
|
-
${t}
|
|
1042
|
-
},
|
|
1043
|
-
sessions: async () => {
|
|
1044
|
-
${t}
|
|
1045
|
-
},
|
|
1046
|
-
};
|
|
1047
|
-
`}},dr=e=>{if(!e)return _;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:`
|
|
985
|
+
browser,`,importLines:['import type { Browser } from "@lunora/browser";'],stub:A("browserStub: Browser","throw new Error(\"ctx.browser: provide a \\`browser\\` config thunk, e.g. \\`browser: (env) => createBrowser({ binding: env.BROWSER, launch })\\` with \\`import { launch } from '@cloudflare/playwright'\\`. Session reuse (connect/sessions) additionally needs those two exports passed the same way.\");",["connect","content","launch","pdf","scrape","screenshot","sessions"])}:P,gr=e=>e?{build:`
|
|
1048
986
|
const r2sqlEnv = env as Record<string, unknown>;
|
|
1049
987
|
const r2sqlAccountId = (r2sqlEnv.R2_SQL_ACCOUNT_ID ?? r2sqlEnv.CLOUDFLARE_ACCOUNT_ID) as string | undefined;
|
|
1050
988
|
const r2sqlToken = r2sqlEnv.R2_SQL_TOKEN as string | undefined;
|
|
@@ -1055,41 +993,14 @@ const browserStub: Browser = {
|
|
|
1055
993
|
? createR2Sql({ accountId: r2sqlAccountId, apiToken: r2sqlToken, bucket: r2sqlBucket })
|
|
1056
994
|
: r2sqlStub;
|
|
1057
995
|
`,configField:`
|
|
1058
|
-
r2sql?: (env: Record<string, unknown>) => R2SqlClient;`,contextField:"",importLines:['import type { R2SqlClient } from "@lunora/bindings/r2sql";','import { createR2Sql } from "@lunora/bindings/r2sql";'],stub:`
|
|
1059
|
-
const r2sqlStub: R2SqlClient = {
|
|
1060
|
-
describe: async () => {
|
|
1061
|
-
${t}
|
|
1062
|
-
},
|
|
1063
|
-
explain: async () => {
|
|
1064
|
-
${t}
|
|
1065
|
-
},
|
|
1066
|
-
from: () => {
|
|
1067
|
-
${t}
|
|
1068
|
-
},
|
|
1069
|
-
query: async () => {
|
|
1070
|
-
${t}
|
|
1071
|
-
},
|
|
1072
|
-
showDatabases: async () => {
|
|
1073
|
-
${t}
|
|
1074
|
-
},
|
|
1075
|
-
showTables: async () => {
|
|
1076
|
-
${t}
|
|
1077
|
-
},
|
|
1078
|
-
};
|
|
1079
|
-
`}},cr=e=>e?{build:`
|
|
996
|
+
r2sql?: (env: Record<string, unknown>) => R2SqlClient;`,contextField:"",importLines:['import type { R2SqlClient } from "@lunora/bindings/r2sql";','import { createR2Sql } from "@lunora/bindings/r2sql";'],stub:A("r2sqlStub: R2SqlClient",'throw new Error("ctx.r2sql: no R2 SQL credentials found. Set \\`R2_SQL_TOKEN\\`, \\`R2_SQL_ACCOUNT_ID\\` (or \\`CLOUDFLARE_ACCOUNT_ID\\`), and \\`R2_SQL_BUCKET\\` in your env/.dev.vars, or pass an \\`r2sql\\` config thunk to createShardDO().");',["describe","explain","from","query","showDatabases","showTables"],{sync:["from"]})}:P,fr=e=>e?{build:`
|
|
1080
997
|
const pipelinesBinding = config.pipelines?.(env) ?? (env as Record<string, unknown>).PIPELINES;
|
|
1081
998
|
const pipelines: PipelineClient = pipelinesBinding ? createPipelines({ binding: pipelinesBinding as PipelineBindingLike }) : pipelinesStub;
|
|
1082
999
|
`,configField:`
|
|
1083
|
-
pipelines?: (env: Record<string, unknown>) => PipelineBindingLike;`,contextField:"",importLines:['import type { PipelineBindingLike, PipelineClient } from "@lunora/bindings/pipelines";','import { createPipelines } from "@lunora/bindings/pipelines";'],stub
|
|
1084
|
-
const pipelinesStub: PipelineClient = {
|
|
1085
|
-
send: async () => {
|
|
1086
|
-
throw new Error("ctx.pipelines: no Pipelines binding found. Add a \\\`pipelines\\\` binding (env.PIPELINES) to wrangler.jsonc, or pass \\\`pipelines\\\` to createShardDO().");
|
|
1087
|
-
},
|
|
1088
|
-
};
|
|
1089
|
-
`}:_,Pr=(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}\`). */
|
|
1000
|
+
pipelines?: (env: Record<string, unknown>) => PipelineBindingLike;`,contextField:"",importLines:['import type { PipelineBindingLike, PipelineClient } from "@lunora/bindings/pipelines";','import { createPipelines } from "@lunora/bindings/pipelines";'],stub:A("pipelinesStub: PipelineClient",'throw new Error("ctx.pipelines: no Pipelines binding found. Add a \\`pipelines\\` binding (env.PIPELINES) to wrangler.jsonc, or pass \\`pipelines\\` to createShardDO().");',["send"])}:P,Wr=(e,n)=>{if(e.length===0)return"";const t=n?`, ${JSON.stringify(n)}`:"",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}\`). */
|
|
1090
1001
|
export class ${o.className} extends LunoraContainer {
|
|
1091
1002
|
public constructor(ctx: ConstructorParameters<typeof LunoraContainer>[0], env: Record<string, unknown>) {
|
|
1092
|
-
super(ctx, env, ${o.exportName}, "${o.exportName}"${
|
|
1003
|
+
super(ctx, env, ${o.exportName}, "${o.exportName}"${t});
|
|
1093
1004
|
}
|
|
1094
1005
|
}
|
|
1095
1006
|
`)).join(`
|
|
@@ -1111,23 +1022,23 @@ import { ${a} } from "../containers.js";
|
|
|
1111
1022
|
|
|
1112
1023
|
export { ContainerProxy } from "@lunora/container/do";
|
|
1113
1024
|
|
|
1114
|
-
${r}`},
|
|
1025
|
+
${r}`},yr=(e,n)=>{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 t=e.map(r=>{const a=r.maxInstances===void 0?"":`, maxInstances: ${String(r.maxInstances)}`;return` { binding: "${r.bindingName}", exportName: "${r.exportName}"${a} },`}).join(`
|
|
1115
1026
|
`);return{build:`
|
|
1116
|
-
const containers = createContainerContext(env, LUNORA_CONTAINERS, ${
|
|
1027
|
+
const containers = createContainerContext(env, LUNORA_CONTAINERS, ${n?JSON.stringify(n):"undefined"}, this.getCurrentTraceparent());
|
|
1117
1028
|
`,contextField:`
|
|
1118
1029
|
containers,`,importLines:['import type { ContainerBindingSpec } from "@lunora/container";','import { createContainerContext } from "@lunora/container";'],specs:`
|
|
1119
1030
|
/** Wiring specs for \`ctx.containers\` (codegen-derived from \`lunora/containers.ts\`). */
|
|
1120
1031
|
const LUNORA_CONTAINERS: ReadonlyArray<ContainerBindingSpec> = [
|
|
1121
|
-
${
|
|
1032
|
+
${t}
|
|
1122
1033
|
];
|
|
1123
|
-
`}},
|
|
1034
|
+
`}},Ur=e=>{if(e.length===0)return"";const n=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}\`). */
|
|
1124
1035
|
export class ${r.className} extends LunoraWorkflow<WorkflowParamsOf<typeof ${r.exportName}>, WorkflowOutputOf<typeof ${r.exportName}>> {
|
|
1125
1036
|
public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
1126
1037
|
super(ctx, env, ${r.exportName}, "${r.exportName}");
|
|
1127
1038
|
}
|
|
1128
1039
|
}
|
|
1129
1040
|
`)).join(`
|
|
1130
|
-
`),
|
|
1041
|
+
`),t=e.map(r=>r.exportName).join(", ");return`${S}/**
|
|
1131
1042
|
* WorkflowEntrypoint classes for the workflows declared in
|
|
1132
1043
|
* \`lunora/workflows.ts\`. Re-export them from your worker entry — wrangler
|
|
1133
1044
|
* requires each \`workflows[].class_name\` to be exported by the worker:
|
|
@@ -1136,7 +1047,7 @@ export class ${r.className} extends LunoraWorkflow<WorkflowParamsOf<typeof ${r.e
|
|
|
1136
1047
|
*/
|
|
1137
1048
|
import LunoraWorkflow from "@lunora/workflow/do";
|
|
1138
1049
|
|
|
1139
|
-
import { ${
|
|
1050
|
+
import { ${t} } from "../workflows.js";
|
|
1140
1051
|
|
|
1141
1052
|
/** Params type carried by a \`defineWorkflow\` definition (its phantom \`__params\`), so each entrypoint keeps the authored \`ctx.params\` type. */
|
|
1142
1053
|
type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params }
|
|
@@ -1148,7 +1059,7 @@ type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params
|
|
|
1148
1059
|
/** Output type carried by a \`defineWorkflow\` definition (its phantom \`__output\`), so each entrypoint keeps the authored return type. */
|
|
1149
1060
|
type WorkflowOutputOf<Definition> = Definition extends { __output?: infer Output } ? Output : unknown;
|
|
1150
1061
|
|
|
1151
|
-
${
|
|
1062
|
+
${n}`},Kr=e=>{if(e.length===0)return"";const n=e.filter(a=>a.voice).length>0,t=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}\`). */
|
|
1152
1063
|
export class ${a.className} extends LunoraWorkflow<AgentRunInput, AgentRunResult> {
|
|
1153
1064
|
public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
1154
1065
|
super(ctx, env, compileAgentWorkflow(${a.exportName}, "${a.exportName}"), "${a.exportName}");
|
|
@@ -1168,15 +1079,15 @@ export class ${i} extends VoiceSessionDO {
|
|
|
1168
1079
|
* Workflow. Re-export them from your worker entry — wrangler requires each
|
|
1169
1080
|
* \`workflows[].class_name\` to be exported by the worker:
|
|
1170
1081
|
*
|
|
1171
|
-
* \`export * from "./lunora/_generated/agents.js";\`${
|
|
1082
|
+
* \`export * from "./lunora/_generated/agents.js";\`${n?"\n *\n * Voice-enabled agents ALSO get a `VoiceSessionDO` subclass here — a real\n * Durable Object (unlike the Workflow), so wrangler needs both its\n * `durable_objects` binding and its `class_name` export (the same re-export\n * line covers it).":""}
|
|
1172
1083
|
*/
|
|
1173
1084
|
import LunoraWorkflow from "@lunora/workflow/do";
|
|
1174
|
-
${
|
|
1085
|
+
${n?'import { compileAgentWorkflow, VoiceSessionDO } from "@lunora/agent";':'import { compileAgentWorkflow } from "@lunora/agent";'}
|
|
1175
1086
|
import type { AgentRunInput, AgentRunResult } from "@lunora/agent";
|
|
1176
1087
|
|
|
1177
1088
|
import { ${r} } from "../agents.js";
|
|
1178
1089
|
|
|
1179
|
-
${
|
|
1090
|
+
${t}`},Qr=e=>{const n=e.filter(a=>a.mode==="push");if(n.length===0)return"";for(const a of n)m(a.exportName,`queue export "${a.exportName}"`);const t=n.map(a=>a.exportName).join(", "),r=n.map(a=>` ${JSON.stringify(a.name)}: { definition: ${a.exportName}, exportName: ${JSON.stringify(a.exportName)} },`).join(`
|
|
1180
1091
|
`);return`${S}/**
|
|
1181
1092
|
* Push-consumer registry for the queues declared in \`lunora/queues.ts\`. The
|
|
1182
1093
|
* composed worker's \`queue(batch, env, ctx)\` entry routes each delivered batch
|
|
@@ -1185,105 +1096,61 @@ ${n}`},qr=e=>{const t=e.filter(a=>a.mode==="push");if(t.length===0)return"";for(
|
|
|
1185
1096
|
*/
|
|
1186
1097
|
import type { QueueRegistry } from "@lunora/queue";
|
|
1187
1098
|
|
|
1188
|
-
import { ${
|
|
1099
|
+
import { ${t} } from "../queues.js";
|
|
1189
1100
|
|
|
1190
1101
|
/** Stable wrangler queue name → { definition, exportName } for batch routing. */
|
|
1191
1102
|
export const LUNORA_QUEUE_REGISTRY: QueueRegistry = {
|
|
1192
1103
|
${r}
|
|
1193
1104
|
};
|
|
1194
|
-
`},
|
|
1105
|
+
`},br=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const t of e)m(t.exportName,`workflow export "${t.exportName}"`),m(t.bindingName,`workflow binding "${t.bindingName}"`);const n=e.map(t=>` { binding: "${t.bindingName}", exportName: "${t.exportName}" },`).join(`
|
|
1195
1106
|
`);return{build:`
|
|
1196
1107
|
const workflows = createWorkflowContext(env, LUNORA_WORKFLOWS);
|
|
1197
1108
|
`,contextField:`
|
|
1198
1109
|
workflows,`,importLines:['import type { WorkflowBindingSpec } from "@lunora/workflow";','import { createWorkflowContext } from "@lunora/workflow";'],specs:`
|
|
1199
1110
|
/** Wiring specs for \`ctx.workflows\` (codegen-derived from \`lunora/workflows.ts\`). */
|
|
1200
1111
|
const LUNORA_WORKFLOWS: ReadonlyArray<WorkflowBindingSpec> = [
|
|
1201
|
-
${
|
|
1112
|
+
${n}
|
|
1202
1113
|
];
|
|
1203
|
-
`}},
|
|
1114
|
+
`}},wr=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const t of e)m(t.exportName,`queue export "${t.exportName}"`),m(t.bindingName,`queue binding "${t.bindingName}"`);const n=e.map(t=>` { binding: "${t.bindingName}", exportName: "${t.exportName}", name: ${JSON.stringify(t.name)} },`).join(`
|
|
1204
1115
|
`);return{build:`
|
|
1205
1116
|
const queues = createQueueContext(env, LUNORA_QUEUES);
|
|
1206
1117
|
`,contextField:`
|
|
1207
1118
|
queues,`,importLines:['import type { QueueBindingSpec } from "@lunora/queue";','import { createQueueContext } from "@lunora/queue";'],specs:`
|
|
1208
1119
|
/** Wiring specs for \`ctx.queues\` (codegen-derived from \`lunora/queues.ts\`). */
|
|
1209
1120
|
const LUNORA_QUEUES: ReadonlyArray<QueueBindingSpec> = [
|
|
1210
|
-
${
|
|
1121
|
+
${n}
|
|
1211
1122
|
];
|
|
1212
|
-
`}},
|
|
1123
|
+
`}},xr=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const t of e)m(t.exportName,`agent export "${t.exportName}"`),m(t.bindingName,`agent binding "${t.bindingName}"`);const n=e.map(t=>` { binding: "${t.bindingName}", exportName: "${t.exportName}"${t.publicRun===!0?", publicRun: true":""} },`).join(`
|
|
1213
1124
|
`);return{build:`
|
|
1214
1125
|
const agents = createAgentContext(env, LUNORA_AGENTS);
|
|
1215
1126
|
`,contextField:`
|
|
1216
1127
|
agents,`,importLines:['import { createAgentContext } from "@lunora/agent";','import type { AgentBindingSpec } from "@lunora/agent";'],specs:`
|
|
1217
1128
|
/** Wiring specs for \`ctx.agents\` (codegen-derived from \`lunora/agents.ts\`). */
|
|
1218
1129
|
const LUNORA_AGENTS: ReadonlyArray<AgentBindingSpec> = [
|
|
1219
|
-
${
|
|
1130
|
+
${n}
|
|
1220
1131
|
];
|
|
1221
|
-
`}},
|
|
1222
|
-
|
|
1223
|
-
const
|
|
1224
|
-
`,override:`
|
|
1225
|
-
protected override workflowsMetadata(): WorkflowsResult {
|
|
1226
|
-
return LUNORA_WORKFLOWS_INFO;
|
|
1227
|
-
}
|
|
1228
|
-
`}},fr=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:`
|
|
1229
|
-
/** Read-only declared-queue metadata (discovered from \`lunora/queues.ts\`) served via \`__lunora_admin__:listQueues\` for the studio's queues view. */
|
|
1230
|
-
const LUNORA_QUEUES_INFO: QueuesResult = ${JSON.stringify(t,void 0,4)};
|
|
1132
|
+
`}},gt=(e,n,t,r,a)=>({constant:`
|
|
1133
|
+
${a}
|
|
1134
|
+
const ${e}: ${n} = ${JSON.stringify(r,void 0,4)};
|
|
1231
1135
|
`,override:`
|
|
1232
|
-
protected override
|
|
1233
|
-
return
|
|
1136
|
+
protected override ${t}(): ${n} {
|
|
1137
|
+
return ${e};
|
|
1234
1138
|
}
|
|
1235
|
-
`}
|
|
1139
|
+
`}),kr=e=>{if(e.length===0)return{constant:"",override:""};const n={workflows:e.map(t=>({binding:t.bindingName,className:t.className,exportName:t.exportName,name:t.name}))};return gt("LUNORA_WORKFLOWS_INFO","WorkflowsResult","workflowsMetadata",n,"/** Read-only declared-workflow metadata (discovered from `lunora/workflows.ts`) served via `__lunora_admin__:listWorkflows` for the studio's workflows view. */")},vr=e=>{if(e.length===0)return{constant:"",override:""};const n={queues:e.map(t=>({binding:t.bindingName,...t.tuning.deadLetterQueue===void 0?{}:{deadLetterQueue:t.tuning.deadLetterQueue},exportName:t.exportName,mode:t.mode,name:t.name}))};return gt("LUNORA_QUEUES_INFO","QueuesResult","queuesMetadata",n,"/** Read-only declared-queue metadata (discovered from `lunora/queues.ts`) served via `__lunora_admin__:listQueues` for the studio's queues view. */")},$r=e=>e?{imports:['import type { LunoraDatabaseLike as LunoraPaymentDbLike, LunoraPayment, PaymentsFromContextOptions } from "@lunora/payment";','import { paymentsFromContext } from "@lunora/payment";'],build:`
|
|
1236
1140
|
const payments: LunoraPayment = config.payment
|
|
1237
1141
|
? paymentsFromContext({ auth: { userId: userId ?? null }, db: db as unknown as LunoraPaymentDbLike }, config.payment(env))
|
|
1238
1142
|
: paymentStub;
|
|
1239
1143
|
`,configField:`
|
|
1240
1144
|
payment?: (env: Record<string, unknown>) => PaymentsFromContextOptions;`,contextField:`
|
|
1241
|
-
payments,`,stub:`
|
|
1242
|
-
const paymentStub: LunoraPayment = {
|
|
1243
|
-
attach: () => {
|
|
1244
|
-
${t}
|
|
1245
|
-
},
|
|
1246
|
-
cancelSubscription: () => {
|
|
1247
|
-
${t}
|
|
1248
|
-
},
|
|
1249
|
-
check: () => {
|
|
1250
|
-
${t}
|
|
1251
|
-
},
|
|
1252
|
-
createCheckout: () => {
|
|
1253
|
-
${t}
|
|
1254
|
-
},
|
|
1255
|
-
createPortalSession: () => {
|
|
1256
|
-
${t}
|
|
1257
|
-
},
|
|
1258
|
-
handleWebhook: () => {
|
|
1259
|
-
${t}
|
|
1260
|
-
},
|
|
1261
|
-
listBalances: () => {
|
|
1262
|
-
${t}
|
|
1263
|
-
},
|
|
1264
|
-
listSubscriptions: () => {
|
|
1265
|
-
${t}
|
|
1266
|
-
},
|
|
1267
|
-
track: () => {
|
|
1268
|
-
${t}
|
|
1269
|
-
},
|
|
1270
|
-
} as unknown as LunoraPayment;
|
|
1271
|
-
`}},yr=e=>e?{imports:['import type { X402Pay, X402PayConfig } from "@lunora/x402/pay";','import { lazyX402Pay } from "@lunora/x402/pay";'],build:`
|
|
1145
|
+
payments,`,stub:A("paymentStub: LunoraPayment",'throw new Error("ctx.payments: no payment configured. Pass \\`payment\\` to createShardDO().");',["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"],{cast:" as unknown as LunoraPayment",sync:["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"]})}:{build:"",configField:"",contextField:"",imports:[],stub:""},Sr=e=>e?{imports:['import type { X402Pay, X402PayConfig } from "@lunora/x402/pay";','import { lazyX402Pay } from "@lunora/x402/pay";'],build:`
|
|
1272
1146
|
const x402: X402Pay = config.x402
|
|
1273
1147
|
? lazyX402Pay(config.x402(env), { getSecret: (name: string) => secrets.get(name) })
|
|
1274
1148
|
: x402Stub;
|
|
1275
1149
|
`,configField:`
|
|
1276
|
-
x402?: (env: Record<string, unknown>) => X402PayConfig;`,
|
|
1277
|
-
x402,`,stub:`
|
|
1278
|
-
const x402Stub: X402Pay = {
|
|
1279
|
-
fetch: () => {
|
|
1280
|
-
throw new Error("ctx.x402: no pay rail configured. Pass \\\`x402\\\` to createShardDO().");
|
|
1281
|
-
},
|
|
1282
|
-
} as unknown as X402Pay;
|
|
1283
|
-
`}:{build:"",configField:"",contextField:"",imports:[],stub:""},wr=(e,t,n,r)=>["AdvisorProcedure","AdvisoryFinding","DatabaseWriterLike","DataMigrationLike","ExportRow",...r?["FlagsResult"]:[],"ImportShardResult","KeyRange","MaskPoliciesResult","MigrationRunResult",...n?["QueuesResult"]:[],"RunShardApplyCdcArgs","RunShardExportArgs","RunShardImportArgs","RunShardMigrationArgs","RlsPoliciesResult","RunShardRankBeforeArgs","RunShardRankPageArgs","RunShardWriteArgs","RunShardWriteResult","SchedulerLike","TransactionHeadroomTracker","SchemaLike","ShardDOState","ShardRankPageResult","SqlExec","StorageRulesResult","StudioFeaturesResult","SystemReaderStorageLike","TelemetrySink",...t?["WorkflowsResult"]:[],...e?["WriteHook"]:[]],Br=({advisories:e=[],advisorProcedures:t=[],agents:n=[],containers:r=[],env:a,flagKeys:o=[],hasAccessFacade:i=!1,hasAi:s=!1,hasAnalytics:d=!1,hasBrowser:u=!1,hasFlags:p=!1,hasHyperdrive:g=!1,hasImages:b=!1,hasKv:c=!1,hasNotify:l=!1,hasPayments:f=!1,hasPipelines:x=!1,hasR2sql:k=!1,hasX402:v=!1,maskMetadata:A,mutators:P=[],queues:L=[],rlsMetadata:$,schema:w,schemaSnapshot:M,shapes:te=[],storageRules:F,studioFeatures:ne,useUmbrella:re=!1,workflows:j=[]})=>{const T=ee(re),z=P.length>0,O=te.length>0,C=M===void 0?"":on(M),q=M===void 0?"":`
|
|
1150
|
+
x402?: (env: Record<string, unknown>) => X402PayConfig;`,stub:A("x402Stub: X402Pay",'throw new Error("ctx.x402: no pay rail configured. Pass \\`x402\\` to createShardDO().");',["fetch"],{cast:" as unknown as X402Pay",sync:["fetch"]})}:{build:"",configField:"",imports:[],stub:""},Rr=(e,n,t,r)=>["AdvisorProcedure","AdvisoryFinding","DatabaseWriterLike","DataMigrationLike","ExportRow",...r?["FlagsResult"]:[],"ImportShardResult","KeyRange","MaskPoliciesResult","MigrationRunResult",...t?["QueuesResult"]:[],"RunShardApplyCdcArgs","RunShardExportArgs","RunShardImportArgs","RunShardMigrationArgs","RlsPoliciesResult","RunShardRankBeforeArgs","RunShardRankPageArgs","RunShardWriteArgs","RunShardWriteResult","SchedulerLike","TransactionHeadroomTracker","SchemaLike","ShardDOState","ShardRankPageResult","SqlExec","StorageRulesResult","StudioFeaturesResult","SystemReaderStorageLike","TelemetrySink",...n?["WorkflowsResult"]:[],...e?["WriteHook"]:[]],Vr=({advisories:e=[],advisorProcedures:n=[],agents:t=[],containers:r=[],env:a,flagKeys:o=[],hasAccessFacade:i=!1,hasAi:s=!1,hasAnalytics:d=!1,hasBrowser:u=!1,hasFlags:h=!1,hasHyperdrive:g=!1,hasImages:y=!1,hasKv:c=!1,hasNotify:l=!1,hasPayments:f=!1,hasPipelines:x=!1,hasR2sql:k=!1,hasX402:v=!1,maskMetadata:L,mutators:M=[],queues:C=[],rlsMetadata:$,schema:w,schemaSnapshot:F,shapes:ae=[],storageRules:B,studioFeatures:oe,useUmbrella:ie=!1,workflows:W=[]})=>{const T=ne(ie),Y=M.length>0,O=ae.length>0,I=F===void 0?"":hn(F),j=F===void 0?"":`
|
|
1284
1151
|
/** Structural schema snapshot + its content hash, recorded in the shard's \`__lunora_schema_history\` ledger on cold start so the studio can show a schema-version timeline and diff any two versions. */
|
|
1285
|
-
const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(
|
|
1286
|
-
`,
|
|
1152
|
+
const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(mn(F))}, json: ${JSON.stringify(I)} };
|
|
1153
|
+
`,se=F===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",{build:le,configField:Re,contextField:Ne,stub:Ae}=ar(s),de=dr(i),V=or(c),E=ir(h,T.flags),H=cr(o,h,T.flags),Z=sr(l),ce=lr(a),J=ur(d),U=pr(y),K=hr(g),Q=mr(u),q=gr(k),ee=fr(x),{build:Te,contextField:xe,importLines:ke,specs:ue}=wr(C),{build:Oe,contextField:Le,importLines:ve,specs:pe}=yr(r,w.jurisdiction),{build:Ce,contextField:Ie,importLines:$e,specs:_e}=br(W),{build:De,contextField:he,importLines:me,specs:Pe}=xr(t),{build:Ee,configField:Me,contextField:ge,imports:fe,stub:p}=$r(f),{build:Fe,configField:yt,imports:bt,stub:wt}=Sr(v),xt=e,kt=n,vt=$??{policies:[],roles:[]},$t=L??{columns:[]},St=B??{rules:[]},Rt=oe??{analytics:!1,auth:!1,containers:!1,flags:!1,kv:!1,mail:!1,notifications:!1,payments:!1,queues:!1,scheduler:!1,storage:!1,vectors:!1,workflows:!1},{constant:Nt,override:At}=kr(W),{constant:Tt,override:Ot}=vr(C),z=w.vectorIndexes.length>0,He=new Set(w.tables.filter(b=>typeof b.shardMode=="object"&&b.shardMode.kind==="shardBy").map(b=>b.name)),Se=w.vectorIndexes.some(b=>He.has(b.table)),ye=w.tables.some(b=>b.shardMode==="global"),Be=w.tables.some(b=>b.shardMode==="global"&&b.globalBackend==="hyperdrive"),Je=w.tables.some(b=>b.shardMode==="global"&&b.globalBackend!=="hyperdrive"),G=w.tables.some(b=>b.externalSource!==void 0);if(Je&&Be)throw new te("INTERNAL",'lunora codegen: mixing `.global()` (D1) and `.global({ backend: "hyperdrive" })` tables in one app is not supported yet — use a single global backend.');const je=w.tables.length>0,Lt=Yn(w),Ct=er(w),It=nr(w),_t=Zn(w),ze=tr(w),Ge=Rr(z,W.length>0,C.length>0,h);O&&Ge.push("WhereInput");const Xe=rr(ye),Dt=O?`
|
|
1287
1154
|
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 {
|
|
1288
1155
|
const shape = LUNORA_SHAPES[name];
|
|
1289
1156
|
|
|
@@ -1336,50 +1203,31 @@ const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.st
|
|
|
1336
1203
|
|
|
1337
1204
|
return { columns: shape.columns, effectiveWhere, global: isGlobal, table: shape.table };
|
|
1338
1205
|
}
|
|
1339
|
-
`:"",
|
|
1206
|
+
`:"",Pt=Y?`
|
|
1340
1207
|
protected override isCustomMutator(functionPath: string): boolean {
|
|
1341
1208
|
return LUNORA_MUTATOR_PATHS.has(functionPath);
|
|
1342
1209
|
}
|
|
1343
|
-
`:"",
|
|
1344
|
-
vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",
|
|
1345
|
-
d1?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",
|
|
1346
|
-
hyperdriveGlobal?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",
|
|
1347
|
-
sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",
|
|
1348
|
-
const vectorsStub: VectorSearchLike = {
|
|
1349
|
-
deleteByIds: async () => {
|
|
1350
|
-
throw new Error("ctx.vectors: no vectors configured. Pass \`vectors\` to createShardDO().");
|
|
1351
|
-
},
|
|
1352
|
-
getByIds: async () => {
|
|
1353
|
-
throw new Error("ctx.vectors: no vectors configured. Pass \`vectors\` to createShardDO().");
|
|
1354
|
-
},
|
|
1355
|
-
query: async () => {
|
|
1356
|
-
throw new Error("ctx.vectors: no vectors configured. Pass \`vectors\` to createShardDO().");
|
|
1357
|
-
},
|
|
1358
|
-
upsert: async () => {
|
|
1359
|
-
throw new Error("ctx.vectors: no vectors configured. Pass \`vectors\` to createShardDO().");
|
|
1360
|
-
},
|
|
1361
|
-
upsertNow: async () => {
|
|
1362
|
-
throw new Error("ctx.vectors: no vectors configured. Pass \`vectors\` to createShardDO().");
|
|
1363
|
-
},
|
|
1364
|
-
};
|
|
1365
|
-
`:"",Bt=ke?`
|
|
1210
|
+
`:"",Et=O?"\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":"",Mt=O?"assertShapeShardable, ":"",be=[`import type { ${Ge.join(", ")} } from "${T.do}";`,`import { applyCdcChanges, ${Mt}createReadFootprint, createShardCtxDb, exportShardRows, importShardRows, ${G?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}${Se?"ROOT_SHARD_NAME, ":""}runDataMigration, runShardMigrations, ${Xe.importFragment}ShardDO as ShardDOBase } from "${T.do}";`,...G?[`import type { ExternalSourceLike, SourceClientLike } from "${T.do}";`]:[],O?`import { asBucketStorage, buildRlsReadRegistry, composeShapeReadWhere, createSecrets, LunoraError } from "${T.server}";`:`import { asBucketStorage, createSecrets, LunoraError } from "${T.server}";`];je&&be.push(`import { bindOrm, bindTableFacade } from "${T.server}";`),z&&be.push('import type { SchemaLike as VectorSchemaLike, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";','import { createContextVectors, createVectors, createVectorSyncHook } from "@lunora/bindings/vectors";'),s&&be.push('import type { AiBindingLike, LunoraAi } from "@lunora/ai";','import { createAi } from "@lunora/ai";'),be.push(...de.importLines,...V.importLines,...E.importLines,...Z.importLines,...ce.importLines,...J.importLines,...U.importLines,...K.importLines,...Q.importLines,...q.importLines,...ee.importLines,...ve,...$e,...ke,...me,...fe,...bt,"",'import schema from "../schema.js";',`import { ${["LUNORA_FUNCTIONS","LUNORA_LIFECYCLE_HOOKS","LUNORA_MIGRATIONS",...Y?["LUNORA_MUTATOR_PATHS"]:[],...O?["LUNORA_SHAPES"]:[]].join(", ")} } from "./functions.js";`);const Ft=z?`
|
|
1211
|
+
vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",Bt=Je?`
|
|
1212
|
+
d1?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",jt=Be?`
|
|
1213
|
+
hyperdriveGlobal?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",qt=G?`
|
|
1214
|
+
sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",Wt='throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");',Ut='throw new Error("ctx.vectors: no vectors configured. Pass `vectors` to createShardDO().");',Kt='throw new Error("ctx.scheduler: no scheduler configured. Pass `scheduler` to createShardDO().");',Qt='throw new Error("ctx.storage: no storage configured. Pass `storage` to createShardDO().");',Vt=ye?A("globalDbStub: DatabaseWriterLike",Wt,["aggregate","count","delete","findFirst","findFirstOrThrow","findMany","get","groupBy","insert","normalizeId","patch","query","rank","rankPage","replace"],{sync:["normalizeId","query"]}):"",Ht=z?A("vectorsStub: VectorSearchLike",Ut,["deleteByIds","getByIds","query","upsert","upsertNow"]):"",Jt=Se?`
|
|
1366
1215
|
const vectorShardKey = this.currentShardKey();
|
|
1367
|
-
`:"",
|
|
1216
|
+
`:"",zt=Se?"namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, ":"",Gt=Se?`, { namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, shardedIndexNames: [${w.vectorIndexes.filter(b=>He.has(b.table)).map(b=>JSON.stringify(b.name)).join(", ")}] }`:"",Xt=z?`
|
|
1368
1217
|
let vectors: VectorSearchLike;
|
|
1369
1218
|
let onWrite: WriteHook | undefined;
|
|
1370
1219
|
|
|
1371
1220
|
if (config.vectors) {
|
|
1372
1221
|
const lunora = createVectors({ indexes: config.vectors(env) });
|
|
1373
|
-
${
|
|
1374
|
-
vectors = createContextVectors(lunora${
|
|
1375
|
-
onWrite = createVectorSyncHook({ ${
|
|
1222
|
+
${Jt}
|
|
1223
|
+
vectors = createContextVectors(lunora${Gt});
|
|
1224
|
+
onWrite = createVectorSyncHook({ ${zt}schema: schema as unknown as VectorSchemaLike, vectors });
|
|
1376
1225
|
} else {
|
|
1377
1226
|
vectors = vectorsStub;
|
|
1378
1227
|
onWrite = undefined;
|
|
1379
1228
|
}
|
|
1380
|
-
`:"",
|
|
1381
|
-
|
|
1382
|
-
auth: { identity: identity ?? null, userId: userId ?? null },`,Kt=J?`{${Ge}
|
|
1229
|
+
`:"",Yt=`{
|
|
1230
|
+
auth: { identity: identity ?? null, userId: userId ?? null },
|
|
1383
1231
|
broadcast: (delta) => {
|
|
1384
1232
|
this.recordChangedTable(delta.table, delta.indexKeys);
|
|
1385
1233
|
},
|
|
@@ -1388,33 +1236,30 @@ ${Bt}
|
|
|
1388
1236
|
headroom: options.headroom ?? this.transactionHeadroom(),
|
|
1389
1237
|
onIndexUse: this.getCtxDbIndexUseHook(),
|
|
1390
1238
|
onRead: options.onRead ?? this.getCtxDbReadHook(),
|
|
1391
|
-
onReadRange: options.onReadRange
|
|
1392
|
-
onWrite
|
|
1239
|
+
onReadRange: options.onReadRange,${z?`
|
|
1240
|
+
onWrite,`:""}
|
|
1393
1241
|
scheduler,
|
|
1394
1242
|
schema: schema as unknown as SchemaLike,
|
|
1395
1243
|
sql: this.sql as SqlExec,
|
|
1396
|
-
storage,${
|
|
1397
|
-
|
|
1244
|
+
storage,${ye?`
|
|
1245
|
+
globalDb,`:""}
|
|
1246
|
+
}`,X=` const env = (this.env ?? {}) as Record<string, unknown>;
|
|
1247
|
+
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
1248
|
+
const writer = createShardCtxDb({
|
|
1398
1249
|
broadcast: (delta) => {
|
|
1399
1250
|
this.recordChangedTable(delta.table, delta.indexKeys);
|
|
1400
1251
|
},
|
|
1401
1252
|
cdc: config.cdc ?? false,
|
|
1402
|
-
enforceRls: true,
|
|
1403
|
-
headroom: options.headroom ?? this.transactionHeadroom(),
|
|
1404
|
-
onIndexUse: this.getCtxDbIndexUseHook(),
|
|
1405
|
-
onRead: options.onRead ?? this.getCtxDbReadHook(),
|
|
1406
|
-
onReadRange: options.onReadRange,
|
|
1407
1253
|
scheduler,
|
|
1408
1254
|
schema: schema as unknown as SchemaLike,
|
|
1409
1255
|
sql: this.sql as SqlExec,
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
`:"",Gt=O&&ge?`
|
|
1256
|
+
});`,Zt=z?`
|
|
1257
|
+
vectors,`:"",en=je?`
|
|
1258
|
+
orm: bindOrm(facade),`:"",Ye=Be?"config.hyperdriveGlobal":"config.d1",tn=ye?` const globalDb: DatabaseWriterLike = ${Ye}?.(env, { identity, userId }) ?? globalDbStub;
|
|
1259
|
+
`:"",nn=O&&ye?`
|
|
1415
1260
|
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 }>> {
|
|
1416
1261
|
const env = this.env as Record<string, unknown>;
|
|
1417
|
-
const globalDb: DatabaseWriterLike = ${
|
|
1262
|
+
const globalDb: DatabaseWriterLike = ${Ye}?.(env, identity) ?? globalDbStub;
|
|
1418
1263
|
const rows: Array<{ doc: Record<string, unknown>; id: string }> = [];
|
|
1419
1264
|
|
|
1420
1265
|
let cursor: null | string = null;
|
|
@@ -1441,10 +1286,10 @@ ${Bt}
|
|
|
1441
1286
|
|
|
1442
1287
|
return rows;
|
|
1443
1288
|
}
|
|
1444
|
-
`:"",
|
|
1289
|
+
`:"",rn=G?`
|
|
1445
1290
|
const sourceClientCache = new WeakMap<object, Map<string, SourceClientLike>>();
|
|
1446
1291
|
const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
|
|
1447
|
-
`:"",
|
|
1292
|
+
`:"",an=G?`
|
|
1448
1293
|
protected override async pollExternalSources(): Promise<number | undefined> {
|
|
1449
1294
|
const env = (this.env ?? {}) as Record<string, unknown>;
|
|
1450
1295
|
const sourced = Object.entries((schema as unknown as SchemaLike).tables)
|
|
@@ -1580,7 +1425,7 @@ const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
|
|
|
1580
1425
|
|
|
1581
1426
|
return nextDueAt;
|
|
1582
1427
|
}
|
|
1583
|
-
`:"",
|
|
1428
|
+
`:"",Ze=ze.length>0,on=G||Ze?`
|
|
1584
1429
|
public constructor(state: ShardDOState, env: unknown) {
|
|
1585
1430
|
super(state, env);
|
|
1586
1431
|
${G?`
|
|
@@ -1593,27 +1438,27 @@ ${G?`
|
|
|
1593
1438
|
if (autoSourced) {
|
|
1594
1439
|
void this.scheduleSourcePoll();
|
|
1595
1440
|
}
|
|
1596
|
-
`:""}${
|
|
1441
|
+
`:""}${Ze?`
|
|
1597
1442
|
if (LUNORA_TTL_SWEEPS.length > 0) {
|
|
1598
1443
|
void this.scheduleTtlSweep();
|
|
1599
1444
|
}
|
|
1600
1445
|
`:""} }
|
|
1601
|
-
`:"",
|
|
1446
|
+
`:"",sn=je?`
|
|
1602
1447
|
const facade = db as unknown as Record<string, ReturnType<typeof bindTableFacade>>;
|
|
1603
|
-
${w.tables.map(
|
|
1448
|
+
${w.tables.map(b=>` facade[${JSON.stringify(b.name)}] = bindTableFacade(db, ${JSON.stringify(b.name)});`).join(`
|
|
1604
1449
|
`)}
|
|
1605
|
-
`:"",
|
|
1450
|
+
`:"",ln=`${de.build}${V.build}${E.build}${J.build}${ce.build}
|
|
1606
1451
|
const secrets = createSecrets(env);
|
|
1607
|
-
`,
|
|
1608
|
-
secrets,`,
|
|
1452
|
+
`,dn=`${de.contextField}${V.contextField}${E.contextField}${Z.contextField}${J.contextField}${ce.contextField}
|
|
1453
|
+
secrets,`,cn=Z.build,et=y||g||u||k||x||v,un=et?`
|
|
1609
1454
|
// ActionCtx-only helpers (external, non-deterministic I/O): constructed
|
|
1610
1455
|
// and attached only for an \`action\` so query/mutation ctx never carry them.
|
|
1611
1456
|
if (isAction) {
|
|
1612
|
-
${
|
|
1457
|
+
${U.build}${K.build}${Q.build}${q.build}${ee.build}${Fe}${[...y?[" ctx.images = images;"]:[],...g?[" ctx.sql = sql;"]:[],...u?[" ctx.browser = browser;"]:[],...k?[" ctx.r2sql = r2sql;"]:[],...x?[" ctx.pipelines = pipelines;"]:[],...v?[" ctx.x402 = x402;"]:[]].join(`
|
|
1613
1458
|
`)}
|
|
1614
1459
|
}
|
|
1615
|
-
`:"",
|
|
1616
|
-
`:"";return`${S}${
|
|
1460
|
+
`:"",pn=et?` const isAction = LUNORA_FUNCTIONS[options.functionPath ?? ""]?.kind === "action";
|
|
1461
|
+
`:"";return`${S}${be.join(`
|
|
1617
1462
|
`)}
|
|
1618
1463
|
|
|
1619
1464
|
type FunctionKind = "action" | "mutation" | "query";
|
|
@@ -1623,83 +1468,47 @@ interface FunctionReference {
|
|
|
1623
1468
|
}
|
|
1624
1469
|
|
|
1625
1470
|
/** Foreign-key columns per table (\`v.id("target")\` fields) for the data browser. */
|
|
1626
|
-
const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(
|
|
1471
|
+
const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(Lt,void 0,4)};
|
|
1627
1472
|
|
|
1628
1473
|
/** Declared indexes per table (secondary, search, geo, rank, vector) for the schema viewer. */
|
|
1629
|
-
const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(
|
|
1474
|
+
const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(Ct,void 0,4)};
|
|
1630
1475
|
|
|
1631
1476
|
/** Columns per table (typed, with PK/FK markers) for the studio's schema diagram, served via \`__lunora_admin__:describeTable\`. */
|
|
1632
|
-
const LUNORA_TABLE_COLUMNS: Record<string, Array<{ isStorage?: boolean; name: string; optional: boolean; pk?: boolean; ref?: string; type: string }>> = ${JSON.stringify(
|
|
1477
|
+
const LUNORA_TABLE_COLUMNS: Record<string, Array<{ isStorage?: boolean; name: string; optional: boolean; pk?: boolean; ref?: string; type: string }>> = ${JSON.stringify(It,void 0,4)};
|
|
1633
1478
|
|
|
1634
1479
|
/** Storage-key columns per table (\`v.storage(...)\` fields) for the file browser's records↔files join. */
|
|
1635
|
-
const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify(
|
|
1480
|
+
const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify(_t,void 0,4)};
|
|
1636
1481
|
|
|
1637
1482
|
/** Declarative TTL policies (\`.ttl(field, { after? })\`) the DO alarm sweep auto-expires rows for. */
|
|
1638
|
-
const LUNORA_TTL_SWEEPS: Array<{ after?: number; field: string; softDeleteField?: string; table: string }> = ${JSON.stringify(
|
|
1483
|
+
const LUNORA_TTL_SWEEPS: Array<{ after?: number; field: string; softDeleteField?: string; table: string }> = ${JSON.stringify(ze,void 0,4)};
|
|
1639
1484
|
|
|
1640
1485
|
/** Static schema advisories (computed by @lunora/advisor at codegen time) served via \`__lunora_admin__:getAdvisories\`. */
|
|
1641
|
-
const LUNORA_ADVISORIES: AdvisoryFinding[] = ${JSON.stringify(
|
|
1486
|
+
const LUNORA_ADVISORIES: AdvisoryFinding[] = ${JSON.stringify(xt,void 0,4)};
|
|
1642
1487
|
|
|
1643
1488
|
/** Every declared procedure (discovered by @lunora/codegen) served via \`__lunora_admin__:getAdvisorProcedures\` — the health map's denominator. */
|
|
1644
|
-
const LUNORA_ADVISOR_PROCEDURES: AdvisorProcedure[] = ${JSON.stringify(
|
|
1489
|
+
const LUNORA_ADVISOR_PROCEDURES: AdvisorProcedure[] = ${JSON.stringify(kt,void 0,4)};
|
|
1645
1490
|
|
|
1646
1491
|
/** Read-only RLS metadata (policies + roles discovered from \`.use(rls(...))\` chains) served via \`__lunora_admin__:rlsPolicies\` for the studio's RLS inspector. */
|
|
1647
|
-
const LUNORA_RLS_METADATA: RlsPoliciesResult = ${JSON.stringify(
|
|
1492
|
+
const LUNORA_RLS_METADATA: RlsPoliciesResult = ${JSON.stringify(vt,void 0,4)};
|
|
1648
1493
|
|
|
1649
1494
|
/** 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. */
|
|
1650
|
-
const LUNORA_MASK_METADATA: MaskPoliciesResult = ${JSON.stringify(
|
|
1495
|
+
const LUNORA_MASK_METADATA: MaskPoliciesResult = ${JSON.stringify($t,void 0,4)};
|
|
1651
1496
|
|
|
1652
1497
|
/** Read-only storage access-rule metadata (discovered from \`.use(storageRules(...))\` chains) served via \`__lunora_admin__:storageRules\` for the studio's access-rules view. */
|
|
1653
|
-
const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(
|
|
1498
|
+
const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(St,void 0,4)};
|
|
1654
1499
|
|
|
1655
1500
|
/** 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. */
|
|
1656
|
-
const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(
|
|
1657
|
-
${
|
|
1501
|
+
const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(Rt,void 0,4)};
|
|
1502
|
+
${j}${H.constant}${Et}${Nt}${Tt}${pe}${_e}${ue}${Pe}
|
|
1658
1503
|
export interface ShardDOConfig {
|
|
1659
1504
|
/** Opt into change-data-capture: records a post-image to \`__cdc_log\` on every write (backs streaming export + replay-PITR). */
|
|
1660
1505
|
cdc?: boolean;
|
|
1661
1506
|
/** 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. */
|
|
1662
1507
|
observability?: (env: Record<string, unknown>) => TelemetrySink | undefined;
|
|
1663
1508
|
scheduler?: (env: Record<string, unknown>) => unknown;
|
|
1664
|
-
storage?: (env: Record<string, unknown>) => unknown;${
|
|
1509
|
+
storage?: (env: Record<string, unknown>) => unknown;${Ft}${Re}${V.configField}${E.configField}${J.configField}${U.configField}${K.configField}${Q.configField}${q.configField}${ee.configField}${Me}${yt}${Bt}${jt}${qt}
|
|
1665
1510
|
}
|
|
1666
|
-
|
|
1667
|
-
const schedulerStub = {
|
|
1668
|
-
cancel: async () => {
|
|
1669
|
-
throw new Error("ctx.scheduler: no scheduler configured. Pass \`scheduler\` to createShardDO().");
|
|
1670
|
-
},
|
|
1671
|
-
runAfter: async () => {
|
|
1672
|
-
throw new Error("ctx.scheduler: no scheduler configured. Pass \`scheduler\` to createShardDO().");
|
|
1673
|
-
},
|
|
1674
|
-
runAt: async () => {
|
|
1675
|
-
throw new Error("ctx.scheduler: no scheduler configured. Pass \`scheduler\` to createShardDO().");
|
|
1676
|
-
},
|
|
1677
|
-
};
|
|
1678
|
-
|
|
1679
|
-
const storageStub = {
|
|
1680
|
-
delete: async () => {
|
|
1681
|
-
throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
|
|
1682
|
-
},
|
|
1683
|
-
download: async () => {
|
|
1684
|
-
throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
|
|
1685
|
-
},
|
|
1686
|
-
getMetadata: async () => {
|
|
1687
|
-
throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
|
|
1688
|
-
},
|
|
1689
|
-
getSignedUrl: async () => {
|
|
1690
|
-
throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
|
|
1691
|
-
},
|
|
1692
|
-
getUrl: () => {
|
|
1693
|
-
throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
|
|
1694
|
-
},
|
|
1695
|
-
list: async () => {
|
|
1696
|
-
throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
|
|
1697
|
-
},
|
|
1698
|
-
upload: async () => {
|
|
1699
|
-
throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
|
|
1700
|
-
},
|
|
1701
|
-
};
|
|
1702
|
-
${Ft}${zt}${qt}${Se}${Q.stub}${E.stub}${V.stub}${W.stub}${U.stub}${K.stub}${B.stub}${Y.stub}${h}${mt}${Vt}
|
|
1511
|
+
${A("schedulerStub",Kt,["cancel","runAfter","runAt"])}${A("storageStub",Qt,["delete","download","getMetadata","getSignedUrl","getUrl","list","upload"],{sync:["getUrl"]})}${Vt}${rn}${Ht}${Ae}${V.stub}${E.stub}${J.stub}${U.stub}${K.stub}${Q.stub}${q.stub}${ee.stub}${p}${wt}
|
|
1703
1512
|
// Bound in-process \`ctx.run*\` composition depth so a self- or cyclically-
|
|
1704
1513
|
// referencing call fails loudly with a clear error instead of overflowing the
|
|
1705
1514
|
// stack. Tracked across the awaited handler chain (one DO invocation is
|
|
@@ -1736,7 +1545,7 @@ const dispatchRun = async (expected: FunctionKind, functionPath: string, args: R
|
|
|
1736
1545
|
* from the worker entry so wrangler binds it by name.
|
|
1737
1546
|
*/
|
|
1738
1547
|
export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOState, env: unknown) => ShardDOBase =>
|
|
1739
|
-
class extends ShardDOBase {${
|
|
1548
|
+
class extends ShardDOBase {${on}
|
|
1740
1549
|
private migrated = false;
|
|
1741
1550
|
|
|
1742
1551
|
public override async handleRpc(functionPath: string, args: Record<string, unknown>, headroom?: TransactionHeadroomTracker): Promise<unknown> {
|
|
@@ -1785,7 +1594,7 @@ export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOSt
|
|
|
1785
1594
|
|
|
1786
1595
|
return registered.handler(ctx, args);
|
|
1787
1596
|
}
|
|
1788
|
-
${
|
|
1597
|
+
${Xe.override}
|
|
1789
1598
|
protected override async executeSubscription(functionPath: string, args: Record<string, unknown>, identity?: { identity?: Record<string, unknown>; userId?: string }): Promise<{ ranges?: Map<string, KeyRange[]>; result: unknown; tables: Set<string> } | null> {
|
|
1790
1599
|
const registered = LUNORA_FUNCTIONS[functionPath];
|
|
1791
1600
|
|
|
@@ -1820,7 +1629,7 @@ ${Ve.override}
|
|
|
1820
1629
|
iterator: (signal) => (registered.handler as (context: unknown, args: Record<string, unknown>, signal: AbortSignal) => AsyncIterable<unknown>)(this.buildCtx({ functionPath }), args, signal),
|
|
1821
1630
|
};
|
|
1822
1631
|
}
|
|
1823
|
-
${
|
|
1632
|
+
${Pt}${Dt}${nn}${an}
|
|
1824
1633
|
protected override lifecycleHookPaths(event: "connect" | "disconnect"): readonly string[] {
|
|
1825
1634
|
return LUNORA_LIFECYCLE_HOOKS[event];
|
|
1826
1635
|
}
|
|
@@ -1860,7 +1669,7 @@ ${Ct}${Lt}${Gt}${Xt}
|
|
|
1860
1669
|
protected override studioFeatures(): StudioFeaturesResult {
|
|
1861
1670
|
return LUNORA_STUDIO_FEATURES;
|
|
1862
1671
|
}
|
|
1863
|
-
${H.evaluateOverride}${H.subscriptionOverride}${
|
|
1672
|
+
${H.evaluateOverride}${H.subscriptionOverride}${At}${Ot}
|
|
1864
1673
|
protected override advisories(): AdvisoryFinding[] {
|
|
1865
1674
|
return LUNORA_ADVISORIES;
|
|
1866
1675
|
}
|
|
@@ -1878,17 +1687,7 @@ ${H.evaluateOverride}${H.subscriptionOverride}${$t}${Rt}
|
|
|
1878
1687
|
|
|
1879
1688
|
this.ensureMigrated();
|
|
1880
1689
|
|
|
1881
|
-
|
|
1882
|
-
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
1883
|
-
const writer = createShardCtxDb({
|
|
1884
|
-
broadcast: (delta) => {
|
|
1885
|
-
this.recordChangedTable(delta.table, delta.indexKeys);
|
|
1886
|
-
},
|
|
1887
|
-
cdc: config.cdc ?? false,
|
|
1888
|
-
scheduler,
|
|
1889
|
-
schema: schema as unknown as SchemaLike,
|
|
1890
|
-
sql: this.sql as SqlExec,
|
|
1891
|
-
});
|
|
1690
|
+
${X}
|
|
1892
1691
|
|
|
1893
1692
|
return runDataMigration({
|
|
1894
1693
|
batchSize: args.batchSize,
|
|
@@ -1921,17 +1720,7 @@ ${H.evaluateOverride}${H.subscriptionOverride}${$t}${Rt}
|
|
|
1921
1720
|
|
|
1922
1721
|
this.ensureMigrated();
|
|
1923
1722
|
|
|
1924
|
-
|
|
1925
|
-
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
1926
|
-
const writer = createShardCtxDb({
|
|
1927
|
-
broadcast: (delta) => {
|
|
1928
|
-
this.recordChangedTable(delta.table, delta.indexKeys);
|
|
1929
|
-
},
|
|
1930
|
-
cdc: config.cdc ?? false,
|
|
1931
|
-
scheduler,
|
|
1932
|
-
schema: schema as unknown as SchemaLike,
|
|
1933
|
-
sql: this.sql as SqlExec,
|
|
1934
|
-
});
|
|
1723
|
+
${X}
|
|
1935
1724
|
|
|
1936
1725
|
if (args.op === "insert") {
|
|
1937
1726
|
const id = await writer.insert(args.table, args.doc ?? {});
|
|
@@ -1975,17 +1764,7 @@ ${H.evaluateOverride}${H.subscriptionOverride}${$t}${Rt}
|
|
|
1975
1764
|
protected override async runShardExport(args: RunShardExportArgs): Promise<ExportRow[]> {
|
|
1976
1765
|
this.ensureMigrated();
|
|
1977
1766
|
|
|
1978
|
-
|
|
1979
|
-
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
1980
|
-
const writer = createShardCtxDb({
|
|
1981
|
-
broadcast: (delta) => {
|
|
1982
|
-
this.recordChangedTable(delta.table, delta.indexKeys);
|
|
1983
|
-
},
|
|
1984
|
-
cdc: config.cdc ?? false,
|
|
1985
|
-
scheduler,
|
|
1986
|
-
schema: schema as unknown as SchemaLike,
|
|
1987
|
-
sql: this.sql as SqlExec,
|
|
1988
|
-
});
|
|
1767
|
+
${X}
|
|
1989
1768
|
|
|
1990
1769
|
const rows: ExportRow[] = [];
|
|
1991
1770
|
|
|
@@ -2002,17 +1781,7 @@ ${H.evaluateOverride}${H.subscriptionOverride}${$t}${Rt}
|
|
|
2002
1781
|
protected override async runShardImport(args: RunShardImportArgs): Promise<ImportShardResult> {
|
|
2003
1782
|
this.ensureMigrated();
|
|
2004
1783
|
|
|
2005
|
-
|
|
2006
|
-
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
2007
|
-
const writer = createShardCtxDb({
|
|
2008
|
-
broadcast: (delta) => {
|
|
2009
|
-
this.recordChangedTable(delta.table, delta.indexKeys);
|
|
2010
|
-
},
|
|
2011
|
-
cdc: config.cdc ?? false,
|
|
2012
|
-
scheduler,
|
|
2013
|
-
schema: schema as unknown as SchemaLike,
|
|
2014
|
-
sql: this.sql as SqlExec,
|
|
2015
|
-
});
|
|
1784
|
+
${X}
|
|
2016
1785
|
|
|
2017
1786
|
// \`importShardRows\` inserts with \`allowExplicitId\`, so a source
|
|
2018
1787
|
// database's \`_id\`s carry across verbatim and every foreign key
|
|
@@ -2063,17 +1832,7 @@ ${H.evaluateOverride}${H.subscriptionOverride}${$t}${Rt}
|
|
|
2063
1832
|
protected override async runShardRankBefore(args: RunShardRankBeforeArgs): Promise<{ before: number; total: number }> {
|
|
2064
1833
|
this.ensureMigrated();
|
|
2065
1834
|
|
|
2066
|
-
|
|
2067
|
-
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
2068
|
-
const writer = createShardCtxDb({
|
|
2069
|
-
broadcast: (delta) => {
|
|
2070
|
-
this.recordChangedTable(delta.table, delta.indexKeys);
|
|
2071
|
-
},
|
|
2072
|
-
cdc: config.cdc ?? false,
|
|
2073
|
-
scheduler,
|
|
2074
|
-
schema: schema as unknown as SchemaLike,
|
|
2075
|
-
sql: this.sql as SqlExec,
|
|
2076
|
-
});
|
|
1835
|
+
${X}
|
|
2077
1836
|
|
|
2078
1837
|
// \`rankBefore\` is optional on \`DatabaseWriterLike\` (the D1 twin omits it),
|
|
2079
1838
|
// but the shard writer from \`createShardCtxDb\` always defines it.
|
|
@@ -2091,17 +1850,7 @@ ${H.evaluateOverride}${H.subscriptionOverride}${$t}${Rt}
|
|
|
2091
1850
|
protected override async runShardRankPage(args: RunShardRankPageArgs): Promise<ShardRankPageResult> {
|
|
2092
1851
|
this.ensureMigrated();
|
|
2093
1852
|
|
|
2094
|
-
|
|
2095
|
-
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
2096
|
-
const writer = createShardCtxDb({
|
|
2097
|
-
broadcast: (delta) => {
|
|
2098
|
-
this.recordChangedTable(delta.table, delta.indexKeys);
|
|
2099
|
-
},
|
|
2100
|
-
cdc: config.cdc ?? false,
|
|
2101
|
-
scheduler,
|
|
2102
|
-
schema: schema as unknown as SchemaLike,
|
|
2103
|
-
sql: this.sql as SqlExec,
|
|
2104
|
-
});
|
|
1853
|
+
${X}
|
|
2105
1854
|
|
|
2106
1855
|
// \`rankPageRows\` is optional on \`DatabaseWriterLike\` (the D1 twin omits it),
|
|
2107
1856
|
// but the shard writer from \`createShardCtxDb\` always defines it. The sort
|
|
@@ -2122,17 +1871,7 @@ ${H.evaluateOverride}${H.subscriptionOverride}${$t}${Rt}
|
|
|
2122
1871
|
protected override async runShardApplyCdc(args: RunShardApplyCdcArgs): Promise<{ applied: number }> {
|
|
2123
1872
|
this.ensureMigrated();
|
|
2124
1873
|
|
|
2125
|
-
|
|
2126
|
-
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
2127
|
-
const writer = createShardCtxDb({
|
|
2128
|
-
broadcast: (delta) => {
|
|
2129
|
-
this.recordChangedTable(delta.table, delta.indexKeys);
|
|
2130
|
-
},
|
|
2131
|
-
cdc: config.cdc ?? false,
|
|
2132
|
-
scheduler,
|
|
2133
|
-
schema: schema as unknown as SchemaLike,
|
|
2134
|
-
sql: this.sql as SqlExec,
|
|
2135
|
-
});
|
|
1874
|
+
${X}
|
|
2136
1875
|
|
|
2137
1876
|
await applyCdcChanges(writer, args.changes);
|
|
2138
1877
|
|
|
@@ -2144,7 +1883,7 @@ ${H.evaluateOverride}${H.subscriptionOverride}${$t}${Rt}
|
|
|
2144
1883
|
return;
|
|
2145
1884
|
}
|
|
2146
1885
|
|
|
2147
|
-
runShardMigrations(this.sql as SqlExec, schema as unknown as SchemaLike, { cdc: config.cdc ?? false${
|
|
1886
|
+
runShardMigrations(this.sql as SqlExec, schema as unknown as SchemaLike, { cdc: config.cdc ?? false${se} });
|
|
2148
1887
|
this.migrated = true;
|
|
2149
1888
|
}
|
|
2150
1889
|
|
|
@@ -2157,7 +1896,7 @@ ${H.evaluateOverride}${H.subscriptionOverride}${$t}${Rt}
|
|
|
2157
1896
|
// dispatch path) fall back to the per-request fields as before.
|
|
2158
1897
|
const userId = options.identity ? options.identity.userId : this.getCurrentUserId();
|
|
2159
1898
|
const identity = options.identity ? options.identity.identity : this.getCurrentIdentity();
|
|
2160
|
-
${
|
|
1899
|
+
${Xt}${le}${ln}${Oe}${Ce}${Te}${De}
|
|
2161
1900
|
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
2162
1901
|
// Build the storage adapter once and share it between \`ctx.storage\`
|
|
2163
1902
|
// and \`ctx.db.system._storage\` so both read the same R2 binding. The
|
|
@@ -2184,13 +1923,13 @@ ${Ut}${oe}${en}${Ne}${Oe}${Re}${Ce}
|
|
|
2184
1923
|
// so both write to the same trace.
|
|
2185
1924
|
const span = this.makeDispatchSpan(traceAnchor, observability);
|
|
2186
1925
|
|
|
2187
|
-
${
|
|
1926
|
+
${tn} // \`ctx.db\`, wrapped in automatic instrumentation: by default this
|
|
2188
1927
|
// adds aggregate counters (call count, total time, per-operation
|
|
2189
1928
|
// breakdown) to the wide event rather than a span per call, so a
|
|
2190
1929
|
// handler making hundreds of queries stays readable. See
|
|
2191
1930
|
// \`instrumentDatabase\` for the \`"spans"\` / \`"off"\` levels.
|
|
2192
|
-
const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${
|
|
2193
|
-
${
|
|
1931
|
+
const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${Yt}), logFunctionPath, traceAnchor, observability);
|
|
1932
|
+
${sn}${Ee}
|
|
2194
1933
|
|
|
2195
1934
|
// \`ctx.trace\` / \`ctx.metrics\`: spans and measurements to the same sink.
|
|
2196
1935
|
// The trace anchor is threaded explicitly for the same reason \`identity\`
|
|
@@ -2198,7 +1937,7 @@ ${Zt}${De}
|
|
|
2198
1937
|
// writing mutation's trace from the shared per-request field.
|
|
2199
1938
|
const trace = this.makeTracer(logFunctionPath, observability, traceAnchor);
|
|
2200
1939
|
const metrics = this.makeMetrics(logFunctionPath, observability);
|
|
2201
|
-
${
|
|
1940
|
+
${cn}
|
|
2202
1941
|
// \`ctx.now\`: the wall-clock instant (epoch ms) this function began,
|
|
2203
1942
|
// captured ONCE so the whole handler body sees a single stable value.
|
|
2204
1943
|
// Query/mutation handlers must be deterministic (they may be re-run on
|
|
@@ -2221,13 +1960,13 @@ ${nn}
|
|
|
2221
1960
|
ip: this.getCurrentIp(),
|
|
2222
1961
|
log,
|
|
2223
1962
|
metrics,
|
|
2224
|
-
now,${
|
|
1963
|
+
now,${en}
|
|
2225
1964
|
scheduler,
|
|
2226
1965
|
span,
|
|
2227
1966
|
storage,
|
|
2228
|
-
trace,${
|
|
1967
|
+
trace,${Zt}${Ne}${dn}${ge}${Le}${Ie}${xe}${he}
|
|
2229
1968
|
};
|
|
2230
|
-
${
|
|
1969
|
+
${pn}${un}
|
|
2231
1970
|
ctx.runAction = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("action", reference.__lunoraRef, fnArgs, ctx);
|
|
2232
1971
|
ctx.runMutation = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("mutation", reference.__lunoraRef, fnArgs, ctx);
|
|
2233
1972
|
ctx.runQuery = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("query", reference.__lunoraRef, fnArgs, ctx);
|
|
@@ -2235,29 +1974,29 @@ ${an}${rn}
|
|
|
2235
1974
|
return ctx;
|
|
2236
1975
|
}
|
|
2237
1976
|
};
|
|
2238
|
-
`},
|
|
1977
|
+
`},Ve=e=>{switch(e.kind){case"array":case"object":case"record":case"union":return{builder:"text",mode:"json",notNull:!0,typeAnnotation:N(e)};case"bigint":return{builder:"blob",mode:"bigint",notNull:!0};case"boolean":return{builder:"integer",mode:"boolean",notNull:!0};case"bytes":return{builder:"blob",mode:"buffer",notNull:!0};case"date":case"timestamp":return{builder:"integer",notNull:!0};case"from":return{builder:"text",notNull:!0,typeAnnotation:N(e)};case"id":return{builder:"text",notNull:!0};case"literal":{const n=e.literalValue??"";return n.startsWith('"')||n.startsWith("'")?{builder:"text",notNull:!0}:n==="true"||n==="false"?{builder:"integer",mode:"boolean",notNull:!0}:n==="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?Ve(e.inner):{builder:"text",notNull:!1},notNull:!1};case"storage":case"string":return{builder:"text",notNull:!0};default:return{builder:"text",notNull:!0}}},ft=(e,n)=>{const t=re(e);return t.kind==="id"&&t.tableName!==void 0&&n.has(t.tableName)?t.tableName:void 0},Nr=(e,n,t)=>{m(e,"drizzle column name");const r=Ve(n),a=r.mode?`, { mode: "${r.mode}" }`:"";let o=`${r.builder}("${e}"${a})`;r.typeAnnotation&&(o+=`.$type<${r.typeAnnotation}>()`);const i=ft(n,t);return i!==void 0&&(o+=`.references((): AnySQLiteColumn => ${i}._id)`),r.notNull&&(o+=".notNull()"),o},Ar=e=>{m(e.name,"drizzle index name");const n=e.unique?"uniqueIndex":"index",t=e.fields.map(r=>(m(r,"drizzle index field"),`t.${r}`)).join(", ");return` ${e.name}: ${n}("${e.name}").on(${t}),`},Tr=(e,n)=>{m(e.name,"table name");const t=[' _id: text("_id").primaryKey(),',' _creationTime: integer("_creationTime").notNull(),',...Object.entries(e.shape).map(([a,o])=>` ${a}: ${Nr(a,o,n)},`)].join(`
|
|
2239
1978
|
`),r=e.indexes.length>0?`, (t) => ({
|
|
2240
|
-
${e.indexes.map(a=>
|
|
1979
|
+
${e.indexes.map(a=>Ar(a)).join(`
|
|
2241
1980
|
`)}
|
|
2242
1981
|
})`:"";return`export const ${e.name} = sqliteTable("${e.name}", {
|
|
2243
|
-
${
|
|
2244
|
-
}${r});`}
|
|
2245
|
-
`;const
|
|
1982
|
+
${t}
|
|
1983
|
+
}${r});`},Or=e=>e.typeAnnotation?.includes('Id<"')??!1,Lr=(e,n)=>{const t=new Set(["integer","sqliteTable","text"]),r=new Set;let a=!1,o=!1;for(const i of e){for(const s of Object.values(i.shape)){const d=Ve(s);t.add(d.builder),o=o||Or(d),a=a||ft(s,n)!==void 0}for(const s of i.indexes)r.add(s.unique?"uniqueIndex":"index")}return{columns:[...t].toSorted((i,s)=>i.localeCompare(s)),indexes:[...r].toSorted((i,s)=>i.localeCompare(s)),needsAnyColumn:a,needsId:o}},nt=(e,n=!1)=>{if(e.length===0)return`${S}export {};
|
|
1984
|
+
`;const t=ne(n),r=new Set(e.map(g=>g.name)),{columns:a,indexes:o,needsAnyColumn:i,needsId:s}=Lr(e,r),d=[...o,...a].toSorted((g,y)=>g.localeCompare(y)),u=e.map(g=>Tr(g,r)).join(`
|
|
2246
1985
|
|
|
2247
|
-
`),
|
|
1986
|
+
`),h=[i?`import type { AnySQLiteColumn } from "${t.serverDrizzle}";
|
|
2248
1987
|
`:"",s?`import type { Id } from "./dataModel.js";
|
|
2249
|
-
`:""].join("");return`${S}import { ${d.join(", ")} } from "${
|
|
2250
|
-
${
|
|
2251
|
-
${u}
|
|
2252
|
-
`},jr=(e,t=!1)=>{const n=e.tables.filter(a=>a.shardMode==="global"),r=e.tables.filter(a=>a.shardMode!=="global");return{global:D(et(n,t),Be),shard:D(et(r,t),Be)}},Wr=e=>{const t=[],n=new Map;for(const s of e){const d=n.get(s.cron);d?d.push(s):(n.set(s.cron,[s]),t.push(s.cron))}const r=t.map(s=>` ${JSON.stringify(s)},`).join(`
|
|
2253
|
-
`),a=r.length>0?`
|
|
2254
|
-
${r}
|
|
2255
|
-
`:"",o=[...n.entries()].map(([s,d])=>{const u=d.map(p=>{const g=p.workflow?`workflow: ${JSON.stringify(p.workflow.binding)}`:`functionPath: ${JSON.stringify(p.functionPath)}`;return` { name: ${JSON.stringify(p.name)}, ${g}, args: ${JSON.stringify(p.args)} },`}).join(`
|
|
2256
|
-
`);return` ${JSON.stringify(s)}: [
|
|
1988
|
+
`:""].join("");return`${S}import { ${d.join(", ")} } from "${t.serverDrizzle}";
|
|
1989
|
+
${h}
|
|
2257
1990
|
${u}
|
|
1991
|
+
`},Hr=(e,n=!1)=>{const t=e.tables.filter(a=>a.shardMode==="global"),r=e.tables.filter(a=>a.shardMode!=="global");return{global:D(nt(t,n),Ue),shard:D(nt(r,n),Ue)}},Jr=e=>{const n=new Map;for(const i of e){const s=n.get(i.cron);s?s.push(i):n.set(i.cron,[i])}const t=[...n.keys()].map(i=>` ${JSON.stringify(i)},`).join(`
|
|
1992
|
+
`),r=t.length>0?`
|
|
1993
|
+
${t}
|
|
1994
|
+
`:"",a=[...n.entries()].map(([i,s])=>{const d=s.map(u=>{const h=u.workflow?`workflow: ${JSON.stringify(u.workflow.binding)}`:`functionPath: ${JSON.stringify(u.functionPath)}`;return` { name: ${JSON.stringify(u.name)}, ${h}, args: ${JSON.stringify(u.args)} },`}).join(`
|
|
1995
|
+
`);return` ${JSON.stringify(i)}: [
|
|
1996
|
+
${d}
|
|
2258
1997
|
],`}).join(`
|
|
2259
|
-
`),
|
|
2260
|
-
${
|
|
1998
|
+
`),o=a.length>0?`
|
|
1999
|
+
${a}
|
|
2261
2000
|
`:"";return`${S}/**
|
|
2262
2001
|
* One scheduled cron invocation. Exactly one target is set: \`functionPath\` is
|
|
2263
2002
|
* the \`namespace:fn\` dispatch ref (matches \`__lunoraRef\`), invoked on the
|
|
@@ -2276,16 +2015,16 @@ export interface LunoraCronJob {
|
|
|
2276
2015
|
* Deduplicated cron schedules — mirror of wrangler's \`triggers.crons\`. The
|
|
2277
2016
|
* Lunora vite plugin keeps \`wrangler.jsonc\` in sync with this array.
|
|
2278
2017
|
*/
|
|
2279
|
-
export const LUNORA_CRON_TRIGGERS: ReadonlyArray<string> = [${
|
|
2018
|
+
export const LUNORA_CRON_TRIGGERS: ReadonlyArray<string> = [${r}];
|
|
2280
2019
|
|
|
2281
2020
|
/**
|
|
2282
2021
|
* Dispatcher map keyed by cron expression. The Worker's \`scheduled()\` handler
|
|
2283
2022
|
* looks up \`event.cron\` here and dispatches every job in the list.
|
|
2284
2023
|
*/
|
|
2285
|
-
export const LUNORA_CRONS: Record<string, ReadonlyArray<LunoraCronJob>> = {${
|
|
2286
|
-
`},
|
|
2287
|
-
`),n
|
|
2288
|
-
${
|
|
2024
|
+
export const LUNORA_CRONS: Record<string, ReadonlyArray<LunoraCronJob>> = {${o}};
|
|
2025
|
+
`},zr=e=>{const n=[...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(`
|
|
2026
|
+
`),t=n.length>0?`
|
|
2027
|
+
${n}
|
|
2289
2028
|
`:"";return`${S}/**
|
|
2290
2029
|
* One vector index declared in \`schema.ts\` — an inline \`.vectorize()\` column
|
|
2291
2030
|
* or a standalone \`defineVectorIndex()\`. \`field\` is the source column (absent
|
|
@@ -2306,5 +2045,5 @@ export interface LunoraVectorIndex {
|
|
|
2306
2045
|
* Vectorize cannot enumerate indexes at runtime, so the worker passes this to
|
|
2307
2046
|
* \`createWorker({ vectorIntrospector })\` to back the studio's vector browser.
|
|
2308
2047
|
*/
|
|
2309
|
-
export const LUNORA_VECTOR_INDEXES: ReadonlyArray<LunoraVectorIndex> = [${
|
|
2310
|
-
`},
|
|
2048
|
+
export const LUNORA_VECTOR_INDEXES: ReadonlyArray<LunoraVectorIndex> = [${t}];
|
|
2049
|
+
`},Gr=e=>[...new Set(e.map(n=>n.cron))];export{Vr as $,Br as B,Hr as C,zr as E,Gr as F,Jr as L,Fr as M,Mr as P,jr as Q,Er as R,S,qr as V,Zn as a,Dn as d,Qr as f,Kr as h,Ur as m,Pr as n,Wr as p,gn as r};
|