@lunora/codegen 1.0.0-alpha.84 → 1.0.0-alpha.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{FLAGS_FILENAME-BiJh08O0.mjs → FLAGS_FILENAME-CHaH6obH.mjs} +1 -1
- package/dist/packem_shared/GENERATED_HEADER-CUBdTCVk.mjs +1 -0
- package/dist/packem_shared/{MUTATORS_FILENAME-9652koWz.mjs → MUTATORS_FILENAME-DY3rgWGl.mjs} +1 -1
- package/dist/packem_shared/{NOTIFY_FILENAME-DeIlwPBu.mjs → NOTIFY_FILENAME-CDvoTY3Y.mjs} +1 -1
- package/dist/packem_shared/{OPENRPC_VERSION-K3RTK2CP.mjs → OPENRPC_VERSION-aq5eyIkd.mjs} +1 -1
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-ChA6rpGP.mjs +9 -0
- package/dist/packem_shared/{SHAPES_FILENAME-Cwn4I4UB.mjs → SHAPES_FILENAME-BdLj5-mD.mjs} +1 -1
- package/dist/packem_shared/{buildOpenApiDocument-Blf3mpIz.mjs → buildOpenApiDocument-Bw3MChvT.mjs} +1 -1
- package/dist/packem_shared/{discover-queries-B4Lw0cEr.mjs → discover-queries-BmZeJ--u.mjs} +1 -1
- package/dist/packem_shared/{discoverAuthApiCalls-CVTXSguP.mjs → discoverAuthApiCalls-BgL6nj03.mjs} +1 -1
- package/dist/packem_shared/{discoverCrons-CZ0_RXUc.mjs → discoverCrons-WJscxQFl.mjs} +1 -1
- package/dist/packem_shared/discoverFunctions-BgGmxEqW.mjs +1 -0
- package/dist/packem_shared/{discoverHttpRoutes-VyBQ9CbN.mjs → discoverHttpRoutes-eW8RbVOr.mjs} +1 -1
- package/dist/packem_shared/{discoverInserts-BGlOx2Cg.mjs → discoverInserts-BCz6zpI0.mjs} +1 -1
- package/dist/packem_shared/{discoverMaskProcedures-DpAT4zsu.mjs → discoverMaskProcedures-DLfQRsQc.mjs} +1 -1
- package/dist/packem_shared/{discoverMigrations-CcOvlTA7.mjs → discoverMigrations-Cbc4W765.mjs} +1 -1
- package/dist/packem_shared/{discoverNondeterministicCalls-CVY5_-x1.mjs → discoverNondeterministicCalls-x9IhWxPP.mjs} +1 -1
- package/dist/packem_shared/discoverQueries-Cf0LGoQG.mjs +1 -0
- package/dist/packem_shared/{discoverR2sqlCalls-BKn9ogOI.mjs → discoverR2sqlCalls--MSfSeDm.mjs} +1 -1
- package/dist/packem_shared/{discoverRlsMetadata-B2iTIbm0.mjs → discoverRlsMetadata-DTRS0ROc.mjs} +1 -1
- package/dist/packem_shared/{discoverSandboxUsage-rkLj3ZC0.mjs → discoverSandboxUsage-BDyeyuYo.mjs} +1 -1
- package/dist/packem_shared/discoverSchema-DSJSX4Ss.mjs +1 -0
- package/dist/packem_shared/{discoverStorageRulesMetadata-AD_GPKdF.mjs → discoverStorageRulesMetadata-Cic97L-2.mjs} +1 -1
- package/dist/packem_shared/{emit-B7IUlWwi.mjs → emit-DMvG162j.mjs} +335 -324
- package/dist/packem_shared/{emitApp-jRD2D9kI.mjs → emitApp--dJ6EnFn.mjs} +1 -1
- package/dist/packem_shared/parse-validator-CkLxY-Mr.mjs +1 -0
- package/package.json +8 -8
- package/dist/packem_shared/GENERATED_HEADER-oy7DTIDi.mjs +0 -1
- package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-DHVrsPNK.mjs +0 -9
- package/dist/packem_shared/discoverFunctions-9GMvSwz7.mjs +0 -1
- package/dist/packem_shared/discoverQueries-BFFoJLOQ.mjs +0 -1
- package/dist/packem_shared/discoverSchema-1zm6abY5.mjs +0 -1
- package/dist/packem_shared/parse-validator-DCrBLhq7.mjs +0 -1
|
@@ -15,89 +15,57 @@ 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"}],ln=nt,dn=new Map(ln.flatMap(e=>e.serverCtxField?[[e.key,e.serverCtxField]]:[])),
|
|
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"}],ln=nt,dn=new Map(ln.flatMap(e=>e.serverCtxField?[[e.key,e.serverCtxField]]:[])),Ar=nt.flatMap(e=>"appMethod"in e?[{appMethod:e.appMethod,key:e.key}]:[]),rt=/^(?:"(?:[^"\\]|\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4}))*"|'[^'\\]*'|-?\d+(?:\.\d+)?|true|false|null)$/u,cn=new Set(["any","bigint","boolean","date","id","null","number","storage","string","timestamp"]),at=e=>e.column!==void 0,un=(e,t)=>{switch(e){case"bigint":return`if (typeof ${t} !== "bigint") return DEFER;
|
|
19
19
|
`;case"boolean":return`if (typeof ${t} !== "boolean") return DEFER;
|
|
20
20
|
`;case"date":case"number":case"timestamp":return`if (typeof ${t} !== "number" || !Number.isFinite(${t})) return DEFER;
|
|
21
21
|
`;case"null":return`if (${t} !== null) return DEFER;
|
|
22
22
|
`;default:return`if (typeof ${t} !== "string") return DEFER;
|
|
23
23
|
`}},pn=(e,t)=>{const n=e.literalValue?.trim();if(!(n===void 0||!rt.test(n)))return{out:t,pre:`if (${t} !== ${n}) return DEFER;
|
|
24
|
-
`}},
|
|
24
|
+
`}},qe=(e,t,n)=>{if(!at(e)&&!(e.hasRefinement||e.sourceText!==void 0)){if(cn.has(e.kind))return e.kind==="any"?{out:t,pre:""}:{out:t,pre:un(e.kind,t)};switch(e.kind){case"array":return hn(e,t,n);case"literal":return pn(e,t);case"object":return mn(e,t,n);default:return}}},hn=(e,t,n)=>{const{inner:r}=e;if(!r)return;const a=n.next(),o=`__arr${String(a)}`,i=`__i${String(a)}`,s=`__e${String(a)}`,d=qe(r,s,n);if(!d)return;const u=`if (!Array.isArray(${t})) return DEFER;
|
|
25
25
|
const ${o} = new Array(${t}.length);
|
|
26
26
|
for (let ${i} = 0; ${i} < ${t}.length; ${i}++) {
|
|
27
27
|
const ${s} = ${t}[${i}];
|
|
28
|
-
${
|
|
28
|
+
${d.pre}${o}[${i}] = ${d.out};
|
|
29
29
|
}
|
|
30
|
-
`;return{out:o,pre:u}},gn=(e,t,n,r)=>{const a=JSON.stringify(e);if(t.kind==="optional"){if(t.hasRefinement||t.sourceText!==void 0||at(t))return;const{inner:i}=t;if(!i)return;const s=
|
|
30
|
+
`;return{out:o,pre:u}},gn=(e,t,n,r)=>{const a=JSON.stringify(e);if(t.kind==="optional"){if(t.hasRefinement||t.sourceText!==void 0||at(t))return;const{inner:i}=t;if(!i)return;const s=qe(i,n,r);if(!s)return;const d=r.next(),u=`__has${String(d)}`,p=`__val${String(d)}`,g=`let ${u} = false;
|
|
31
31
|
let ${p};
|
|
32
32
|
if (${n} !== undefined) {
|
|
33
33
|
${s.pre}${p} = ${s.out};
|
|
34
34
|
${u} = true;
|
|
35
35
|
}
|
|
36
|
-
`;return{entry:`...(${u} ? { ${a}: ${p} } : {})`,pre:
|
|
36
|
+
`;return{entry:`...(${u} ? { ${a}: ${p} } : {})`,pre:g}}const o=qe(t,n,r);if(o)return{entry:`${a}: ${o.out}`,pre:o.pre}},ot=(e,t,n)=>{let r="";const a=[];for(const o of Object.keys(e)){const i=e[o];if(!i)return;const s=gn(o,i,t(o),n);if(!s)return;r+=s.pre,a.push(s.entry)}return{entries:a.join(", "),pre:r}},mn=(e,t,n)=>{const r=e.shape??{},a=ot(r,d=>`${t}[${JSON.stringify(d)}]`,n);if(!a)return;const o=n.next(),i=`__obj${String(o)}`,s=`if (typeof ${t} !== "object" || ${t} === null || Array.isArray(${t})) return DEFER;
|
|
37
37
|
${a.pre}const ${i} = { ${a.entries} };
|
|
38
38
|
`;return{out:i,pre:s}},fn=e=>{let t=0;const n=ot(e,r=>`source[${JSON.stringify(r)}]`,{next:()=>(t+=1,t)});if(n)return`(source) => {
|
|
39
39
|
if (typeof source !== "object" || source === null || Array.isArray(source)) return DEFER;
|
|
40
40
|
${n.pre}return { ${n.entries} };
|
|
41
|
-
}`},
|
|
41
|
+
}`},S=`// GENERATED by @lunora/codegen — do not edit.
|
|
42
42
|
// Run \`lunora codegen\` to regenerate.
|
|
43
43
|
|
|
44
|
-
`,
|
|
44
|
+
`,ee=(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"},st=/^[A-Za-z_$][\w$]*$/u,bn=/^[\w./-]+$/u,m=(e,t)=>{if(!st.test(e))throw new Z("INTERNAL",`@lunora/codegen: ${t} is not a valid JS identifier: ${JSON.stringify(e)}`)},Fe=e=>e.charAt(0).toUpperCase()+e.slice(1),I=e=>st.test(e)?e:JSON.stringify(e),yn={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"},wn=e=>{if(e===void 0)return"unknown";if(!rt.test(e))throw new Z("INTERNAL",`@lunora/codegen: v.literal() argument is not a parseable string/number/boolean/null literal: ${JSON.stringify(e)}`);return e},N=e=>{const t=yn[e.kind];if(t!==void 0)return t;switch(e.kind){case"array":return`Array<${e.inner?N(e.inner):"unknown"}>`;case"from":return e.tsType??"unknown";case"id":{const n=e.tableName??"_unknown_";return m(n,"v.id() table name"),`Id<"${n}">`}case"literal":return wn(e.literalValue);case"object":return e.shape?`{ ${Object.entries(e.shape).map(([n,r])=>it(n,r)).join("; ")} }`:"Record<string, unknown>";case"optional":return`${e.inner?N(e.inner):"unknown"} | undefined`;case"record":{const n=e.keyType?N(e.keyType):"string",r=e.valueType?N(e.valueType):"unknown";return`Record<${n}, ${r}>`}case"union":return e.members&&e.members.length>0?e.members.map(n=>N(n)).join(" | "):"never";default:return"unknown"}},it=(e,t)=>{const n=I(e);if(t.kind==="optional"){const r=t.inner?N(t.inner):"unknown";return`${n}?: ${r}`}return`${n}: ${N(t)}`},fe=e=>{const t=Object.entries(e);return t.length===0?"{}":`{ ${t.map(([n,r])=>it(n,r)).join("; ")} }`},xn=e=>e.kind==="optional"||!!e.column?.hasDefault,kn=e=>{m(e.name,"table name");const t=Object.entries(e.shape).map(([r,a])=>{const o=a.kind==="optional"&&a.inner?a.inner:a,i=N(o),s=I(r);return xn(a)?` ${s}?: ${i};`:` ${s}: ${i};`}).join(`
|
|
45
45
|
`),n=t?`
|
|
46
46
|
${t}
|
|
47
47
|
`:"";return`export interface Insert_${e.name} {
|
|
48
48
|
_id?: Id<"${e.name}">;
|
|
49
|
-
_creationTime?: number;${n}}`},
|
|
50
|
-
`),
|
|
51
|
-
${
|
|
49
|
+
_creationTime?: number;${n}}`},Be="schema",Lr=e=>{for(const c of e.tables)m(c.name,"table name");const t=e.tables.map(c=>`"${c.name}"`).join(" | ")||"never",n=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=I(x);if(k.kind==="optional"){const A=k.inner?N(k.inner):"unknown";return` ${v}?: ${A};`}return` ${v}: ${N(k)};`}).join(`
|
|
50
|
+
`),f=l?`
|
|
51
|
+
${l}
|
|
52
52
|
`:"";return`export interface Doc_${c.name} {
|
|
53
53
|
_id: Id<"${c.name}">;
|
|
54
|
-
_creationTime: number;${
|
|
55
|
-
|
|
56
|
-
`),
|
|
57
|
-
`),
|
|
58
|
-
`),
|
|
59
|
-
`),
|
|
60
|
-
`),
|
|
61
|
-
`),
|
|
62
|
-
|
|
63
|
-
`),
|
|
64
|
-
`),
|
|
65
|
-
`);return
|
|
66
|
-
${
|
|
54
|
+
_creationTime: number;${f}}`}).join(`
|
|
55
|
+
|
|
56
|
+
`),a=e.tables.map(c=>` ${c.name}: Doc_${c.name};`).join(`
|
|
57
|
+
`),o=e.tables.map(c=>{const l=c.indexes.map(f=>JSON.stringify(f.name)).join(" | ");return` ${c.name}: ${l||"never"};`}).join(`
|
|
58
|
+
`),i=e.tables.map(c=>{const l=c.searchIndexes.map(f=>JSON.stringify(f.name)).join(" | ");return` ${c.name}: ${l||"never"};`}).join(`
|
|
59
|
+
`),s=e.tables.map(c=>{const l=c.rankIndexes.map(f=>JSON.stringify(f.name)).join(" | ");return` ${c.name}: ${l||"never"};`}).join(`
|
|
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",p=e.tables.map(c=>kn(c)).join(`
|
|
62
|
+
|
|
63
|
+
`),g=e.tables.map(c=>` ${c.name}: Insert_${c.name};`).join(`
|
|
64
|
+
`),b=e.tables.map(c=>{const l=c.relations.map(f=>(m(f.table,"relation target table"),` ${I(f.name)}: ${f.kind==="one"?"OneRelation":"ManyRelation"}<"${f.table}">;`)).join(`
|
|
65
|
+
`);return l?` ${c.name}: {
|
|
66
|
+
${l}
|
|
67
67
|
};`:` ${c.name}: {};`}).join(`
|
|
68
|
-
`);return`${
|
|
69
|
-
DatabaseReaderFacade as DatabaseReaderFacadeOf,
|
|
70
|
-
DatabaseWriterFacade as DatabaseWriterFacadeOf,
|
|
71
|
-
LoadWith as LoadWithOf,
|
|
72
|
-
TableReaderFacade as TableReaderFacadeOf,
|
|
73
|
-
TableWriterFacade as TableWriterFacadeOf,
|
|
74
|
-
WithArg as WithArgOf,
|
|
75
|
-
} from "${n.serverDataModel}";
|
|
76
|
-
|
|
77
|
-
export type {
|
|
78
|
-
AggregateOp,
|
|
79
|
-
GroupByEntry,
|
|
80
|
-
OrderBy,
|
|
81
|
-
QueryArgs,
|
|
82
|
-
QueryPage,
|
|
83
|
-
RankPage,
|
|
84
|
-
RankResult,
|
|
85
|
-
RestrictableQueryOptions,
|
|
86
|
-
RestrictableQueryOptionsOf,
|
|
87
|
-
SearchFilterBuilder,
|
|
88
|
-
SearchReader,
|
|
89
|
-
TableAggregateOptions,
|
|
90
|
-
TableAggregateOptionsOf,
|
|
91
|
-
TableGroupByOptions,
|
|
92
|
-
TableGroupByOptionsOf,
|
|
93
|
-
TableRankOptions,
|
|
94
|
-
TableRankPageOptions,
|
|
95
|
-
Where,
|
|
96
|
-
WhereOf,
|
|
97
|
-
WhereOperators,
|
|
98
|
-
} from "${n.serverDataModel}";
|
|
99
|
-
|
|
100
|
-
export type TableName = ${r};
|
|
68
|
+
`);return D(`${S}export type TableName = ${t};
|
|
101
69
|
|
|
102
70
|
/**
|
|
103
71
|
* The tables **this app declared** — every {@link TableName} except those an add-on
|
|
@@ -114,14 +82,14 @@ export type TableName = ${r};
|
|
|
114
82
|
* const EXPORTED: readonly AppTableName[] = ["nodes", "tagColors"];
|
|
115
83
|
* \`\`\`
|
|
116
84
|
*/
|
|
117
|
-
export type AppTableName = ${
|
|
85
|
+
export type AppTableName = ${n};
|
|
118
86
|
|
|
119
87
|
export type Id<TName extends string> = string & { readonly __table: TName };
|
|
120
88
|
|
|
121
|
-
${
|
|
89
|
+
${r}
|
|
122
90
|
|
|
123
91
|
export interface DataModel {
|
|
124
|
-
${
|
|
92
|
+
${a}
|
|
125
93
|
}
|
|
126
94
|
|
|
127
95
|
export type Doc<T extends keyof DataModel> = DataModel[T];
|
|
@@ -131,40 +99,40 @@ export type Doc<T extends keyof DataModel> = DataModel[T];
|
|
|
131
99
|
* Used by \`TableReader.withIndex()\` to constrain callers to declared names.
|
|
132
100
|
*/
|
|
133
101
|
export interface IndexNamesByTable {
|
|
134
|
-
${
|
|
102
|
+
${o}
|
|
135
103
|
}
|
|
136
104
|
|
|
137
105
|
export type IndexName<T extends keyof DataModel> = IndexNamesByTable[T];
|
|
138
106
|
|
|
139
107
|
/** Per-table search-index name union. \`never\` for tables without searchIndex. */
|
|
140
108
|
export interface SearchIndexNamesByTable {
|
|
141
|
-
${
|
|
109
|
+
${i}
|
|
142
110
|
}
|
|
143
111
|
|
|
144
112
|
export type SearchIndexName<T extends keyof DataModel> = SearchIndexNamesByTable[T];
|
|
145
113
|
|
|
146
114
|
/** Per-table rank-index name union. \`never\` for tables without a rankIndex. */
|
|
147
115
|
export interface RankIndexNamesByTable {
|
|
148
|
-
${
|
|
116
|
+
${s}
|
|
149
117
|
}
|
|
150
118
|
|
|
151
119
|
export type RankIndexName<T extends keyof DataModel> = RankIndexNamesByTable[T];
|
|
152
120
|
|
|
153
121
|
/** Per-table geo-index name union. \`never\` for tables without a geoIndex. */
|
|
154
122
|
export interface GeoIndexNamesByTable {
|
|
155
|
-
${
|
|
123
|
+
${d}
|
|
156
124
|
}
|
|
157
125
|
|
|
158
126
|
export type GeoIndexName<T extends keyof DataModel> = GeoIndexNamesByTable[T];
|
|
159
127
|
|
|
160
128
|
/** Union of declared vector index names. \`never\` when none are declared. */
|
|
161
|
-
export type VectorIndexName = ${
|
|
129
|
+
export type VectorIndexName = ${u};
|
|
162
130
|
|
|
163
|
-
${
|
|
131
|
+
${p}
|
|
164
132
|
|
|
165
133
|
/** Per-table insert shape, accepted by \`ctx.db.<table>.insert(...)\`. */
|
|
166
134
|
export interface InsertModel {
|
|
167
|
-
${
|
|
135
|
+
${g}
|
|
168
136
|
}
|
|
169
137
|
|
|
170
138
|
export type Insert<T extends keyof DataModel> = InsertModel[T];
|
|
@@ -186,59 +154,14 @@ export interface ManyRelation<Target extends keyof DataModel> {
|
|
|
186
154
|
|
|
187
155
|
/** Per-table relation map keyed by accessor name. \`{}\` for tables with none. */
|
|
188
156
|
export interface Relations {
|
|
189
|
-
${
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/** The \`with\` argument for table \`T\` — see \`@lunora/server/data-model\`. */
|
|
193
|
-
export type WithArg<T extends keyof DataModel> = WithArgOf<DataModel, Relations, T>;
|
|
194
|
-
|
|
195
|
-
/** \`Doc<T>\` narrowed to exactly the relations requested in the with-arg \`W\`. */
|
|
196
|
-
export type LoadWith<T extends keyof DataModel, W> = LoadWithOf<DataModel, Relations, T, W>;
|
|
197
|
-
|
|
198
|
-
/** Read-only typed table accessor exposed on \`QueryCtx.db.<table>\`. */
|
|
199
|
-
export type TableReaderFacade<T extends keyof DataModel> = TableReaderFacadeOf<DataModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, T, GeoIndexNamesByTable>;
|
|
200
|
-
|
|
201
|
-
/** Read-write typed table accessor exposed on \`MutationCtx.db.<table>\` / \`ActionCtx.db.<table>\`. */
|
|
202
|
-
export type TableWriterFacade<T extends keyof DataModel> = TableWriterFacadeOf<DataModel, InsertModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, T, GeoIndexNamesByTable>;
|
|
203
|
-
|
|
204
|
-
/** Per-table read facade — \`ctx.db.<table>\` on a \`QueryCtx\`. */
|
|
205
|
-
export type DatabaseReaderFacade = DatabaseReaderFacadeOf<DataModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, GeoIndexNamesByTable>;
|
|
206
|
-
|
|
207
|
-
/** Per-table read-write facade — \`ctx.db.<table>\` on a \`MutationCtx\` / \`ActionCtx\`. */
|
|
208
|
-
export type DatabaseWriterFacade = DatabaseWriterFacadeOf<DataModel, InsertModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, GeoIndexNamesByTable>;
|
|
209
|
-
|
|
210
|
-
/** Insert builder returned by \`ctx.orm.insert(table)\`. */
|
|
211
|
-
export interface OrmInsertBuilder<T extends keyof DataModel> {
|
|
212
|
-
values: (values: Insert<T>) => Promise<Id<T>>;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/** Replace builder returned by \`ctx.orm.replace(table, id)\` — swaps the whole document. */
|
|
216
|
-
export interface OrmReplaceBuilder<T extends keyof DataModel> {
|
|
217
|
-
with: (values: Insert<T>) => Promise<void>;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/** Update builder returned by \`ctx.orm.update(table, id)\` — patches the named fields. */
|
|
221
|
-
export interface OrmUpdateBuilder<T extends keyof DataModel> {
|
|
222
|
-
set: (values: Partial<Insert<T>>) => Promise<void>;
|
|
157
|
+
${b}
|
|
223
158
|
}
|
|
224
159
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
query: DatabaseReaderFacade;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/** Read-write ORM surface — \`ctx.orm\` on a \`MutationCtx\` / \`ActionCtx\`. Writes are addressed by id, like \`ctx.db\`. */
|
|
231
|
-
export interface OrmWriter extends OrmReader {
|
|
232
|
-
delete: <T extends keyof DataModel>(table: T, id: Id<T>) => Promise<void>;
|
|
233
|
-
insert: <T extends keyof DataModel>(table: T) => OrmInsertBuilder<T>;
|
|
234
|
-
replace: <T extends keyof DataModel>(table: T, id: Id<T>) => OrmReplaceBuilder<T>;
|
|
235
|
-
update: <T extends keyof DataModel>(table: T, id: Id<T>) => OrmUpdateBuilder<T>;
|
|
236
|
-
}
|
|
237
|
-
`},vn=/import\("(?<spec>(?:\.\.?\/)*_generated\/[^"]+)"\)/gu,lt=/^(?:\.\.?\/)*_generated\//u,dt=/\.[A-Za-z]\w*$/u,qe=e=>e.replaceAll(vn,(t,n)=>{const r=n.replace(lt,"./");return`import("${dt.test(r)?r:`${r}.js`}")`}),$n=/import\("(?<spec>\.\.?\/[^"]+)"\)/gu,Sn=/^(?:\.\.?\/)+/u,Rn=e=>{const t=[];for(const n of e.split("/"))if(!(n===""||n===".")){if(n===".."&&t.length>0&&t.at(-1)!==".."){t.pop();continue}t.push(n)}return t.join("/")},Be=(e,t)=>e.replaceAll($n,(n,r)=>{if(lt.test(r.replace(Sn,"")))return n;const a=t.includes("/")?t.slice(0,t.lastIndexOf("/")):"",o=`../${Rn(`${a}/${r}`)}`;return`import("${dt.test(o)?o:`${o}.js`}")`}),Nn=["client","do","errors","flags","observability","platform","ratelimit","runtime","server","values"],On=new RegExp(String.raw`import\("@lunora/(?<pkg>${Nn.join("|")})(?<subpath>/[^"]*)?"\)`,"gu"),Tn={flags:new Set(["/web"]),platform:new Set},ct=(e,t)=>t?e.replaceAll(On,(n,r,a)=>{const o=Tn[r];return a&&o&&!o.has(a)?n:`import("lunorash/${r}${a??""}")`}):e,je=e=>["Doc","Id"].filter(t=>new RegExp(String.raw`\b${t}<`,"u").test(e)),An=e=>e.output===void 0||e.output.kind==="any"?e.returnType:C(e.output),Ze=e=>{const t=new Map;for(const r of e){const a=t.get(r.filePath)??[];a.push(r),t.set(r.filePath,a)}const n=([r,a])=>{const o=a.toSorted((i,s)=>i.exportName.localeCompare(s.exportName)).map(i=>{const s=me(i.args),l=qe(Be(An(i),i.filePath));return` ${i.exportName}: FunctionReference<"${i.kind}", ${s}, ${l}>;`}).join(`
|
|
238
|
-
`);return` ${D(R(r))}: {
|
|
160
|
+
`,Be)},vn=/import\("(?<spec>(?:\.\.?\/)*_generated\/[^"]+)"\)/gu,lt=/^(?:\.\.?\/)*_generated\//u,dt=/\.[A-Za-z]\w*$/u,$n=e=>e.replaceAll(vn,(t,n)=>{const r=n.replace(lt,"./");return`import("${dt.test(r)?r:`${r}.js`}")`}),Sn=/import\("(?<spec>\.\.?\/[^"]+)"\)/gu,Rn=/^(?:\.\.?\/)+/u,Nn=e=>{const t=[];for(const n of e.split("/"))if(!(n===""||n===".")){if(n===".."&&t.length>0&&t.at(-1)!==".."){t.pop();continue}t.push(n)}return t.join("/")},Tn=(e,t)=>e.replaceAll(Sn,(n,r)=>{if(lt.test(r.replace(Rn,"")))return n;const a=t.includes("/")?t.slice(0,t.lastIndexOf("/")):"",o=`../${Nn(`${a}/${r}`)}`;return`import("${dt.test(o)?o:`${o}.js`}")`}),D=(e,t)=>$n(Tn(e,t)),On=["client","do","errors","flags","observability","platform","ratelimit","runtime","server","values"],An=new RegExp(String.raw`import\("@lunora/(?<pkg>${On.join("|")})(?<subpath>/[^"]*)?"\)`,"gu"),Ln={flags:new Set(["/web"]),platform:new Set},ct=(e,t)=>t?e.replaceAll(An,(n,r,a)=>{const o=Ln[r];return a&&o&&!o.has(a)?n:`import("lunorash/${r}${a??""}")`}):e,je=e=>["Doc","Id"].filter(t=>new RegExp(String.raw`\b${t}<`,"u").test(e)),Cn=e=>e.output===void 0||e.output.kind==="any"?e.returnType:N(e.output),Ze=e=>{const t=new Map;for(const r of e){const a=t.get(r.filePath)??[];a.push(r),t.set(r.filePath,a)}const n=([r,a])=>{const o=a.toSorted((i,s)=>i.exportName.localeCompare(s.exportName)).map(i=>{const s=D(fe(i.args),i.filePath),d=D(Cn(i),i.filePath);return` ${i.exportName}: FunctionReference<"${i.kind}", ${s}, ${d}>;`}).join(`
|
|
161
|
+
`);return` ${I(R(r))}: {
|
|
239
162
|
${o}
|
|
240
163
|
};`};return[...t.entries()].toSorted(([r],[a])=>r.localeCompare(a)).map(r=>n(r)).join(`
|
|
241
|
-
`)},
|
|
164
|
+
`)},In=(e,t)=>{if(e.length===0&&t.length===0)return{block:"",importLine:""};const n=[];let r="";if(e.length>0&&(r+="\n/** Params type carried by a `defineWorkflow` definition (its phantom `__params`). */\ntype WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params } ? (unknown extends Params ? Record<string, unknown> : Params) : Record<string, unknown>;\n"),r+=`
|
|
242
165
|
/** A typed reference to a durable workflow, addressable for \`cronJobs()\` targets. Mirrors \`@lunora/scheduler\`'s \`WorkflowReference\` structurally. */
|
|
243
166
|
export interface WorkflowReference<Params = Record<string, unknown>> {
|
|
244
167
|
readonly isLunoraWorkflow: true;
|
|
@@ -246,7 +169,7 @@ export interface WorkflowReference<Params = Record<string, unknown>> {
|
|
|
246
169
|
readonly binding: string;
|
|
247
170
|
readonly name: string;
|
|
248
171
|
}
|
|
249
|
-
`,e.length>0){const a=[...e].toSorted((s,
|
|
172
|
+
`,e.length>0){const a=[...e].toSorted((s,d)=>s.exportName.localeCompare(d.exportName)),o=a.map(s=>` ${s.exportName}: WorkflowReference<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${s.exportName}>>;`).join(`
|
|
250
173
|
`),i=a.map(s=>` ${s.exportName}: { isLunoraWorkflow: true, binding: ${JSON.stringify(s.bindingName)}, name: ${JSON.stringify(s.exportName)} },`).join(`
|
|
251
174
|
`);r+=`
|
|
252
175
|
/** This project's durable workflows, addressable as typed references (e.g. \`crons.daily("digest", …, workflows.digestPipeline, params)\`). */
|
|
@@ -258,7 +181,7 @@ export const workflows: WorkflowsRef = {
|
|
|
258
181
|
${i}
|
|
259
182
|
};
|
|
260
183
|
`,n.push(`import type * as lunoraWorkflowDefinitions from "../workflows.js";
|
|
261
|
-
`)}if(t.length>0){const a=[...t].toSorted((s,
|
|
184
|
+
`)}if(t.length>0){const a=[...t].toSorted((s,d)=>s.exportName.localeCompare(d.exportName)),o=a.map(s=>` ${s.exportName}: WorkflowReference<AgentRunInput>;`).join(`
|
|
262
185
|
`),i=a.map(s=>` ${s.exportName}: { isLunoraWorkflow: true, binding: ${JSON.stringify(s.bindingName)}, name: ${JSON.stringify(s.name)} },`).join(`
|
|
263
186
|
`);r+=`
|
|
264
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 })\`). */
|
|
@@ -270,7 +193,7 @@ export const agents: AgentsRef = {
|
|
|
270
193
|
${i}
|
|
271
194
|
};
|
|
272
195
|
`,n.push(`import type { AgentRunInput } from "@lunora/agent";
|
|
273
|
-
`)}return{block:r,importLine:n.join("")}},
|
|
196
|
+
`)}return{block:r,importLine:n.join("")}},Dn=()=>Object.keys(tt().functions).toSorted((e,t)=>e.localeCompare(t)),ut=e=>new Set(e.filter(t=>R(t.filePath)==="agents").map(t=>t.exportName)),_n=()=>new Set(Object.entries(tt().functions).filter(([,e])=>e.visibility==="internal").map(([e])=>e)),En=(e,t)=>{const n={importLine:"",lines:"",prelude:""};if(e.length===0)return n;const r=ut(t),a=_n(),o=t.find(s=>R(s.filePath)==="agents"&&a.has(s.exportName));if(o)throw new Z("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=Dn().filter(s=>!r.has(s));return i.length===0?n:{importLine:`import { agentComponent } from "@lunora/agent/component";
|
|
274
197
|
`,lines:i.map(s=>` "agents:${s}": lunoraAgentRuntimeFunctions.${s} as unknown as RegisteredLunoraFunction,`).join(`
|
|
275
198
|
`),prelude:`
|
|
276
199
|
/**
|
|
@@ -279,14 +202,14 @@ ${i}
|
|
|
279
202
|
* subscribe to the public queries (\`agents:agentMessages\` is the live thread view).
|
|
280
203
|
*/
|
|
281
204
|
const lunoraAgentRuntimeFunctions = agentComponent().functions;
|
|
282
|
-
`}},
|
|
283
|
-
`,lines:' "sandbox:invoke": lunoraSandbox.invoke as unknown as RegisteredLunoraFunction,',prelude:"\n/**\n * The `@lunora/agent` sandbox dispatcher — auto-registered because `lunora/`\n * imports a sandbox tool (`browserTool`/`containerTool`). The batteries-included\n * tools dispatch to this internal action, which runs on an action ctx carrying\n * `ctx.browser` + `ctx.containers` (the durable tool step itself has neither).\n */\nconst lunoraSandbox = sandboxComponent();\n"}},
|
|
284
|
-
`);return` ${
|
|
285
|
-
${
|
|
205
|
+
`}},Pn=(e,t)=>{if(!e)return{importLine:"",lines:"",prelude:""};const n=t.find(r=>R(r.filePath)==="sandbox"&&r.exportName==="invoke");if(n)throw new Z("INTERNAL",`@lunora/codegen: "sandbox:invoke" is reserved for the batteries-included sandbox tool dispatcher (browserTool/containerTool) — rename the "invoke" export in ${n.filePath}`);return{importLine:`import { sandboxComponent } from "@lunora/agent/component";
|
|
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"}},Mn=(e,t)=>{if(e.length===0)return[];const n=ut(t),r=[{args:{key:{kind:"string"},limit:{inner:{kind:"number"},kind:"optional"}},exportName:"agentMessages",filePath:"agents",kind:"query",returnType:"Record<string, unknown>[]"},{args:{decision:{kind:"union",members:[{kind:"literal",literalValue:'"approve"'},{kind:"literal",literalValue:'"reject"'}]},instanceId:{kind:"string"},note:{inner:{kind:"string"},kind:"optional"},threadKey:{kind:"string"},toolCallId:{kind:"string"}},exportName:"agentResolveApproval",filePath:"agents",kind:"mutation",returnType:"{ resolved: boolean }"},{args:{agent:{kind:"string"},input:{kind:"string"},threadKey:{kind:"string"},title:{inner:{kind:"string"},kind:"optional"}},exportName:"agentRun",filePath:"agents",kind:"mutation",returnType:"{ id: string; threadKey: string }"},{args:{key:{kind:"string"}},exportName:"agentState",filePath:"agents",kind:"query",returnType:"Record<string, unknown> | undefined"},{args:{key:{kind:"string"}},exportName:"agentThread",filePath:"agents",kind:"query",returnType:"Record<string, unknown> | undefined"}];for(const a of e)a.voice&&r.push({args:{threadKey:{kind:"string"}},exportName:`${a.exportName}Voice`,filePath:"agents",kind:"stream",returnType:"Record<string, unknown>"});return r.filter(a=>!n.has(a.exportName))},Fn=(e,t)=>{if(e.length===0)return[];const n=new Set(t.filter(r=>R(r.filePath)==="mutators").map(r=>r.exportName));return e.filter(r=>!n.has(r.exportName)).map(r=>({args:r.args,exportName:r.exportName,filePath:r.filePath,kind:"mutation",returnType:r.returnType}))},qn=e=>{const t=e.filter(i=>i.stream);if(t.length===0)return{block:"",body:""};const n=new Map;for(const i of t){const s=n.get(i.filePath)??[];s.push(i),n.set(i.filePath,s)}const r=[...n.entries()].toSorted(([i],[s])=>i.localeCompare(s)),a=r.map(([i,s])=>{const d=s.map(u=>{const p=D(u.chunkType??"unknown",u.filePath),g=D(fe(u.searchParams),u.filePath),b=D(fe(u.params),u.filePath);return` ${I(u.exportName)}: HttpStreamRef<${p}, ${g}, ${b}>;`}).join(`
|
|
207
|
+
`);return` ${I(R(i))}: {
|
|
208
|
+
${d}
|
|
286
209
|
};`}).join(`
|
|
287
|
-
`),o=r.map(([i,s])=>{const
|
|
288
|
-
`);return` ${
|
|
289
|
-
${
|
|
210
|
+
`),o=r.map(([i,s])=>{const d=s.map(u=>` ${I(u.exportName)}: { method: ${JSON.stringify(u.method)}, path: ${JSON.stringify(u.path)} },`).join(`
|
|
211
|
+
`);return` ${I(R(i))}: {
|
|
212
|
+
${d}
|
|
290
213
|
},`}).join(`
|
|
291
214
|
`);return{block:`
|
|
292
215
|
/** This project's HTTP-SSE stream routes (\`httpRoute.<verb>(path).stream()\`), addressable as typed references for \`client.httpStream\` / \`useHttpStream\`. */
|
|
@@ -297,26 +220,26 @@ ${a}
|
|
|
297
220
|
export const httpStreams: HttpStreamsRef = {
|
|
298
221
|
${o}
|
|
299
222
|
};
|
|
300
|
-
`,body:a}},
|
|
301
|
-
${
|
|
302
|
-
${
|
|
303
|
-
import type { ${
|
|
304
|
-
`:"",
|
|
223
|
+
`,body:a}},Cr=e=>{const{agents:t=[],functions:n,httpRoutes:r=[],mutators:a=[],useUmbrella:o=!1,workflows:i=[]}=e,s=ee(o),d=[...n.filter($=>$.visibility!=="internal"),...Mn(t,n),...Fn(a,n)],u=n.filter($=>$.visibility==="internal"),p=Ze(d),g=Ze(u),b=qn(r),c=`${p}
|
|
224
|
+
${g}
|
|
225
|
+
${b.body}`,l=je(c),f=l.length>0?`
|
|
226
|
+
import type { ${l.join(", ")} } from "./dataModel.js";
|
|
227
|
+
`:"",x=p?`
|
|
305
228
|
${p}
|
|
306
|
-
`:"",
|
|
307
|
-
${
|
|
308
|
-
`:"",
|
|
229
|
+
`:"",k=g?`
|
|
230
|
+
${g}
|
|
231
|
+
`:"",v=In(i,t),A=`export interface ApiTypes {${x}}
|
|
309
232
|
|
|
310
233
|
export const api = anyApi as unknown as ApiTypes;
|
|
311
234
|
|
|
312
235
|
/** Internal functions — callable only server-side via \`ctx.run*\`, never from a client. */
|
|
313
|
-
export interface InternalApiTypes {${
|
|
236
|
+
export interface InternalApiTypes {${k}}
|
|
314
237
|
|
|
315
238
|
export const internal = anyApi as unknown as InternalApiTypes;
|
|
316
|
-
${
|
|
317
|
-
`:"";return ct(`${
|
|
318
|
-
${
|
|
319
|
-
${
|
|
239
|
+
${v.block}${b.block}`,P=[...A.includes("FunctionReference<")?["FunctionReference"]:[],...b.block===""?[]:["HttpStreamRef"]],L=P.length>0?`import type { ${P.join(", ")} } from "${s.client}";
|
|
240
|
+
`:"";return ct(`${S}import { anyApi } from "${s.client}";
|
|
241
|
+
${L}${v.importLine}${f}
|
|
242
|
+
${A}`,o)},Ir=e=>e?`${S}import { createSeedClient as createSeedClientBase } from "@lunora/seed";
|
|
320
243
|
import type { SeedClient, SeedClientOptions } from "@lunora/seed";
|
|
321
244
|
|
|
322
245
|
import schema from "../schema.js";
|
|
@@ -333,9 +256,9 @@ import type { InsertModel } from "./dataModel.js";
|
|
|
333
256
|
* const { posts } = await seed.posts((x) => x([10, 20]));
|
|
334
257
|
*/
|
|
335
258
|
export const createSeedClient = (options?: SeedClientOptions): SeedClient<InsertModel> => createSeedClientBase<InsertModel>(schema, options);
|
|
336
|
-
`:"",
|
|
337
|
-
export interface ${Fe(
|
|
338
|
-
${
|
|
259
|
+
`:"",Dr=(e,t,n=!1)=>{if(e.length===0||!t)return"";const r=ee(n),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),p=D(fe(d.args),d.filePath),g=Object.keys(d.args).length>0,b=g?` args: ${p};`:` args?: ${p};`,c=g?`(args: ${p}) => void`:`(args?: ${p}) => void`,l=`${d.exportName}CollectionOptions`;return`/** Options for the \`${d.exportName}\` shape binding. */
|
|
260
|
+
export interface ${Fe(l)} {
|
|
261
|
+
${b}
|
|
339
262
|
/**
|
|
340
263
|
* Share the optimistic-overlay gate with other collections + mutators on this
|
|
341
264
|
* shard. Defaults to the shared per-shard registry, which is almost always what
|
|
@@ -355,11 +278,11 @@ ${y}
|
|
|
355
278
|
}
|
|
356
279
|
|
|
357
280
|
/**
|
|
358
|
-
* Collection options for the \`${
|
|
281
|
+
* Collection options for the \`${d.exportName}\` replication shape: \`config\` for
|
|
359
282
|
* \`createCollection\`, plus the \`checkpoints\` registry to hand \`bindMutators\` and
|
|
360
283
|
* \`scope\` to re-point the subscription.
|
|
361
284
|
*/
|
|
362
|
-
export const ${
|
|
285
|
+
export const ${d.exportName}CollectionOptions = (options: ${Fe(l)}): LunoraCollectionOptions<${u}> =>
|
|
363
286
|
lunoraCollectionOptions<${u}>({
|
|
364
287
|
client: options.client,
|
|
365
288
|
...(options.checkpoints === undefined ? {} : { checkpoints: options.checkpoints }),
|
|
@@ -367,27 +290,27 @@ export const ${l.exportName}CollectionOptions = (options: ${Fe(d)}): LunoraColle
|
|
|
367
290
|
...(options.load === undefined ? {} : { load: options.load }),
|
|
368
291
|
...(options.onError === undefined ? {} : { onError: options.onError }),
|
|
369
292
|
...(options.shardKey === undefined ? {} : { shardKey: options.shardKey }),
|
|
370
|
-
shape: { args: options.args, name: ${JSON.stringify(
|
|
293
|
+
shape: { args: options.args, name: ${JSON.stringify(d.exportName)}, ...(options.shardKey === undefined ? {} : { shardKey: options.shardKey }) },
|
|
371
294
|
});
|
|
372
295
|
|
|
373
|
-
/** Live collection for the \`${
|
|
374
|
-
export const ${
|
|
375
|
-
options: ${Fe(
|
|
376
|
-
): { checkpoints: CheckpointRegistry; collection: Collection<${u}, string>; scope: ${
|
|
377
|
-
const { checkpoints, config, scope } = ${
|
|
296
|
+
/** Live collection for the \`${d.exportName}\` shape, with its sync controls. */
|
|
297
|
+
export const ${d.exportName}Collection = (
|
|
298
|
+
options: ${Fe(l)},
|
|
299
|
+
): { checkpoints: CheckpointRegistry; collection: Collection<${u}, string>; scope: ${c} } => {
|
|
300
|
+
const { checkpoints, config, scope } = ${d.exportName}CollectionOptions(options);
|
|
378
301
|
|
|
379
302
|
return { checkpoints, collection: createCollection(config), scope };
|
|
380
303
|
};`}).join(`
|
|
381
304
|
|
|
382
305
|
`),i=je(o),s=i.length>0?`import type { ${i.join(", ")} } from "./dataModel.js";
|
|
383
|
-
`:"";return`${
|
|
306
|
+
`:"";return`${S}import type { LunoraClient, SubscriptionError } from "${r.client}";
|
|
384
307
|
import { lunoraCollectionOptions } from "@lunora/db/collections";
|
|
385
308
|
import type { CheckpointRegistry, LunoraCollectionOptions, Row } from "@lunora/db";
|
|
386
309
|
import type { Collection } from "@tanstack/db";
|
|
387
310
|
import { createCollection } from "@tanstack/db";
|
|
388
311
|
${s}
|
|
389
312
|
${o}
|
|
390
|
-
`},
|
|
313
|
+
`},Bn=(e,t)=>`lunora_${R(e)}_${String(t)}`,jn=`const callRegistered = async <R>(context: CallerCtx, functionPath: string, args: Record<string, unknown> | undefined): Promise<R> => {
|
|
391
314
|
const registered = LUNORA_FUNCTIONS[functionPath];
|
|
392
315
|
|
|
393
316
|
if (!registered) {
|
|
@@ -395,45 +318,45 @@ ${o}
|
|
|
395
318
|
}
|
|
396
319
|
|
|
397
320
|
return (await registered.handler(context, args ?? {})) as R;
|
|
398
|
-
};`,
|
|
399
|
-
`),s=e.map(
|
|
400
|
-
`),
|
|
401
|
-
`),u=n.map(
|
|
402
|
-
`),p=r.map(
|
|
403
|
-
`),
|
|
404
|
-
`),
|
|
405
|
-
`);return{dispatchBody:
|
|
406
|
-
${
|
|
321
|
+
};`,Wn=(e,t,n=[],r=[])=>{const a=new Map,o=l=>{a.has(l)||a.set(l,Bn(l,a.size))};for(const l of e)o(l.filePath);for(const l of t)o(l.filePath);for(const l of n)o(l.filePath);for(const l of r)o(l.filePath);const i=[...a.entries()].map(([l,f])=>{if(!bn.test(l))throw new Z("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe file path: ${JSON.stringify(l)}`);return`import * as ${f} from "../${l}.js";`}).join(`
|
|
322
|
+
`),s=e.map(l=>` "${R(l.filePath)}:${l.exportName}": ${a.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredLunoraFunction,`).join(`
|
|
323
|
+
`),d=t.map(l=>` ${JSON.stringify(l.id)}: ${a.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredDataMigration,`).join(`
|
|
324
|
+
`),u=n.map(l=>` "${R(l.filePath)}:${l.exportName}": ${a.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredLunoraFunction,`).join(`
|
|
325
|
+
`),p=r.map(l=>` "${l.exportName}": ${a.get(l.filePath)??""}.${l.exportName} as unknown as RegisteredShape,`).join(`
|
|
326
|
+
`),g=n.map(l=>`${R(l.filePath)}:${l.exportName}`),b=[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=fn(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:b.length>0?`
|
|
329
|
+
${b}
|
|
407
330
|
`:"",importBlock:i.length>0?`${i}
|
|
408
331
|
|
|
409
|
-
`:"",installBlock:
|
|
410
|
-
${
|
|
411
|
-
`:"",mutatorPaths:
|
|
332
|
+
`:"",installBlock:c,migrationBody:d.length>0?`
|
|
333
|
+
${d}
|
|
334
|
+
`:"",mutatorPaths:g,shapeBody:p.length>0?`
|
|
412
335
|
${p}
|
|
413
|
-
`:""}},
|
|
414
|
-
`);return` ${
|
|
336
|
+
`:""}},Un=e=>{const t=new Map;for(const a of e){const o=t.get(a.filePath)??[];o.push(a),t.set(a.filePath,o)}const n=[...t.entries()].toSorted(([a],[o])=>a.localeCompare(o)),r=n.map(([a,o])=>{const i=o.map(s=>{const d=D(fe(s.args),s.filePath),u=d==="{}"?"?":"",p=D(s.returnType,s.filePath);return s.kind==="stream"?` ${s.exportName}: (args${u}: ${d}) => Promise<AsyncIterable<${p}>>;`:` ${s.exportName}: (args${u}: ${d}) => Promise<${p}>;`}).join(`
|
|
337
|
+
`);return` ${I(R(a))}: {
|
|
415
338
|
${i}
|
|
416
339
|
};`}).join(`
|
|
417
|
-
`);return{implementation:n.map(([a,o])=>{const i=R(a),s=o.map(
|
|
418
|
-
`);return` ${
|
|
340
|
+
`);return{implementation:n.map(([a,o])=>{const i=R(a),s=o.map(d=>` ${d.exportName}: (args) => callRegistered(context, "${i}:${d.exportName}", args),`).join(`
|
|
341
|
+
`);return` ${I(i)}: {
|
|
419
342
|
${s}
|
|
420
343
|
},`}).join(`
|
|
421
|
-
`),types:r}},
|
|
422
|
-
`:"",
|
|
423
|
-
readonly ai: LunoraAi;`:"",F=
|
|
424
|
-
`:"",
|
|
425
|
-
readonly payments: LunoraPayment;`:"",
|
|
426
|
-
`:"",
|
|
427
|
-
readonly x402: X402Pay;`:"",
|
|
344
|
+
`),types:r}},Kn=(e,t=[])=>{const n=new Set;for(const r of e.tables)for(const a of Object.values(r.shape)){const o=a.kind==="optional"&&a.inner?a.inner:a;o.kind==="storage"&&typeof o.bucket=="string"&&o.bucket!==""&&n.add(o.bucket)}for(const r of t)r!==""&&r!=="default"&&n.add(r);return["default",...[...n].toSorted((r,a)=>r.localeCompare(a))]},_r=({agents:e=[],containers:t=[],env:n,hasAccessFacade:r=!1,hasAi:a=!1,hasAnalytics:o=!1,hasBrowser:i=!1,hasFlags:s=!1,hasHyperdrive:d=!1,hasImages:u=!1,hasKv:p=!1,hasNotify:g=!1,hasPayments:b=!1,hasPipelines:c=!1,hasR2sql:l=!1,hasX402:f=!1,identity:x,queues:k=[],schema:v,storageRuleBuckets:A=[],useUmbrella:P=!1,workflows:L=[]}={})=>{const $=ee(P),w=Kn(v??{tables:[]},A).map(h=>JSON.stringify(h)).join(" | "),M=a?`import type { LunoraAi } from "@lunora/ai";
|
|
345
|
+
`:"",te=a?`
|
|
346
|
+
readonly ai: LunoraAi;`:"",F=b?`import type { LunoraPayment } from "@lunora/payment";
|
|
347
|
+
`:"",ne=b?`
|
|
348
|
+
readonly payments: LunoraPayment;`:"",re=f?`import type { X402Pay } from "@lunora/x402/pay";
|
|
349
|
+
`:"",j=f?`
|
|
350
|
+
readonly x402: X402Pay;`:"",T=t.length>0?`import type { ContainerAccessor } from "@lunora/container";
|
|
428
351
|
`:"",z=t.length>0?`
|
|
429
352
|
readonly containers: {${t.map(h=>`
|
|
430
353
|
readonly ${h.exportName}: ContainerAccessor;`).join("")}
|
|
431
|
-
};`:"",
|
|
432
|
-
readonly ${h.bindingName}?: unknown;`)),...
|
|
433
|
-
readonly ${h.bindingName}?: unknown;`)),...
|
|
354
|
+
};`:"",O=[...a?[" /** Workers AI binding (the conventional `env.AI`), narrowing `ctx.ai`. */\n readonly AI?: unknown;"]:[],...t.map(h=>(m(h.bindingName,`container binding "${h.bindingName}"`),` /** Durable Object namespace for the \`${h.exportName}\` container. */
|
|
355
|
+
readonly ${h.bindingName}?: unknown;`)),...L.map(h=>(m(h.bindingName,`workflow binding "${h.bindingName}"`),` /** Workflow binding for the \`${h.exportName}\` workflow. */
|
|
356
|
+
readonly ${h.bindingName}?: unknown;`)),...k.map(h=>(m(h.bindingName,`queue binding "${h.bindingName}"`),` /** Queue producer binding for the \`${h.exportName}\` queue. */
|
|
434
357
|
readonly ${h.bindingName}?: unknown;`)),...e.map(h=>(m(h.bindingName,`agent binding "${h.bindingName}"`),` /** Workflow binding for the \`${h.exportName}\` agent. */
|
|
435
358
|
readonly ${h.bindingName}?: unknown;`))].join(`
|
|
436
|
-
`),
|
|
359
|
+
`),C=`
|
|
437
360
|
|
|
438
361
|
/**
|
|
439
362
|
* This project's Cloudflare bindings, as far as codegen can discover them from
|
|
@@ -446,26 +369,26 @@ ${s}
|
|
|
446
369
|
* surface, so treat them as \`Fetcher\`/\`Service<unknown>\` and cast.
|
|
447
370
|
*/
|
|
448
371
|
export interface CloudflareBindings {
|
|
449
|
-
readonly [binding: string]: unknown;${
|
|
450
|
-
${
|
|
372
|
+
readonly [binding: string]: unknown;${O?`
|
|
373
|
+
${O}`:""}
|
|
451
374
|
}
|
|
452
375
|
|
|
453
376
|
/** Alias for {@link CloudflareBindings} — the typed shape of \`env\`. */
|
|
454
|
-
export type Env = CloudflareBindings;`,
|
|
455
|
-
readonly vectors: VectorSearch<VectorIndexName>;`:"",
|
|
456
|
-
readonly vectors: VectorSearchReader<VectorIndexName>;`:"",
|
|
377
|
+
export type Env = CloudflareBindings;`,q=(h,Ee)=>Ee?dn.get(h)?.field??"":"",ae=q("kv",p),oe=q("analytics",o),ve=q("hyperdrive",d),$e=q("browser",i),Se=q("images",u),se=q("pipelines",c),Q=q("r2sql",l),E=(v?.vectorIndexes.length??0)>0,H=E?' | "vectors"':"",X=E?`
|
|
378
|
+
readonly vectors: VectorSearch<VectorIndexName>;`:"",ie=E?`
|
|
379
|
+
readonly vectors: VectorSearchReader<VectorIndexName>;`:"",V=E?`import type { VectorSearch, VectorSearchReader } from "${$.server}";
|
|
457
380
|
import type { VectorIndexName } from "./dataModel.js";
|
|
458
|
-
`:"",
|
|
381
|
+
`:"",W=r?`
|
|
459
382
|
/** Verified Cloudflare Access identity — a synchronous facade over the resolved claims (email / groups / hasGroup / claims). Anonymous when no Access token is present. */
|
|
460
|
-
readonly access: import("@lunora/cloudflare-access/context").AccessFacade;`:"",
|
|
383
|
+
readonly access: import("@lunora/cloudflare-access/context").AccessFacade;`:"",U=s?`
|
|
461
384
|
/** Feature-flag evaluation (OpenFeature). Reads are memoized per request; evaluations never throw — a provider error resolves to the supplied default. */
|
|
462
|
-
readonly flags: import("${
|
|
385
|
+
readonly flags: import("${$.flags}").LunoraFlags;`:"",K=g?`
|
|
463
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. */
|
|
464
387
|
readonly notify: import("@lunora/notify").LunoraNotify;
|
|
465
388
|
/** Device push sub-facade — the same object as ctx.notify.push (register / send / broadcast). Sends belong in action handlers. */
|
|
466
|
-
readonly push: import("@lunora/notify").LunoraPush;`:"",
|
|
389
|
+
readonly push: import("@lunora/notify").LunoraPush;`:"",B=L.length>0,Y=B?`import type { WorkflowHandle } from "@lunora/workflow";
|
|
467
390
|
import type * as lunoraWorkflowDefinitions from "../workflows.js";
|
|
468
|
-
`:"",
|
|
391
|
+
`:"",Re=B?`
|
|
469
392
|
|
|
470
393
|
/** Params type carried by a \`defineWorkflow\` definition (its phantom \`__params\`). */
|
|
471
394
|
type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params }
|
|
@@ -476,43 +399,43 @@ type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params
|
|
|
476
399
|
|
|
477
400
|
/** This project's declared workflows, addressable from \`ctx.workflows\` by their \`lunora/workflows.ts\` export name. */
|
|
478
401
|
export interface LunoraWorkflows {
|
|
479
|
-
${
|
|
402
|
+
${L.map(h=>` get(name: ${JSON.stringify(h.exportName)}): WorkflowHandle<WorkflowParamsOf<typeof lunoraWorkflowDefinitions.${h.exportName}>>;`).join(`
|
|
480
403
|
`)}
|
|
481
|
-
}`:"",
|
|
482
|
-
readonly workflows: LunoraWorkflows;`:"",
|
|
404
|
+
}`:"",be=B?' | "workflows"':"",ye=B?`
|
|
405
|
+
readonly workflows: LunoraWorkflows;`:"",le=k.length>0,Ne=le?`import type { QueueProducer } from "@lunora/queue";
|
|
483
406
|
import type * as lunoraQueueDefinitions from "../queues.js";
|
|
484
|
-
`:"",
|
|
407
|
+
`:"",Te=le?`
|
|
485
408
|
|
|
486
409
|
/** Message body type carried by a \`defineQueue\` definition (its phantom \`__lunoraBody\`). */
|
|
487
410
|
type QueueBodyOf<Definition> = Definition extends { __lunoraBody?: infer Body } ? (unknown extends Body ? unknown : NonNullable<Body>) : unknown;
|
|
488
411
|
|
|
489
412
|
/** This project's declared queues, addressable from \`ctx.queues\` by their \`lunora/queues.ts\` export name. */
|
|
490
413
|
export interface LunoraQueues {
|
|
491
|
-
${
|
|
414
|
+
${k.map(h=>` readonly ${h.exportName}: QueueProducer<QueueBodyOf<typeof lunoraQueueDefinitions.${h.exportName}>>;`).join(`
|
|
492
415
|
`)}
|
|
493
|
-
}`:"",
|
|
494
|
-
readonly queues: LunoraQueues;`:"",
|
|
495
|
-
`:"",
|
|
416
|
+
}`:"",we=le?`
|
|
417
|
+
readonly queues: LunoraQueues;`:"",de=e.length>0,Oe=de?`import type { AgentHandle } from "@lunora/agent";
|
|
418
|
+
`:"",Ae=de?`
|
|
496
419
|
|
|
497
420
|
/** This project's declared agents, addressable from \`ctx.agents\` by their \`lunora/agents.ts\` export name. */
|
|
498
421
|
export interface LunoraAgents {
|
|
499
422
|
${e.map(h=>(m(h.exportName,`agent export "${h.exportName}"`),` readonly ${h.exportName}: AgentHandle;`)).join(`
|
|
500
423
|
`)}
|
|
501
|
-
}`:"",
|
|
502
|
-
readonly agents: LunoraAgents;`:"",
|
|
424
|
+
}`:"",xe=de?`
|
|
425
|
+
readonly agents: LunoraAgents;`:"",Le=x?`import type { InferIdentity } from "${$.server}";
|
|
503
426
|
import type * as lunoraIdentityContract from "../identity.js";
|
|
504
|
-
`:"",
|
|
427
|
+
`:"",Ce=x?`
|
|
505
428
|
|
|
506
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. */
|
|
507
|
-
export type Identity = InferIdentity<typeof lunoraIdentityContract.${
|
|
430
|
+
export type Identity = InferIdentity<typeof lunoraIdentityContract.${x.exportName}>;
|
|
508
431
|
|
|
509
432
|
/** \`ctx.auth\` narrowed so \`getIdentity()\` resolves the declared {@link Identity} contract instead of the untyped claim bag. */
|
|
510
|
-
type NarrowedAuth = Omit<QueryCtxBase["auth"], "getIdentity"> & { getIdentity: () => Promise<Identity | null> };`:"",
|
|
511
|
-
readonly auth: NarrowedAuth;`:"",
|
|
512
|
-
`:"",
|
|
433
|
+
type NarrowedAuth = Omit<QueryCtxBase["auth"], "getIdentity"> & { getIdentity: () => Promise<Identity | null> };`:"",ce=x?' | "auth"':"",ue=x?`
|
|
434
|
+
readonly auth: NarrowedAuth;`:"",Ie=x?", Identity":"",De=n?`import type * as lunoraEnvContract from "../env.js";
|
|
435
|
+
`:"",_e=n?`
|
|
513
436
|
|
|
514
437
|
/** This app's declared env contract (\`defineEnv\` in \`lunora/env.ts\`) — the validated, coercion-aware shape of \`ctx.env\`. */
|
|
515
|
-
export type LunoraEnv = ReturnType<typeof lunoraEnvContract.${n.exportName}>;`:"",
|
|
438
|
+
export type LunoraEnv = ReturnType<typeof lunoraEnvContract.${n.exportName}>;`:"",pe=n?' | "env"':"",he=n?"\n /** Validated, typed environment declared by `defineEnv` in `lunora/env.ts` — parsed & coercion-aware config values (`ctx.env.STRIPE_KEY`); a missing or invalid value throws at read time. */\n readonly env: LunoraEnv;":"";return`${S}import { createPolicyDsl, defineMutator as defineMutatorBase, initLunora, v as vBase } from "${$.server}";
|
|
516
439
|
import type {
|
|
517
440
|
ActionBuilder,
|
|
518
441
|
ActionCtx as ActionCtxBase,
|
|
@@ -533,14 +456,102 @@ import type {
|
|
|
533
456
|
Storage as StorageBase,
|
|
534
457
|
TableReader,
|
|
535
458
|
Validator,
|
|
536
|
-
} from "${
|
|
459
|
+
} from "${$.server}";
|
|
460
|
+
|
|
461
|
+
import type {
|
|
462
|
+
DatabaseReaderFacade as DatabaseReaderFacadeOf,
|
|
463
|
+
DatabaseWriterFacade as DatabaseWriterFacadeOf,
|
|
464
|
+
LoadWith as LoadWithOf,
|
|
465
|
+
TableReaderFacade as TableReaderFacadeOf,
|
|
466
|
+
TableWriterFacade as TableWriterFacadeOf,
|
|
467
|
+
WithArg as WithArgOf,
|
|
468
|
+
} from "${$.serverDataModel}";
|
|
469
|
+
|
|
470
|
+
export type {
|
|
471
|
+
AggregateOp,
|
|
472
|
+
GroupByEntry,
|
|
473
|
+
OrderBy,
|
|
474
|
+
QueryArgs,
|
|
475
|
+
QueryPage,
|
|
476
|
+
RankPage,
|
|
477
|
+
RankResult,
|
|
478
|
+
RestrictableQueryOptions,
|
|
479
|
+
RestrictableQueryOptionsOf,
|
|
480
|
+
SearchFilterBuilder,
|
|
481
|
+
SearchReader,
|
|
482
|
+
TableAggregateOptions,
|
|
483
|
+
TableAggregateOptionsOf,
|
|
484
|
+
TableGroupByOptions,
|
|
485
|
+
TableGroupByOptionsOf,
|
|
486
|
+
TableRankOptions,
|
|
487
|
+
TableRankPageOptions,
|
|
488
|
+
Where,
|
|
489
|
+
WhereOf,
|
|
490
|
+
WhereOperators,
|
|
491
|
+
} from "${$.serverDataModel}";
|
|
537
492
|
|
|
538
|
-
import type { DataModel,
|
|
539
|
-
${
|
|
493
|
+
import type { DataModel, Doc, GeoIndexNamesByTable, Id as IdOfTable, IndexNamesByTable, Insert, InsertModel, RankIndexNamesByTable, Relations, SearchIndexNamesByTable, TableName } from "./dataModel.js";
|
|
494
|
+
${V}${M}${F}${re}${T}${Y}${Ne}${Oe}${Le}${De}
|
|
540
495
|
export type { AppTableName, DataModel, Doc, Id, TableName } from "./dataModel.js";
|
|
541
496
|
|
|
497
|
+
/**
|
|
498
|
+
* The query-DSL bindings: \`@lunora/server/data-model\`'s generics parameterized
|
|
499
|
+
* over this project's \`DataModel\` / \`InsertModel\` / \`Relations\` / index maps.
|
|
500
|
+
*
|
|
501
|
+
* They live here rather than in \`dataModel.ts\` because they are the half that
|
|
502
|
+
* needs the SERVER package. Keeping \`dataModel.ts\` free of it lets a sibling
|
|
503
|
+
* package — a web app, another Worker — compile \`api.ts\` for its \`Doc\`/\`Id\`
|
|
504
|
+
* types without installing a server dependency to do it.
|
|
505
|
+
*/
|
|
506
|
+
|
|
507
|
+
/** The \`with\` argument for table \`T\` — see \`@lunora/server/data-model\`. */
|
|
508
|
+
export type WithArg<T extends keyof DataModel> = WithArgOf<DataModel, Relations, T>;
|
|
509
|
+
|
|
510
|
+
/** \`Doc<T>\` narrowed to exactly the relations requested in the with-arg \`W\`. */
|
|
511
|
+
export type LoadWith<T extends keyof DataModel, W> = LoadWithOf<DataModel, Relations, T, W>;
|
|
512
|
+
|
|
513
|
+
/** Read-only typed table accessor exposed on \`QueryCtx.db.<table>\`. */
|
|
514
|
+
export type TableReaderFacade<T extends keyof DataModel> = TableReaderFacadeOf<DataModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, T, GeoIndexNamesByTable>;
|
|
515
|
+
|
|
516
|
+
/** Read-write typed table accessor exposed on \`MutationCtx.db.<table>\` / \`ActionCtx.db.<table>\`. */
|
|
517
|
+
export type TableWriterFacade<T extends keyof DataModel> = TableWriterFacadeOf<DataModel, InsertModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, T, GeoIndexNamesByTable>;
|
|
518
|
+
|
|
519
|
+
/** Per-table read facade — \`ctx.db.<table>\` on a \`QueryCtx\`. */
|
|
520
|
+
export type DatabaseReaderFacade = DatabaseReaderFacadeOf<DataModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, GeoIndexNamesByTable>;
|
|
521
|
+
|
|
522
|
+
/** Per-table read-write facade — \`ctx.db.<table>\` on a \`MutationCtx\` / \`ActionCtx\`. */
|
|
523
|
+
export type DatabaseWriterFacade = DatabaseWriterFacadeOf<DataModel, InsertModel, Relations, RankIndexNamesByTable, SearchIndexNamesByTable, GeoIndexNamesByTable>;
|
|
524
|
+
|
|
525
|
+
/** Insert builder returned by \`ctx.orm.insert(table)\`. */
|
|
526
|
+
export interface OrmInsertBuilder<T extends keyof DataModel> {
|
|
527
|
+
values: (values: Insert<T>) => Promise<IdOfTable<T>>;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
/** Replace builder returned by \`ctx.orm.replace(table, id)\` — swaps the whole document. */
|
|
531
|
+
export interface OrmReplaceBuilder<T extends keyof DataModel> {
|
|
532
|
+
with: (values: Insert<T>) => Promise<void>;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/** Update builder returned by \`ctx.orm.update(table, id)\` — patches the named fields. */
|
|
536
|
+
export interface OrmUpdateBuilder<T extends keyof DataModel> {
|
|
537
|
+
set: (values: Partial<Insert<T>>) => Promise<void>;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/** Read-only ORM surface — \`ctx.orm\` on a \`QueryCtx\`. Mirrors \`ctx.db\` reads under a kitcn-style \`query\` namespace. */
|
|
541
|
+
export interface OrmReader {
|
|
542
|
+
query: DatabaseReaderFacade;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
/** Read-write ORM surface — \`ctx.orm\` on a \`MutationCtx\` / \`ActionCtx\`. Writes are addressed by id, like \`ctx.db\`. */
|
|
546
|
+
export interface OrmWriter extends OrmReader {
|
|
547
|
+
delete: <T extends keyof DataModel>(table: T, id: IdOfTable<T>) => Promise<void>;
|
|
548
|
+
insert: <T extends keyof DataModel>(table: T) => OrmInsertBuilder<T>;
|
|
549
|
+
replace: <T extends keyof DataModel>(table: T, id: IdOfTable<T>) => OrmReplaceBuilder<T>;
|
|
550
|
+
update: <T extends keyof DataModel>(table: T, id: IdOfTable<T>) => OrmUpdateBuilder<T>;
|
|
551
|
+
}
|
|
552
|
+
|
|
542
553
|
/** Storage buckets this schema declares (\`v.storage("name")\`), narrowing \`ctx.storage.bucket(name)\`. */
|
|
543
|
-
export type StorageBucketName = ${
|
|
554
|
+
export type StorageBucketName = ${w};${C}${Re}${Te}${Ae}${Ce}${_e}
|
|
544
555
|
|
|
545
556
|
/**
|
|
546
557
|
* Project-typed contexts. The base contexts from \`@lunora/server\` are
|
|
@@ -603,22 +614,22 @@ type AsIdTable<T extends string> = T extends TableName ? T : string extends T ?
|
|
|
603
614
|
*/
|
|
604
615
|
type TypedAsId = <T extends string>(tableName: AsIdTable<T>, id: string) => IdOfTable<T & TableName>;
|
|
605
616
|
|
|
606
|
-
export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"${
|
|
617
|
+
export interface QueryCtx extends Omit<QueryCtxBase, "db" | "storage"${H}${ce}${pe}> {
|
|
607
618
|
readonly db: Omit<DatabaseReader, "asId" | "query" | "get"> & DatabaseReaderFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
|
|
608
619
|
readonly orm: OrmReader;
|
|
609
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${
|
|
620
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${ie}${W}${ae}${U}${K}${oe}${he}${ue}
|
|
610
621
|
}
|
|
611
622
|
|
|
612
|
-
export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${
|
|
623
|
+
export interface MutationCtx extends Omit<MutationCtxBase, "db" | "storage"${H}${be}${ce}${pe}> {
|
|
613
624
|
readonly db: Omit<DatabaseWriter, "asId" | "query" | "get"> & DatabaseWriterFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
|
|
614
625
|
readonly orm: OrmWriter;
|
|
615
|
-
readonly storage: ReadOnlyStorage<StorageBucketName>;${X}${
|
|
626
|
+
readonly storage: ReadOnlyStorage<StorageBucketName>;${X}${W}${ae}${U}${K}${oe}${he}${ye}${we}${xe}${ue}
|
|
616
627
|
}
|
|
617
628
|
|
|
618
|
-
export interface ActionCtx extends Omit<ActionCtxBase, "db" | "storage"${
|
|
629
|
+
export interface ActionCtx extends Omit<ActionCtxBase, "db" | "storage"${H}${be}${ce}${pe}> {
|
|
619
630
|
readonly db: Omit<DatabaseWriter, "asId" | "query" | "get"> & DatabaseWriterFacade & { asId: TypedAsId; query: TypedTableQuery; get: TypedTableGet };
|
|
620
631
|
readonly orm: OrmWriter;
|
|
621
|
-
readonly storage: StorageBase<StorageBucketName>;${X}${
|
|
632
|
+
readonly storage: StorageBase<StorageBucketName>;${X}${W}${te}${ne}${j}${z}${ae}${U}${K}${ve}${$e}${Se}${oe}${se}${Q}${he}${ye}${we}${xe}${ue}
|
|
622
633
|
}
|
|
623
634
|
|
|
624
635
|
/**
|
|
@@ -651,7 +662,7 @@ export const internalAction = lunoraBuilders.internalAction as unknown as Intern
|
|
|
651
662
|
/**
|
|
652
663
|
* \`defineMutator\` bound to this project's typed {@link MutationCtx} — declare
|
|
653
664
|
* custom mutators (\`lunora/mutators.ts\`) with it instead of importing from
|
|
654
|
-
* \`${
|
|
665
|
+
* \`${$.server}\`, and the authoritative \`server\` impl's \`ctx\` carries the
|
|
655
666
|
* schema-typed \`ctx.db\` (\`ctx.db.query("nodes")\` resolves \`Doc<"nodes">\`,
|
|
656
667
|
* \`ctx.db.patch(id, …)\` takes an \`Id<"nodes">\`) with no hand-written ctx type and
|
|
657
668
|
* no \`as unknown as\` cast. Runtime-identical to the package export; only the
|
|
@@ -676,7 +687,7 @@ export const defineMutator = defineMutatorBase as unknown as <Args extends Recor
|
|
|
676
687
|
* Runtime-identical to \`@lunora/server\`'s \`definePolicy\`; only the types narrow,
|
|
677
688
|
* so the \`rls()\` chain discovers a policy authored either way the same.
|
|
678
689
|
*/
|
|
679
|
-
export const definePolicy = createPolicyDsl<DataModel, Relations${
|
|
690
|
+
export const definePolicy = createPolicyDsl<DataModel, Relations${Ie}>();
|
|
680
691
|
|
|
681
692
|
/**
|
|
682
693
|
* The validator builder \`v\`, with \`v.id(...)\` constrained to THIS schema's
|
|
@@ -693,45 +704,45 @@ export const definePolicy = createPolicyDsl<DataModel, Relations${Ce}>();
|
|
|
693
704
|
export const v = vBase as unknown as Omit<typeof vBase, "id"> & {
|
|
694
705
|
id: <T extends TableName>(table: T) => ColumnValidator<IdOfTable<T>, IdOfTable<T>>;
|
|
695
706
|
};
|
|
696
|
-
`},
|
|
697
|
-
`);let
|
|
698
|
-
${
|
|
707
|
+
`},Qn=e=>{const t={connect:[],disconnect:[]};for(const n of e)n.lifecycle&&t[n.lifecycle].push(`${R(n.filePath)}:${n.exportName}`);return t},Er=e=>{const{agents:t=[],functions:n,migrations:r=[],mutators:a=[],shapes:o=[],useUmbrella:i=!1,usesSandbox:s=!1}=e,d=n.length>0,u=ee(i),{dispatchBody:p,importBlock:g,installBlock:b,migrationBody:c,mutatorPaths:l,shapeBody:f}=Wn(n,r,a,o),x=En(t,n),k=Pn(s,n),v=[x.lines,k.lines].filter(C=>C.length>0).join(`
|
|
708
|
+
`);let A=p;v.length>0&&(A=p.length>0?`${p.trimEnd()}
|
|
709
|
+
${v}
|
|
699
710
|
`:`
|
|
700
|
-
${
|
|
701
|
-
`);const
|
|
702
|
-
`:""
|
|
711
|
+
${v}
|
|
712
|
+
`);const P=Qn(n),L=o.length>0?`import type { RegisteredShape } from "${u.server}";
|
|
713
|
+
`:"",$=o.length>0?`
|
|
703
714
|
/**
|
|
704
715
|
* Replication-shape registry — one entry per \`defineShape\` in \`lunora/shapes.ts\`.
|
|
705
716
|
* The generated ShardDO's \`resolveShape\` override looks a shape up by name and
|
|
706
717
|
* evaluates its trusted \`compileWhere(ctx, args)\` to authorize + scope a
|
|
707
718
|
* \`shape_subscribe\` (reads-as-permissions).
|
|
708
719
|
*/
|
|
709
|
-
export const LUNORA_SHAPES: Record<string, RegisteredShape> = {${
|
|
710
|
-
`:"",
|
|
720
|
+
export const LUNORA_SHAPES: Record<string, RegisteredShape> = {${f}};
|
|
721
|
+
`:"",w=l.length>0?`
|
|
711
722
|
/**
|
|
712
723
|
* Custom-mutator function paths — the \`LUNORA_FUNCTIONS\` keys the generated
|
|
713
724
|
* ShardDO's \`isCustomMutator\` override routes through the client-watermark push
|
|
714
725
|
* protocol (\`x-lunora-client-id\`/\`x-lunora-client-seq\` ordering).
|
|
715
726
|
*/
|
|
716
|
-
export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${
|
|
717
|
-
`:"",
|
|
718
|
-
`:"",
|
|
727
|
+
export const LUNORA_MUTATOR_PATHS: ReadonlySet<string> = new Set([${l.map(C=>JSON.stringify(C)).join(", ")}]);
|
|
728
|
+
`:"",M=b.length>0?`import { DEFER_VALIDATION as DEFER, installCompiledValidatorMap } from "${u.values}";
|
|
729
|
+
`:"",te=b.length>0?`
|
|
719
730
|
/**
|
|
720
731
|
* AOT-compiled argument validators (Worker-safe, no \`eval\`). Each is installed
|
|
721
732
|
* onto its function's live \`.args\` object and consulted by the interpreted
|
|
722
733
|
* parser as a zero-allocation fast path; anything it can't model is deferred.
|
|
723
734
|
*/
|
|
724
|
-
${
|
|
725
|
-
`:"",F=
|
|
735
|
+
${b}
|
|
736
|
+
`:"",F=Un(n),ne=F.types?`
|
|
726
737
|
${F.types}
|
|
727
|
-
`:"",
|
|
738
|
+
`:"",re=F.implementation?`
|
|
728
739
|
${F.implementation}
|
|
729
|
-
`:"",
|
|
730
|
-
`:"",z=
|
|
740
|
+
`:"",j=je(F.types),T=j.length>0?`import type { ${j.join(", ")} } from "./dataModel.js";
|
|
741
|
+
`:"",z=d?"context":"_context",O=d?`${jn}
|
|
731
742
|
|
|
732
|
-
`:"";return ct(`${
|
|
743
|
+
`:"";return ct(`${S}${g}${x.importLine}${k.importLine}${M}${L}import { LunoraError } from "${u.server}";
|
|
733
744
|
import type { ActionCtx, MutationCtx, QueryCtx } from "./server.js";
|
|
734
|
-
${
|
|
745
|
+
${T}
|
|
735
746
|
/**
|
|
736
747
|
* Single registered function, narrowed to the shape \`handleRpc\` needs.
|
|
737
748
|
* The real argument validators / return types are checked elsewhere — at
|
|
@@ -750,13 +761,13 @@ export interface RegisteredLunoraFunction {
|
|
|
750
761
|
/** \`"internal"\` functions are rejected on the external RPC path; absence === public. */
|
|
751
762
|
visibility?: "internal" | "public";
|
|
752
763
|
}
|
|
753
|
-
${
|
|
764
|
+
${x.prelude}${k.prelude}
|
|
754
765
|
/**
|
|
755
766
|
* Static dispatch table. The key matches the \`__lunoraRef\` the client
|
|
756
767
|
* emits (\`api[namespace][fn].__lunoraRef === "namespace:fn"\`).
|
|
757
768
|
*/
|
|
758
|
-
export const LUNORA_FUNCTIONS: Record<string, RegisteredLunoraFunction> = {${
|
|
759
|
-
${
|
|
769
|
+
export const LUNORA_FUNCTIONS: Record<string, RegisteredLunoraFunction> = {${A}};
|
|
770
|
+
${te}${$}${w}
|
|
760
771
|
/**
|
|
761
772
|
* Connection-lifecycle manifest: the function paths the generated ShardDO
|
|
762
773
|
* dispatches when a client's WebSocket connects (\`connect\`) or disconnects
|
|
@@ -764,8 +775,8 @@ ${ee}${S}${x}
|
|
|
764
775
|
* DO runs every hook under the socket's verified identity via system dispatch.
|
|
765
776
|
*/
|
|
766
777
|
export const LUNORA_LIFECYCLE_HOOKS: { connect: readonly string[]; disconnect: readonly string[] } = {
|
|
767
|
-
connect: [${
|
|
768
|
-
disconnect: [${
|
|
778
|
+
connect: [${P.connect.map(C=>JSON.stringify(C)).join(", ")}],
|
|
779
|
+
disconnect: [${P.disconnect.map(C=>JSON.stringify(C)).join(", ")}],
|
|
769
780
|
};
|
|
770
781
|
|
|
771
782
|
/**
|
|
@@ -796,10 +807,10 @@ export type CallerCtx = ActionCtx | MutationCtx | QueryCtx;
|
|
|
796
807
|
* with the supplied \`context\`, exactly like \`ctx.runQuery\`/\`runMutation\`/
|
|
797
808
|
* \`runAction\` but without re-stating the function path.
|
|
798
809
|
*/
|
|
799
|
-
export interface Caller {${
|
|
810
|
+
export interface Caller {${ne}}
|
|
800
811
|
|
|
801
|
-
${
|
|
802
|
-
export const createCaller = (${z}: CallerCtx): Caller => ({${
|
|
812
|
+
${O}/** Build a {@link Caller} bound to \`context\` (typically a handler's \`ctx\`). */
|
|
813
|
+
export const createCaller = (${z}: CallerCtx): Caller => ({${re}});
|
|
803
814
|
|
|
804
815
|
/**
|
|
805
816
|
* Single registered data migration, narrowed to the shape the per-shard runner
|
|
@@ -818,8 +829,8 @@ export interface RegisteredDataMigration {
|
|
|
818
829
|
* Registry of online data migrations keyed by \`defineMigration\`'s \`id\`. The
|
|
819
830
|
* shard DO's admin RPC and the CLI resolve migrations to run through this map.
|
|
820
831
|
*/
|
|
821
|
-
export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${
|
|
822
|
-
`,i)},
|
|
832
|
+
export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${c}};
|
|
833
|
+
`,i)},Hn=e=>{const t={};for(const n of e.tables){const r={};for(const[a,o]of Object.entries(n.shape)){const i=o.kind==="optional"&&o.inner?o.inner:o;i.kind==="id"&&i.tableName!==void 0&&(r[a]=i.tableName)}Object.keys(r).length>0&&(t[n.name]=r)}return t},Vn=e=>{const t={};for(const n of e.tables){const r=[];for(const[a,o]of Object.entries(n.shape))(o.kind==="optional"&&o.inner?o.inner:o).kind==="storage"&&r.push(a);r.length>0&&(t[n.name]=r)}return t},Jn=e=>{const t={};for(const n of e.tables){const r=[...n.indexes.map(a=>({fields:[...a.fields],name:a.name,type:"index",...a.unique===!0?{unique:!0}:{}})),...n.searchIndexes.map(a=>({fields:[a.field,...a.filterFields??[]],name:a.name,type:"search"})),...(n.geoIndexes??[]).map(a=>({fields:[a.field],name:a.name,type:"geo"})),...n.rankIndexes.map(a=>({fields:a.sortBy.map(o=>o.field),name:a.name,type:"rank"})),...n.vectorIndexes.map(a=>({fields:a.field===void 0?[]:[a.field],name:a.name,type:"vector"}))];r.length>0&&(t[n.name]=r)}return t},Gn=e=>{const t=[];for(const n of e.tables)!n.ttl||n.shardMode==="global"||t.push({...n.ttl.after===void 0?{}:{after:n.ttl.after},field:n.ttl.field,...n.softDelete?{softDeleteField:n.softDelete.field}:{},table:n.name});return t},zn=e=>{const t={};for(const n of e.tables){const r=[{name:"_id",optional:!1,pk:!0,type:"id"},{name:"_creationTime",optional:!1,type:"number"}];for(const[a,o]of Object.entries(n.shape)){const i=o.kind==="optional"||!!o.column?.hasDefault,s=o.kind==="optional"&&o.inner?o.inner: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)}t[n.name]=r}return t},Xn=e=>e?{importFragment:"serveRelationFanout, ",override:`
|
|
823
834
|
protected override async runRelationFanoutRead(functionPath: string, args: Record<string, unknown>): Promise<unknown> {
|
|
824
835
|
this.ensureMigrated();
|
|
825
836
|
|
|
@@ -827,7 +838,7 @@ export const LUNORA_MIGRATIONS: Record<string, RegisteredDataMigration> = {${N}}
|
|
|
827
838
|
|
|
828
839
|
return serveRelationFanout(schema as unknown as SchemaLike, db, functionPath, args);
|
|
829
840
|
}
|
|
830
|
-
`}:{importFragment:"",override:""},
|
|
841
|
+
`}:{importFragment:"",override:""},Yn=e=>{if(!e)return{build:"",configField:"",contextField:"",stub:""};const t='throw new Error("ctx.ai: no AI binding found. Add an \\`ai\\` binding (env.AI) to wrangler.jsonc, or pass \\`ai\\` to createShardDO().");';return{build:`
|
|
831
842
|
const aiBinding = config.ai?.(env) ?? (env as Record<string, unknown>).AI;
|
|
832
843
|
// Correlate AI-Gateway-routed calls with the Lunora trace: thread the
|
|
833
844
|
// function path + trace id into createAi, which folds them into the
|
|
@@ -858,7 +869,7 @@ const aiStub: LunoraAi = {
|
|
|
858
869
|
${t}
|
|
859
870
|
}) as unknown as LunoraAi["workersai"],
|
|
860
871
|
};
|
|
861
|
-
`}},_={build:"",configField:"",contextField:"",importLines:[],stub:""},
|
|
872
|
+
`}},_={build:"",configField:"",contextField:"",importLines:[],stub:""},Zn=e=>{if(!e)return _;const t='throw new Error("ctx.kv: no KV binding found. Add a \\`kv_namespaces\\` binding (env.KV) to wrangler.jsonc, or pass \\`kv\\` to createShardDO().");';return{build:`
|
|
862
873
|
const kvBinding = config.kv?.(env) ?? (env as Record<string, unknown>).KV;
|
|
863
874
|
const kv: Kv = kvBinding ? createKv({ namespace: kvBinding as KVNamespaceLike }) : kvStub;
|
|
864
875
|
`,configField:`
|
|
@@ -884,7 +895,7 @@ const kvStub: Kv = {
|
|
|
884
895
|
${t}
|
|
885
896
|
},
|
|
886
897
|
};
|
|
887
|
-
`}},
|
|
898
|
+
`}},er=(e,t)=>e?{build:`
|
|
888
899
|
const flags: import("${t}").LunoraFlags = createFlags({
|
|
889
900
|
hooks: flagsConfig.hooks,
|
|
890
901
|
logger: flagsConfig.logger,
|
|
@@ -893,17 +904,17 @@ const kvStub: Kv = {
|
|
|
893
904
|
});
|
|
894
905
|
`,configField:`
|
|
895
906
|
flags?: (env: Record<string, unknown>) => import("${t}").Provider;`,contextField:`
|
|
896
|
-
flags,`,importLines:[`import { createFlags } from "${t}";`,'import flagsConfig from "../flags.js";'],stub:""}:_,
|
|
907
|
+
flags,`,importLines:[`import { createFlags } from "${t}";`,'import flagsConfig from "../flags.js";'],stub:""}:_,tr=e=>e?{build:`
|
|
897
908
|
const { notify, push } = createNotify(notifyConfig, env, { log, metrics });
|
|
898
909
|
`,configField:"",contextField:`
|
|
899
910
|
notify,
|
|
900
|
-
push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:_,
|
|
911
|
+
push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:_,nr=e=>e?{build:`
|
|
901
912
|
const envConfig = lunoraEnvContract.${e.exportName}(env);
|
|
902
913
|
`,configField:"",contextField:`
|
|
903
|
-
env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:_,
|
|
914
|
+
env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:_,rr=e=>e?{build:`
|
|
904
915
|
const access = accessFacade(identity, userId);
|
|
905
916
|
`,configField:"",contextField:`
|
|
906
|
-
access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:_,
|
|
917
|
+
access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:_,ar=(e,t,n)=>{if(!t)return{constant:"",evaluateOverride:"",subscriptionOverride:""};const r=s=>`
|
|
907
918
|
const env = (this.env ?? {}) as Record<string, unknown>;
|
|
908
919
|
const flags: import("${n}").LunoraFlags = createFlags({
|
|
909
920
|
hooks: flagsConfig.hooks,
|
|
@@ -967,7 +978,7 @@ const LUNORA_FLAG_KEYS: ReadonlyArray<{ key: string; type: "boolean" | "number"
|
|
|
967
978
|
|
|
968
979
|
return flags.boolean(key, typeof args.default === "boolean" ? args.default : false, context);
|
|
969
980
|
}
|
|
970
|
-
`;return{constant:a,evaluateOverride:o,subscriptionOverride:i}},
|
|
981
|
+
`;return{constant:a,evaluateOverride:o,subscriptionOverride:i}},or=e=>{if(!e)return _;const t='throw new Error("ctx.analytics: no Analytics Engine binding found. Add an \\`analytics_engine_datasets\\` binding (env.ANALYTICS) to wrangler.jsonc, or pass \\`analytics\\` to createShardDO().");';return{build:`
|
|
971
982
|
const analyticsBinding = config.analytics?.(env) ?? (env as Record<string, unknown>).ANALYTICS;
|
|
972
983
|
const analytics: AnalyticsClient = analyticsBinding ? createAnalytics(analyticsBinding as AnalyticsEngineDatasetLike) : analyticsStub;
|
|
973
984
|
`,configField:`
|
|
@@ -981,7 +992,7 @@ const analyticsStub: AnalyticsClient = {
|
|
|
981
992
|
${t}
|
|
982
993
|
},
|
|
983
994
|
};
|
|
984
|
-
`}},
|
|
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:`
|
|
985
996
|
const imagesBinding = config.images?.(env) ?? (env as Record<string, unknown>).IMAGES;
|
|
986
997
|
const images: Images = imagesBinding ? createImages({ binding: imagesBinding as ImagesBindingLike }) : imagesStub;
|
|
987
998
|
`,configField:`
|
|
@@ -995,7 +1006,7 @@ const imagesStub: Images = {
|
|
|
995
1006
|
${t}
|
|
996
1007
|
},
|
|
997
1008
|
};
|
|
998
|
-
`}},
|
|
1009
|
+
`}},ir=e=>e?{build:`
|
|
999
1010
|
const sql: SqlClient = config.sql ? config.sql(env) : sqlStub;
|
|
1000
1011
|
`,configField:`
|
|
1001
1012
|
sql?: (env: Record<string, unknown>) => SqlClient;`,contextField:`
|
|
@@ -1005,7 +1016,7 @@ const sqlStub: SqlClient = {
|
|
|
1005
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))\\\`.");
|
|
1006
1017
|
},
|
|
1007
1018
|
};
|
|
1008
|
-
`}:_,
|
|
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:`
|
|
1009
1020
|
const browser: Browser = config.browser ? config.browser(env) : browserStub;
|
|
1010
1021
|
`,configField:`
|
|
1011
1022
|
browser?: (env: Record<string, unknown>) => Browser;`,contextField:`
|
|
@@ -1033,7 +1044,7 @@ const browserStub: Browser = {
|
|
|
1033
1044
|
${t}
|
|
1034
1045
|
},
|
|
1035
1046
|
};
|
|
1036
|
-
`}},
|
|
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:`
|
|
1037
1048
|
const r2sqlEnv = env as Record<string, unknown>;
|
|
1038
1049
|
const r2sqlAccountId = (r2sqlEnv.R2_SQL_ACCOUNT_ID ?? r2sqlEnv.CLOUDFLARE_ACCOUNT_ID) as string | undefined;
|
|
1039
1050
|
const r2sqlToken = r2sqlEnv.R2_SQL_TOKEN as string | undefined;
|
|
@@ -1065,7 +1076,7 @@ const r2sqlStub: R2SqlClient = {
|
|
|
1065
1076
|
${t}
|
|
1066
1077
|
},
|
|
1067
1078
|
};
|
|
1068
|
-
`}},
|
|
1079
|
+
`}},cr=e=>e?{build:`
|
|
1069
1080
|
const pipelinesBinding = config.pipelines?.(env) ?? (env as Record<string, unknown>).PIPELINES;
|
|
1070
1081
|
const pipelines: PipelineClient = pipelinesBinding ? createPipelines({ binding: pipelinesBinding as PipelineBindingLike }) : pipelinesStub;
|
|
1071
1082
|
`,configField:`
|
|
@@ -1075,14 +1086,14 @@ const pipelinesStub: PipelineClient = {
|
|
|
1075
1086
|
throw new Error("ctx.pipelines: no Pipelines binding found. Add a \\\`pipelines\\\` binding (env.PIPELINES) to wrangler.jsonc, or pass \\\`pipelines\\\` to createShardDO().");
|
|
1076
1087
|
},
|
|
1077
1088
|
};
|
|
1078
|
-
`}:_,
|
|
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}\`). */
|
|
1079
1090
|
export class ${o.className} extends LunoraContainer {
|
|
1080
1091
|
public constructor(ctx: ConstructorParameters<typeof LunoraContainer>[0], env: Record<string, unknown>) {
|
|
1081
1092
|
super(ctx, env, ${o.exportName}, "${o.exportName}"${n});
|
|
1082
1093
|
}
|
|
1083
1094
|
}
|
|
1084
1095
|
`)).join(`
|
|
1085
|
-
`),a=e.map(o=>o.exportName).join(", ");return`${
|
|
1096
|
+
`),a=e.map(o=>o.exportName).join(", ");return`${S}/**
|
|
1086
1097
|
* Container-enabled Durable Object classes for the containers declared in
|
|
1087
1098
|
* \`lunora/containers.ts\`. Re-export them from your worker entry — wrangler
|
|
1088
1099
|
* requires each \`containers[].class_name\` to be exported by the worker:
|
|
@@ -1100,7 +1111,7 @@ import { ${a} } from "../containers.js";
|
|
|
1100
1111
|
|
|
1101
1112
|
export { ContainerProxy } from "@lunora/container/do";
|
|
1102
1113
|
|
|
1103
|
-
${r}`},
|
|
1114
|
+
${r}`},ur=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const r of e)m(r.exportName,`container export "${r.exportName}"`),m(r.bindingName,`container binding "${r.bindingName}"`);const n=e.map(r=>{const a=r.maxInstances===void 0?"":`, maxInstances: ${String(r.maxInstances)}`;return` { binding: "${r.bindingName}", exportName: "${r.exportName}"${a} },`}).join(`
|
|
1104
1115
|
`);return{build:`
|
|
1105
1116
|
const containers = createContainerContext(env, LUNORA_CONTAINERS, ${t?JSON.stringify(t):"undefined"}, this.getCurrentTraceparent());
|
|
1106
1117
|
`,contextField:`
|
|
@@ -1109,14 +1120,14 @@ ${r}`},dr=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[]
|
|
|
1109
1120
|
const LUNORA_CONTAINERS: ReadonlyArray<ContainerBindingSpec> = [
|
|
1110
1121
|
${n}
|
|
1111
1122
|
];
|
|
1112
|
-
`}},
|
|
1123
|
+
`}},Mr=e=>{if(e.length===0)return"";const t=e.map(r=>(m(r.exportName,`workflow export "${r.exportName}"`),m(r.className,`workflow class "${r.className}"`),`/** WorkflowEntrypoint for the \`${r.exportName}\` definition (binding \`${r.bindingName}\`). */
|
|
1113
1124
|
export class ${r.className} extends LunoraWorkflow<WorkflowParamsOf<typeof ${r.exportName}>, WorkflowOutputOf<typeof ${r.exportName}>> {
|
|
1114
1125
|
public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
1115
1126
|
super(ctx, env, ${r.exportName}, "${r.exportName}");
|
|
1116
1127
|
}
|
|
1117
1128
|
}
|
|
1118
1129
|
`)).join(`
|
|
1119
|
-
`),n=e.map(r=>r.exportName).join(", ");return`${
|
|
1130
|
+
`),n=e.map(r=>r.exportName).join(", ");return`${S}/**
|
|
1120
1131
|
* WorkflowEntrypoint classes for the workflows declared in
|
|
1121
1132
|
* \`lunora/workflows.ts\`. Re-export them from your worker entry — wrangler
|
|
1122
1133
|
* requires each \`workflows[].class_name\` to be exported by the worker:
|
|
@@ -1137,21 +1148,21 @@ type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params
|
|
|
1137
1148
|
/** Output type carried by a \`defineWorkflow\` definition (its phantom \`__output\`), so each entrypoint keeps the authored return type. */
|
|
1138
1149
|
type WorkflowOutputOf<Definition> = Definition extends { __output?: infer Output } ? Output : unknown;
|
|
1139
1150
|
|
|
1140
|
-
${t}`},
|
|
1151
|
+
${t}`},Fr=e=>{if(e.length===0)return"";const t=e.filter(a=>a.voice).length>0,n=e.map(a=>{m(a.exportName,`agent export "${a.exportName}"`),m(a.className,`agent class "${a.className}"`);const o=`/** WorkflowEntrypoint for the \`${a.exportName}\` agent (binding \`${a.bindingName}\`). */
|
|
1141
1152
|
export class ${a.className} extends LunoraWorkflow<AgentRunInput, AgentRunResult> {
|
|
1142
1153
|
public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
1143
1154
|
super(ctx, env, compileAgentWorkflow(${a.exportName}, "${a.exportName}"), "${a.exportName}");
|
|
1144
1155
|
}
|
|
1145
1156
|
}
|
|
1146
|
-
`;if(!a.voice)return o;const i=a.voiceClassName??"",s=a.voiceBindingName??"";m(i,`agent voice class "${i}"`);const
|
|
1157
|
+
`;if(!a.voice)return o;const i=a.voiceClassName??"",s=a.voiceBindingName??"";m(i,`agent voice class "${i}"`);const d=`
|
|
1147
1158
|
/** Voice-session Durable Object for the \`${a.exportName}\` agent (binding \`${s}\`). */
|
|
1148
1159
|
export class ${i} extends VoiceSessionDO {
|
|
1149
1160
|
public constructor(ctx: ConstructorParameters<typeof VoiceSessionDO>[0], env: Record<string, unknown>) {
|
|
1150
1161
|
super(ctx, env, ${a.exportName}, "${a.exportName}");
|
|
1151
1162
|
}
|
|
1152
1163
|
}
|
|
1153
|
-
`;return`${o}${
|
|
1154
|
-
`),r=e.map(a=>a.exportName).join(", ");return`${
|
|
1164
|
+
`;return`${o}${d}`}).join(`
|
|
1165
|
+
`),r=e.map(a=>a.exportName).join(", ");return`${S}/**
|
|
1155
1166
|
* WorkflowEntrypoint classes for the agents declared in \`lunora/agents.ts\`.
|
|
1156
1167
|
* Each \`defineAgent\` compiles a replay-safe tool-loop onto a Cloudflare
|
|
1157
1168
|
* Workflow. Re-export them from your worker entry — wrangler requires each
|
|
@@ -1165,8 +1176,8 @@ import type { AgentRunInput, AgentRunResult } from "@lunora/agent";
|
|
|
1165
1176
|
|
|
1166
1177
|
import { ${r} } from "../agents.js";
|
|
1167
1178
|
|
|
1168
|
-
${n}`},
|
|
1169
|
-
`);return`${
|
|
1179
|
+
${n}`},qr=e=>{const t=e.filter(a=>a.mode==="push");if(t.length===0)return"";for(const a of t)m(a.exportName,`queue export "${a.exportName}"`);const n=t.map(a=>a.exportName).join(", "),r=t.map(a=>` ${JSON.stringify(a.name)}: { definition: ${a.exportName}, exportName: ${JSON.stringify(a.exportName)} },`).join(`
|
|
1180
|
+
`);return`${S}/**
|
|
1170
1181
|
* Push-consumer registry for the queues declared in \`lunora/queues.ts\`. The
|
|
1171
1182
|
* composed worker's \`queue(batch, env, ctx)\` entry routes each delivered batch
|
|
1172
1183
|
* by \`batch.queue\` to the matching \`defineQueue\` handler. Wired automatically
|
|
@@ -1180,7 +1191,7 @@ import { ${n} } from "../queues.js";
|
|
|
1180
1191
|
export const LUNORA_QUEUE_REGISTRY: QueueRegistry = {
|
|
1181
1192
|
${r}
|
|
1182
1193
|
};
|
|
1183
|
-
`},
|
|
1194
|
+
`},pr=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`workflow export "${n.exportName}"`),m(n.bindingName,`workflow binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}" },`).join(`
|
|
1184
1195
|
`);return{build:`
|
|
1185
1196
|
const workflows = createWorkflowContext(env, LUNORA_WORKFLOWS);
|
|
1186
1197
|
`,contextField:`
|
|
@@ -1189,7 +1200,7 @@ ${r}
|
|
|
1189
1200
|
const LUNORA_WORKFLOWS: ReadonlyArray<WorkflowBindingSpec> = [
|
|
1190
1201
|
${t}
|
|
1191
1202
|
];
|
|
1192
|
-
`}},
|
|
1203
|
+
`}},hr=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`queue export "${n.exportName}"`),m(n.bindingName,`queue binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}", name: ${JSON.stringify(n.name)} },`).join(`
|
|
1193
1204
|
`);return{build:`
|
|
1194
1205
|
const queues = createQueueContext(env, LUNORA_QUEUES);
|
|
1195
1206
|
`,contextField:`
|
|
@@ -1198,7 +1209,7 @@ ${t}
|
|
|
1198
1209
|
const LUNORA_QUEUES: ReadonlyArray<QueueBindingSpec> = [
|
|
1199
1210
|
${t}
|
|
1200
1211
|
];
|
|
1201
|
-
`}},
|
|
1212
|
+
`}},gr=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)m(n.exportName,`agent export "${n.exportName}"`),m(n.bindingName,`agent binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}"${n.publicRun===!0?", publicRun: true":""} },`).join(`
|
|
1202
1213
|
`);return{build:`
|
|
1203
1214
|
const agents = createAgentContext(env, LUNORA_AGENTS);
|
|
1204
1215
|
`,contextField:`
|
|
@@ -1207,21 +1218,21 @@ ${t}
|
|
|
1207
1218
|
const LUNORA_AGENTS: ReadonlyArray<AgentBindingSpec> = [
|
|
1208
1219
|
${t}
|
|
1209
1220
|
];
|
|
1210
|
-
`}},
|
|
1221
|
+
`}},mr=e=>{if(e.length===0)return{constant:"",override:""};const t={workflows:e.map(n=>({binding:n.bindingName,className:n.className,exportName:n.exportName,name:n.name}))};return{constant:`
|
|
1211
1222
|
/** Read-only declared-workflow metadata (discovered from \`lunora/workflows.ts\`) served via \`__lunora_admin__:listWorkflows\` for the studio's workflows view. */
|
|
1212
1223
|
const LUNORA_WORKFLOWS_INFO: WorkflowsResult = ${JSON.stringify(t,void 0,4)};
|
|
1213
1224
|
`,override:`
|
|
1214
1225
|
protected override workflowsMetadata(): WorkflowsResult {
|
|
1215
1226
|
return LUNORA_WORKFLOWS_INFO;
|
|
1216
1227
|
}
|
|
1217
|
-
`}},
|
|
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:`
|
|
1218
1229
|
/** Read-only declared-queue metadata (discovered from \`lunora/queues.ts\`) served via \`__lunora_admin__:listQueues\` for the studio's queues view. */
|
|
1219
1230
|
const LUNORA_QUEUES_INFO: QueuesResult = ${JSON.stringify(t,void 0,4)};
|
|
1220
1231
|
`,override:`
|
|
1221
1232
|
protected override queuesMetadata(): QueuesResult {
|
|
1222
1233
|
return LUNORA_QUEUES_INFO;
|
|
1223
1234
|
}
|
|
1224
|
-
`}},
|
|
1235
|
+
`}},br=e=>{if(!e)return{build:"",configField:"",contextField:"",imports:[],stub:""};const t='throw new Error("ctx.payments: no payment configured. Pass \\`payment\\` to createShardDO().");';return{imports:['import type { LunoraDatabaseLike as LunoraPaymentDbLike, LunoraPayment, PaymentsFromContextOptions } from "@lunora/payment";','import { paymentsFromContext } from "@lunora/payment";'],build:`
|
|
1225
1236
|
const payments: LunoraPayment = config.payment
|
|
1226
1237
|
? paymentsFromContext({ auth: { userId: userId ?? null }, db: db as unknown as LunoraPaymentDbLike }, config.payment(env))
|
|
1227
1238
|
: paymentStub;
|
|
@@ -1257,7 +1268,7 @@ const paymentStub: LunoraPayment = {
|
|
|
1257
1268
|
${t}
|
|
1258
1269
|
},
|
|
1259
1270
|
} as unknown as LunoraPayment;
|
|
1260
|
-
`}},
|
|
1271
|
+
`}},yr=e=>e?{imports:['import type { X402Pay, X402PayConfig } from "@lunora/x402/pay";','import { lazyX402Pay } from "@lunora/x402/pay";'],build:`
|
|
1261
1272
|
const x402: X402Pay = config.x402
|
|
1262
1273
|
? lazyX402Pay(config.x402(env), { getSecret: (name: string) => secrets.get(name) })
|
|
1263
1274
|
: x402Stub;
|
|
@@ -1269,10 +1280,10 @@ const x402Stub: X402Pay = {
|
|
|
1269
1280
|
throw new Error("ctx.x402: no pay rail configured. Pass \\\`x402\\\` to createShardDO().");
|
|
1270
1281
|
},
|
|
1271
1282
|
} as unknown as X402Pay;
|
|
1272
|
-
`}:{build:"",configField:"",contextField:"",imports:[],stub:""},
|
|
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?"":`
|
|
1273
1284
|
/** 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. */
|
|
1274
|
-
const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(sn(
|
|
1275
|
-
`,
|
|
1285
|
+
const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(sn(M))}, json: ${JSON.stringify(C)} };
|
|
1286
|
+
`,ae=M===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",{build:oe,configField:ve,contextField:$e,stub:Se}=Yn(s),se=rr(i),Q=Zn(c),E=er(p,T.flags),H=ar(o,p,T.flags),X=tr(l),ie=nr(a),V=or(d),W=sr(b),U=ir(g),K=lr(u),B=dr(k),Y=cr(x),{build:Re,contextField:be,importLines:ye,specs:le}=hr(L),{build:Ne,contextField:Te,importLines:we,specs:de}=ur(r,w.jurisdiction),{build:Oe,contextField:Ae,importLines:xe,specs:Le}=pr(j),{build:Ce,contextField:ce,importLines:ue,specs:Ie}=gr(n),{build:De,configField:_e,contextField:pe,imports:he,stub:h}=br(f),{build:Ee,configField:ht,imports:gt,stub:mt}=yr(v),ft=e,bt=t,yt=$??{policies:[],roles:[]},wt=A??{columns:[]},xt=F??{rules:[]},kt=ne??{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:vt,override:$t}=mr(j),{constant:St,override:Rt}=fr(L),J=w.vectorIndexes.length>0,Ue=new Set(w.tables.filter(y=>typeof y.shardMode=="object"&&y.shardMode.kind==="shardBy").map(y=>y.name)),ke=w.vectorIndexes.some(y=>Ue.has(y.table)),ge=w.tables.some(y=>y.shardMode==="global"),Pe=w.tables.some(y=>y.shardMode==="global"&&y.globalBackend==="hyperdrive"),Ke=w.tables.some(y=>y.shardMode==="global"&&y.globalBackend!=="hyperdrive"),G=w.tables.some(y=>y.externalSource!==void 0);if(Ke&&Pe)throw new Z("INTERNAL",'lunora codegen: mixing `.global()` (D1) and `.global({ backend: "hyperdrive" })` tables in one app is not supported yet — use a single global backend.');const Me=w.tables.length>0,Nt=Hn(w),Tt=Jn(w),Ot=zn(w),At=Vn(w),Qe=Gn(w),He=wr(J,j.length>0,L.length>0,p);O&&He.push("WhereInput");const Ve=Xn(ge),Lt=O?`
|
|
1276
1287
|
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 {
|
|
1277
1288
|
const shape = LUNORA_SHAPES[name];
|
|
1278
1289
|
|
|
@@ -1329,11 +1340,11 @@ const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.st
|
|
|
1329
1340
|
protected override isCustomMutator(functionPath: string): boolean {
|
|
1330
1341
|
return LUNORA_MUTATOR_PATHS.has(functionPath);
|
|
1331
1342
|
}
|
|
1332
|
-
`:"",It=
|
|
1343
|
+
`:"",It=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":"",Dt=O?"assertShapeShardable, ":"",me=[`import type { ${He.join(", ")} } from "${T.do}";`,`import { applyCdcChanges, ${Dt}createReadFootprint, createShardCtxDb, exportShardRows, importShardRows, ${G?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}${ke?"ROOT_SHARD_NAME, ":""}runDataMigration, runShardMigrations, ${Ve.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}";`];Me&&me.push(`import { bindOrm, bindTableFacade } from "${T.server}";`),J&&me.push('import type { SchemaLike as VectorSchemaLike, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";','import { createContextVectors, createVectors, createVectorSyncHook } from "@lunora/bindings/vectors";'),s&&me.push('import type { AiBindingLike, LunoraAi } from "@lunora/ai";','import { createAi } from "@lunora/ai";'),me.push(...se.importLines,...Q.importLines,...E.importLines,...X.importLines,...ie.importLines,...V.importLines,...W.importLines,...U.importLines,...K.importLines,...B.importLines,...Y.importLines,...we,...xe,...ye,...ue,...he,...gt,"",'import schema from "../schema.js";',`import { ${["LUNORA_FUNCTIONS","LUNORA_LIFECYCLE_HOOKS","LUNORA_MIGRATIONS",...z?["LUNORA_MUTATOR_PATHS"]:[],...O?["LUNORA_SHAPES"]:[]].join(", ")} } from "./functions.js";`);const _t=J?`
|
|
1333
1344
|
vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",Et=Ke?`
|
|
1334
|
-
d1?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",Pt=
|
|
1335
|
-
hyperdriveGlobal?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",
|
|
1336
|
-
sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",
|
|
1345
|
+
d1?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",Pt=Pe?`
|
|
1346
|
+
hyperdriveGlobal?: (env: Record<string, unknown>, request?: { identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",Mt=G?`
|
|
1347
|
+
sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",Ft=ge?'\nconst globalDbStub: DatabaseWriterLike = {\n aggregate: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n count: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n delete: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findFirst: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findFirstOrThrow: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n findMany: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n get: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n groupBy: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n insert: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n normalizeId: () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n patch: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n query: () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n rank: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n rankPage: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n replace: async () => {\n throw new Error("ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().");\n },\n};\n':"",qt=J?`
|
|
1337
1348
|
const vectorsStub: VectorSearchLike = {
|
|
1338
1349
|
deleteByIds: async () => {
|
|
1339
1350
|
throw new Error("ctx.vectors: no vectors configured. Pass \`vectors\` to createShardDO().");
|
|
@@ -1351,9 +1362,9 @@ const vectorsStub: VectorSearchLike = {
|
|
|
1351
1362
|
throw new Error("ctx.vectors: no vectors configured. Pass \`vectors\` to createShardDO().");
|
|
1352
1363
|
},
|
|
1353
1364
|
};
|
|
1354
|
-
`:"",Bt=
|
|
1365
|
+
`:"",Bt=ke?`
|
|
1355
1366
|
const vectorShardKey = this.currentShardKey();
|
|
1356
|
-
`:"",jt=
|
|
1367
|
+
`:"",jt=ke?"namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, ":"",Wt=ke?`, { namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, shardedIndexNames: [${w.vectorIndexes.filter(y=>Ue.has(y.table)).map(y=>JSON.stringify(y.name)).join(", ")}] }`:"",Ut=J?`
|
|
1357
1368
|
let vectors: VectorSearchLike;
|
|
1358
1369
|
let onWrite: WriteHook | undefined;
|
|
1359
1370
|
|
|
@@ -1366,7 +1377,7 @@ ${Bt}
|
|
|
1366
1377
|
vectors = vectorsStub;
|
|
1367
1378
|
onWrite = undefined;
|
|
1368
1379
|
}
|
|
1369
|
-
`:"",
|
|
1380
|
+
`:"",Je=ge?`
|
|
1370
1381
|
globalDb,`:"",Ge=`
|
|
1371
1382
|
auth: { identity: identity ?? null, userId: userId ?? null },`,Kt=J?`{${Ge}
|
|
1372
1383
|
broadcast: (delta) => {
|
|
@@ -1382,7 +1393,7 @@ ${Bt}
|
|
|
1382
1393
|
scheduler,
|
|
1383
1394
|
schema: schema as unknown as SchemaLike,
|
|
1384
1395
|
sql: this.sql as SqlExec,
|
|
1385
|
-
storage,${
|
|
1396
|
+
storage,${Je}
|
|
1386
1397
|
}`:`{${Ge}
|
|
1387
1398
|
broadcast: (delta) => {
|
|
1388
1399
|
this.recordChangedTable(delta.table, delta.indexKeys);
|
|
@@ -1396,11 +1407,11 @@ ${Bt}
|
|
|
1396
1407
|
scheduler,
|
|
1397
1408
|
schema: schema as unknown as SchemaLike,
|
|
1398
1409
|
sql: this.sql as SqlExec,
|
|
1399
|
-
storage,${
|
|
1410
|
+
storage,${Je}
|
|
1400
1411
|
}`,Qt=J?`
|
|
1401
|
-
vectors,`:"",Ht=
|
|
1402
|
-
orm: bindOrm(facade),`:"",
|
|
1403
|
-
`:"",Gt=
|
|
1412
|
+
vectors,`:"",Ht=Me?`
|
|
1413
|
+
orm: bindOrm(facade),`:"",Vt="",ze=Pe?"config.hyperdriveGlobal":"config.d1",Jt=ge?` const globalDb: DatabaseWriterLike = ${ze}?.(env, { identity, userId }) ?? globalDbStub;
|
|
1414
|
+
`:"",Gt=O&&ge?`
|
|
1404
1415
|
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 }>> {
|
|
1405
1416
|
const env = this.env as Record<string, unknown>;
|
|
1406
1417
|
const globalDb: DatabaseWriterLike = ${ze}?.(env, identity) ?? globalDbStub;
|
|
@@ -1430,10 +1441,10 @@ ${Bt}
|
|
|
1430
1441
|
|
|
1431
1442
|
return rows;
|
|
1432
1443
|
}
|
|
1433
|
-
`:"",zt=
|
|
1444
|
+
`:"",zt=G?`
|
|
1434
1445
|
const sourceClientCache = new WeakMap<object, Map<string, SourceClientLike>>();
|
|
1435
1446
|
const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
|
|
1436
|
-
`:"",Xt=
|
|
1447
|
+
`:"",Xt=G?`
|
|
1437
1448
|
protected override async pollExternalSources(): Promise<number | undefined> {
|
|
1438
1449
|
const env = (this.env ?? {}) as Record<string, unknown>;
|
|
1439
1450
|
const sourced = Object.entries((schema as unknown as SchemaLike).tables)
|
|
@@ -1569,10 +1580,10 @@ const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
|
|
|
1569
1580
|
|
|
1570
1581
|
return nextDueAt;
|
|
1571
1582
|
}
|
|
1572
|
-
`:"",Xe=Qe.length>0,Yt=
|
|
1583
|
+
`:"",Xe=Qe.length>0,Yt=G||Xe?`
|
|
1573
1584
|
public constructor(state: ShardDOState, env: unknown) {
|
|
1574
1585
|
super(state, env);
|
|
1575
|
-
${
|
|
1586
|
+
${G?`
|
|
1576
1587
|
const autoSourced = Object.values((schema as unknown as SchemaLike).tables).some((definition) => {
|
|
1577
1588
|
const source = (definition as { externalSource?: ExternalSourceLike }).externalSource;
|
|
1578
1589
|
|
|
@@ -1587,22 +1598,22 @@ ${V?`
|
|
|
1587
1598
|
void this.scheduleTtlSweep();
|
|
1588
1599
|
}
|
|
1589
1600
|
`:""} }
|
|
1590
|
-
`:"",Zt=
|
|
1601
|
+
`:"",Zt=Me?`
|
|
1591
1602
|
const facade = db as unknown as Record<string, ReturnType<typeof bindTableFacade>>;
|
|
1592
|
-
${
|
|
1603
|
+
${w.tables.map(y=>` facade[${JSON.stringify(y.name)}] = bindTableFacade(db, ${JSON.stringify(y.name)});`).join(`
|
|
1593
1604
|
`)}
|
|
1594
|
-
`:"",en=`${
|
|
1605
|
+
`:"",en=`${se.build}${Q.build}${E.build}${V.build}${ie.build}
|
|
1595
1606
|
const secrets = createSecrets(env);
|
|
1596
|
-
`,tn=`${
|
|
1597
|
-
secrets,`,nn=X.build,Ye=
|
|
1607
|
+
`,tn=`${se.contextField}${Q.contextField}${E.contextField}${X.contextField}${V.contextField}${ie.contextField}
|
|
1608
|
+
secrets,`,nn=X.build,Ye=b||g||u||k||x||v,rn=Ye?`
|
|
1598
1609
|
// ActionCtx-only helpers (external, non-deterministic I/O): constructed
|
|
1599
1610
|
// and attached only for an \`action\` so query/mutation ctx never carry them.
|
|
1600
1611
|
if (isAction) {
|
|
1601
|
-
${
|
|
1612
|
+
${W.build}${U.build}${K.build}${B.build}${Y.build}${Ee}${[...b?[" ctx.images = images;"]:[],...g?[" ctx.sql = sql;"]:[],...u?[" ctx.browser = browser;"]:[],...k?[" ctx.r2sql = r2sql;"]:[],...x?[" ctx.pipelines = pipelines;"]:[],...v?[" ctx.x402 = x402;"]:[]].join(`
|
|
1602
1613
|
`)}
|
|
1603
1614
|
}
|
|
1604
1615
|
`:"",an=Ye?` const isAction = LUNORA_FUNCTIONS[options.functionPath ?? ""]?.kind === "action";
|
|
1605
|
-
`:"";return`${
|
|
1616
|
+
`:"";return`${S}${me.join(`
|
|
1606
1617
|
`)}
|
|
1607
1618
|
|
|
1608
1619
|
type FunctionKind = "action" | "mutation" | "query";
|
|
@@ -1615,10 +1626,10 @@ interface FunctionReference {
|
|
|
1615
1626
|
const LUNORA_TABLE_REFS: Record<string, Record<string, string>> = ${JSON.stringify(Nt,void 0,4)};
|
|
1616
1627
|
|
|
1617
1628
|
/** Declared indexes per table (secondary, search, geo, rank, vector) for the schema viewer. */
|
|
1618
|
-
const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(
|
|
1629
|
+
const LUNORA_TABLE_INDEXES: Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>> = ${JSON.stringify(Tt,void 0,4)};
|
|
1619
1630
|
|
|
1620
1631
|
/** Columns per table (typed, with PK/FK markers) for the studio's schema diagram, served via \`__lunora_admin__:describeTable\`. */
|
|
1621
|
-
const LUNORA_TABLE_COLUMNS: Record<string, Array<{ isStorage?: boolean; name: string; optional: boolean; pk?: boolean; ref?: string; type: string }>> = ${JSON.stringify(
|
|
1632
|
+
const LUNORA_TABLE_COLUMNS: Record<string, Array<{ isStorage?: boolean; name: string; optional: boolean; pk?: boolean; ref?: string; type: string }>> = ${JSON.stringify(Ot,void 0,4)};
|
|
1622
1633
|
|
|
1623
1634
|
/** Storage-key columns per table (\`v.storage(...)\` fields) for the file browser's records↔files join. */
|
|
1624
1635
|
const LUNORA_STORAGE_COLUMNS: Record<string, string[]> = ${JSON.stringify(At,void 0,4)};
|
|
@@ -1643,14 +1654,14 @@ const LUNORA_STORAGE_RULES: StorageRulesResult = ${JSON.stringify(xt,void 0,4)};
|
|
|
1643
1654
|
|
|
1644
1655
|
/** 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. */
|
|
1645
1656
|
const LUNORA_STUDIO_FEATURES: StudioFeaturesResult = ${JSON.stringify(kt,void 0,4)};
|
|
1646
|
-
${
|
|
1657
|
+
${q}${H.constant}${It}${vt}${St}${de}${Le}${le}${Ie}
|
|
1647
1658
|
export interface ShardDOConfig {
|
|
1648
1659
|
/** Opt into change-data-capture: records a post-image to \`__cdc_log\` on every write (backs streaming export + replay-PITR). */
|
|
1649
1660
|
cdc?: boolean;
|
|
1650
1661
|
/** 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. */
|
|
1651
1662
|
observability?: (env: Record<string, unknown>) => TelemetrySink | undefined;
|
|
1652
1663
|
scheduler?: (env: Record<string, unknown>) => unknown;
|
|
1653
|
-
storage?: (env: Record<string, unknown>) => unknown;${_t}${
|
|
1664
|
+
storage?: (env: Record<string, unknown>) => unknown;${_t}${ve}${Q.configField}${E.configField}${V.configField}${W.configField}${U.configField}${K.configField}${B.configField}${Y.configField}${_e}${ht}${Et}${Pt}${Mt}
|
|
1654
1665
|
}
|
|
1655
1666
|
|
|
1656
1667
|
const schedulerStub = {
|
|
@@ -1688,7 +1699,7 @@ const storageStub = {
|
|
|
1688
1699
|
throw new Error("ctx.storage: no storage configured. Pass \`storage\` to createShardDO().");
|
|
1689
1700
|
},
|
|
1690
1701
|
};
|
|
1691
|
-
${
|
|
1702
|
+
${Ft}${zt}${qt}${Se}${Q.stub}${E.stub}${V.stub}${W.stub}${U.stub}${K.stub}${B.stub}${Y.stub}${h}${mt}${Vt}
|
|
1692
1703
|
// Bound in-process \`ctx.run*\` composition depth so a self- or cyclically-
|
|
1693
1704
|
// referencing call fails loudly with a clear error instead of overflowing the
|
|
1694
1705
|
// stack. Tracked across the awaited handler chain (one DO invocation is
|
|
@@ -1774,7 +1785,7 @@ export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOSt
|
|
|
1774
1785
|
|
|
1775
1786
|
return registered.handler(ctx, args);
|
|
1776
1787
|
}
|
|
1777
|
-
${
|
|
1788
|
+
${Ve.override}
|
|
1778
1789
|
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> {
|
|
1779
1790
|
const registered = LUNORA_FUNCTIONS[functionPath];
|
|
1780
1791
|
|
|
@@ -1849,7 +1860,7 @@ ${Ct}${Lt}${Gt}${Xt}
|
|
|
1849
1860
|
protected override studioFeatures(): StudioFeaturesResult {
|
|
1850
1861
|
return LUNORA_STUDIO_FEATURES;
|
|
1851
1862
|
}
|
|
1852
|
-
${
|
|
1863
|
+
${H.evaluateOverride}${H.subscriptionOverride}${$t}${Rt}
|
|
1853
1864
|
protected override advisories(): AdvisoryFinding[] {
|
|
1854
1865
|
return LUNORA_ADVISORIES;
|
|
1855
1866
|
}
|
|
@@ -2133,7 +2144,7 @@ ${Q.evaluateOverride}${Q.subscriptionOverride}${$t}${Rt}
|
|
|
2133
2144
|
return;
|
|
2134
2145
|
}
|
|
2135
2146
|
|
|
2136
|
-
runShardMigrations(this.sql as SqlExec, schema as unknown as SchemaLike, { cdc: config.cdc ?? false${
|
|
2147
|
+
runShardMigrations(this.sql as SqlExec, schema as unknown as SchemaLike, { cdc: config.cdc ?? false${ae} });
|
|
2137
2148
|
this.migrated = true;
|
|
2138
2149
|
}
|
|
2139
2150
|
|
|
@@ -2146,7 +2157,7 @@ ${Q.evaluateOverride}${Q.subscriptionOverride}${$t}${Rt}
|
|
|
2146
2157
|
// dispatch path) fall back to the per-request fields as before.
|
|
2147
2158
|
const userId = options.identity ? options.identity.userId : this.getCurrentUserId();
|
|
2148
2159
|
const identity = options.identity ? options.identity.identity : this.getCurrentIdentity();
|
|
2149
|
-
${Ut}${
|
|
2160
|
+
${Ut}${oe}${en}${Ne}${Oe}${Re}${Ce}
|
|
2150
2161
|
const scheduler = (config.scheduler?.(env) ?? schedulerStub) as SchedulerLike;
|
|
2151
2162
|
// Build the storage adapter once and share it between \`ctx.storage\`
|
|
2152
2163
|
// and \`ctx.db.system._storage\` so both read the same R2 binding. The
|
|
@@ -2173,13 +2184,13 @@ ${Ut}${ae}${en}${Re}${Oe}${Se}${Le}
|
|
|
2173
2184
|
// so both write to the same trace.
|
|
2174
2185
|
const span = this.makeDispatchSpan(traceAnchor, observability);
|
|
2175
2186
|
|
|
2176
|
-
${
|
|
2187
|
+
${Jt} // \`ctx.db\`, wrapped in automatic instrumentation: by default this
|
|
2177
2188
|
// adds aggregate counters (call count, total time, per-operation
|
|
2178
2189
|
// breakdown) to the wide event rather than a span per call, so a
|
|
2179
2190
|
// handler making hundreds of queries stays readable. See
|
|
2180
2191
|
// \`instrumentDatabase\` for the \`"spans"\` / \`"off"\` levels.
|
|
2181
2192
|
const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${Kt}), logFunctionPath, traceAnchor, observability);
|
|
2182
|
-
${Zt}${
|
|
2193
|
+
${Zt}${De}
|
|
2183
2194
|
|
|
2184
2195
|
// \`ctx.trace\` / \`ctx.metrics\`: spans and measurements to the same sink.
|
|
2185
2196
|
// The trace anchor is threaded explicitly for the same reason \`identity\`
|
|
@@ -2214,7 +2225,7 @@ ${nn}
|
|
|
2214
2225
|
scheduler,
|
|
2215
2226
|
span,
|
|
2216
2227
|
storage,
|
|
2217
|
-
trace,${Qt}${
|
|
2228
|
+
trace,${Qt}${$e}${tn}${pe}${Te}${Ae}${be}${ce}
|
|
2218
2229
|
};
|
|
2219
2230
|
${an}${rn}
|
|
2220
2231
|
ctx.runAction = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("action", reference.__lunoraRef, fnArgs, ctx);
|
|
@@ -2224,30 +2235,30 @@ ${an}${rn}
|
|
|
2224
2235
|
return ctx;
|
|
2225
2236
|
}
|
|
2226
2237
|
};
|
|
2227
|
-
`},We=e=>{switch(e.kind){case"array":case"object":case"record":case"union":return{builder:"text",mode:"json",notNull:!0,typeAnnotation:
|
|
2238
|
+
`},We=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 t=e.literalValue??"";return t.startsWith('"')||t.startsWith("'")?{builder:"text",notNull:!0}:t==="true"||t==="false"?{builder:"integer",mode:"boolean",notNull:!0}:t==="null"?{builder:"text",notNull:!0}:{builder:"real",notNull:!0}}case"null":return{builder:"text",notNull:!0};case"number":return{builder:"real",notNull:!0};case"optional":return{...e.inner?We(e.inner):{builder:"text",notNull:!1},notNull:!1};case"storage":case"string":return{builder:"text",notNull:!0};default:return{builder:"text",notNull:!0}}},pt=(e,t)=>{const n=e.kind==="optional"&&e.inner?e.inner:e;return n.kind==="id"&&n.tableName!==void 0&&t.has(n.tableName)?n.tableName:void 0},xr=(e,t,n)=>{m(e,"drizzle column name");const r=We(t),a=r.mode?`, { mode: "${r.mode}" }`:"";let o=`${r.builder}("${e}"${a})`;r.typeAnnotation&&(o+=`.$type<${r.typeAnnotation}>()`);const i=pt(t,n);return i!==void 0&&(o+=`.references((): AnySQLiteColumn => ${i}._id)`),r.notNull&&(o+=".notNull()"),o},kr=e=>{m(e.name,"drizzle index name");const t=e.unique?"uniqueIndex":"index",n=e.fields.map(r=>(m(r,"drizzle index field"),`t.${r}`)).join(", ");return` ${e.name}: ${t}("${e.name}").on(${n}),`},vr=(e,t)=>{m(e.name,"table name");const n=[' _id: text("_id").primaryKey(),',' _creationTime: integer("_creationTime").notNull(),',...Object.entries(e.shape).map(([a,o])=>` ${a}: ${xr(a,o,t)},`)].join(`
|
|
2228
2239
|
`),r=e.indexes.length>0?`, (t) => ({
|
|
2229
|
-
${e.indexes.map(a=>
|
|
2240
|
+
${e.indexes.map(a=>kr(a)).join(`
|
|
2230
2241
|
`)}
|
|
2231
2242
|
})`:"";return`export const ${e.name} = sqliteTable("${e.name}", {
|
|
2232
2243
|
${n}
|
|
2233
|
-
}${r});`}
|
|
2234
|
-
`;const n=
|
|
2244
|
+
}${r});`},$r=e=>e.typeAnnotation?.includes('Id<"')??!1,Sr=(e,t)=>{const n=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=We(s);n.add(d.builder),o=o||$r(d),a=a||pt(s,t)!==void 0}for(const s of i.indexes)r.add(s.unique?"uniqueIndex":"index")}return{columns:[...n].toSorted((i,s)=>i.localeCompare(s)),indexes:[...r].toSorted((i,s)=>i.localeCompare(s)),needsAnyColumn:a,needsId:o}},et=(e,t=!1)=>{if(e.length===0)return`${S}export {};
|
|
2245
|
+
`;const n=ee(t),r=new Set(e.map(g=>g.name)),{columns:a,indexes:o,needsAnyColumn:i,needsId:s}=Sr(e,r),d=[...o,...a].toSorted((g,b)=>g.localeCompare(b)),u=e.map(g=>vr(g,r)).join(`
|
|
2235
2246
|
|
|
2236
2247
|
`),p=[i?`import type { AnySQLiteColumn } from "${n.serverDrizzle}";
|
|
2237
2248
|
`:"",s?`import type { Id } from "./dataModel.js";
|
|
2238
|
-
`:""].join("");return`${
|
|
2249
|
+
`:""].join("");return`${S}import { ${d.join(", ")} } from "${n.serverDrizzle}";
|
|
2239
2250
|
${p}
|
|
2240
2251
|
${u}
|
|
2241
|
-
`},
|
|
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(`
|
|
2242
2253
|
`),a=r.length>0?`
|
|
2243
2254
|
${r}
|
|
2244
|
-
`:"",o=[...n.entries()].map(([s,
|
|
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(`
|
|
2245
2256
|
`);return` ${JSON.stringify(s)}: [
|
|
2246
2257
|
${u}
|
|
2247
2258
|
],`}).join(`
|
|
2248
2259
|
`),i=o.length>0?`
|
|
2249
2260
|
${o}
|
|
2250
|
-
`:"";return`${
|
|
2261
|
+
`:"";return`${S}/**
|
|
2251
2262
|
* One scheduled cron invocation. Exactly one target is set: \`functionPath\` is
|
|
2252
2263
|
* the \`namespace:fn\` dispatch ref (matches \`__lunoraRef\`), invoked on the
|
|
2253
2264
|
* shard; \`workflow\` is a \`WORKFLOW_*\` binding name whose durable workflow is
|
|
@@ -2272,10 +2283,10 @@ export const LUNORA_CRON_TRIGGERS: ReadonlyArray<string> = [${a}];
|
|
|
2272
2283
|
* looks up \`event.cron\` here and dispatches every job in the list.
|
|
2273
2284
|
*/
|
|
2274
2285
|
export const LUNORA_CRONS: Record<string, ReadonlyArray<LunoraCronJob>> = {${i}};
|
|
2275
|
-
`},
|
|
2286
|
+
`},Ur=e=>{const t=[...e].toSorted((r,a)=>r.name.localeCompare(a.name)).map(r=>{const a=[`name: ${JSON.stringify(r.name)}`,`table: ${JSON.stringify(r.table)}`];return r.field!==void 0&&a.push(`field: ${JSON.stringify(r.field)}`),r.dimensions!==void 0&&a.push(`dimensions: ${JSON.stringify(r.dimensions)}`),r.metric!==void 0&&a.push(`metric: ${JSON.stringify(r.metric)}`),r.metadata!==void 0&&a.push(`metadata: ${JSON.stringify(r.metadata)}`),` { ${a.join(", ")} },`}).join(`
|
|
2276
2287
|
`),n=t.length>0?`
|
|
2277
2288
|
${t}
|
|
2278
|
-
`:"";return`${
|
|
2289
|
+
`:"";return`${S}/**
|
|
2279
2290
|
* One vector index declared in \`schema.ts\` — an inline \`.vectorize()\` column
|
|
2280
2291
|
* or a standalone \`defineVectorIndex()\`. \`field\` is the source column (absent
|
|
2281
2292
|
* for a \`select\`-derived Shape B index); \`metadata\` lists the row fields
|
|
@@ -2296,4 +2307,4 @@ export interface LunoraVectorIndex {
|
|
|
2296
2307
|
* \`createWorker({ vectorIntrospector })\` to back the studio's vector browser.
|
|
2297
2308
|
*/
|
|
2298
2309
|
export const LUNORA_VECTOR_INDEXES: ReadonlyArray<LunoraVectorIndex> = [${n}];
|
|
2299
|
-
`},
|
|
2310
|
+
`},Kr=e=>{const t=new Set,n=[];for(const r of e)t.has(r.cron)||(t.add(r.cron),n.push(r.cron));return n};export{jr as $,Wr as A,_r as B,Cr as C,Dr as E,Ir as L,Ur as N,S,Kr as T,Vn as a,On as b,Fr as c,qr as d,Lr as g,Mr as l,Ar as n,Er as q,ln as r,Pr as s,Br as x};
|