@lunora/codegen 1.0.0-alpha.235 → 1.0.0-alpha.237
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 +150 -122
- package/dist/index.d.ts +150 -122
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/GENERATED_HEADER-DSXl0YM2.mjs +1 -0
- package/dist/packem_shared/OPENRPC_VERSION-Cl6P9WGv.mjs +3 -0
- package/dist/packem_shared/{SCHEMA_SNAPSHOT_FILENAME-BtMVx-4j.mjs → SCHEMA_SNAPSHOT_FILENAME-BxnbL9RB.mjs} +4 -4
- package/dist/packem_shared/buildOpenApiDocument-nYvBhjxu.mjs +3 -0
- package/dist/packem_shared/capabilities-DJJWVEtk.mjs +18 -0
- package/dist/packem_shared/{describeErrorLevelFindings-D23VSkFP.mjs → describeErrorLevelFindings-vzaGS9KL.mjs} +1 -1
- package/dist/packem_shared/emitAgents-BPFw6ww2.mjs +1 -0
- package/dist/packem_shared/emitApi-CJ9ziZnP.mjs +154 -0
- package/dist/packem_shared/{emitApp-CTLwFZHO.mjs → emitApp-BGhO5bhT.mjs} +3 -3
- package/dist/packem_shared/emitCrons-mkwWkn0R.mjs +69 -0
- package/dist/packem_shared/emitDataModel-D3WuEZ4b.mjs +113 -0
- package/dist/packem_shared/emitDrizzleSchema-Cv0HtLR3.mjs +15 -0
- package/dist/packem_shared/emitFunctions-BqAz1ssY.mjs +249 -0
- package/dist/packem_shared/emitServer-BEo_fCY8.mjs +365 -0
- package/dist/packem_shared/emitShard-Bu7EKdou.mjs +1 -0
- package/dist/packem_shared/fingerprintSchemaSources-L3nGKDQt.mjs +1 -0
- package/dist/packem_shared/json-data-Chfs2Cz5.mjs +1 -0
- package/dist/packem_shared/qualifiers-BhOL15WZ.mjs +1 -0
- package/dist/packem_shared/shard-B3LMNjIg.mjs +1435 -0
- package/dist/packem_shared/shard-runtime-B_ppYvOf.mjs +323 -0
- package/dist/packem_shared/shared-DjUziztz.mjs +9 -0
- package/package.json +3 -3
- package/dist/packem_shared/GENERATED_HEADER-Da0OC3EI.mjs +0 -1
- package/dist/packem_shared/OPENRPC_VERSION-CL0VnCPW.mjs +0 -3
- package/dist/packem_shared/buildOpenApiDocument-C7S5wJCl.mjs +0 -3
- package/dist/packem_shared/emit-DUpkZ68h.mjs +0 -2696
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import{r as p}from"./json-data-Chfs2Cz5.mjs";import{a,G as d}from"./shared-DjUziztz.mjs";const x=e=>e?{importFragment:"serveRelationFanout, ",override:`
|
|
2
|
+
protected override async runRelationFanoutRead(functionPath: string, args: Record<string, unknown>): Promise<unknown> {
|
|
3
|
+
this.ensureMigrated();
|
|
4
|
+
|
|
5
|
+
const { db } = this.buildCtx({ functionPath }) as { db: DatabaseWriterLike };
|
|
6
|
+
|
|
7
|
+
return serveRelationFanout(schema as unknown as SchemaLike, db, functionPath, args);
|
|
8
|
+
}
|
|
9
|
+
`}:{importFragment:"",override:""},k=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:`
|
|
10
|
+
const aiBinding = config.ai?.(env) ?? (env as Record<string, unknown>).AI;
|
|
11
|
+
// Correlate AI-Gateway-routed calls with the Lunora trace: thread the
|
|
12
|
+
// function path + trace id into createAi, which folds them into the
|
|
13
|
+
// gateway's native \`metadata\` only when a gateway is configured (absent
|
|
14
|
+
// otherwise). Mirror the tracer's anchor guard — a deferred subscription
|
|
15
|
+
// re-run must not borrow a concurrent dispatch's trace, so read
|
|
16
|
+
// \`getCurrentTrace()\` only on the synchronous (non-threaded-identity) path.
|
|
17
|
+
const aiTrace = options.identity ? undefined : this.getCurrentTrace();
|
|
18
|
+
const ai: LunoraAi = aiBinding
|
|
19
|
+
? createAi({ binding: aiBinding as AiBindingLike, env: env as Record<string, unknown>, metadata: { functionPath: options.functionPath, traceId: aiTrace?.traceId } })
|
|
20
|
+
: aiStub;
|
|
21
|
+
`,configField:`
|
|
22
|
+
ai?: (env: Record<string, unknown>) => AiBindingLike;`,contextField:`
|
|
23
|
+
ai,`,stub:`
|
|
24
|
+
const aiStub: LunoraAi = {
|
|
25
|
+
embeddingModel: () => {
|
|
26
|
+
${t}
|
|
27
|
+
},
|
|
28
|
+
model: () => {
|
|
29
|
+
${t}
|
|
30
|
+
},
|
|
31
|
+
run: async () => {
|
|
32
|
+
${t}
|
|
33
|
+
},
|
|
34
|
+
// workersai is a callable-with-properties; a bare throwing arrow isn't
|
|
35
|
+
// structurally assignable, so cast it. Never invoked (the stub throws first).
|
|
36
|
+
workersai: (() => {
|
|
37
|
+
${t}
|
|
38
|
+
}) as unknown as LunoraAi["workersai"],
|
|
39
|
+
};
|
|
40
|
+
`}},l=(e,t,n,{cast:r="",sync:o=[]}={})=>{const s=n.map(u=>` ${u}: ${o.includes(u)?"":"async "}() => {
|
|
41
|
+
${t}
|
|
42
|
+
},`).join(`
|
|
43
|
+
`);return`
|
|
44
|
+
const ${e} = {
|
|
45
|
+
${s}
|
|
46
|
+
}${r};
|
|
47
|
+
`},c={build:"",configField:"",contextField:"",importLines:[],stub:""},w=e=>e?{build:`
|
|
48
|
+
const kvBinding = config.kv?.(env) ?? (env as Record<string, unknown>).KV;
|
|
49
|
+
// KV is not this shard's SQLite, so nothing appends a \`__cdc_log\` entry
|
|
50
|
+
// when a value changes — a subscription that read one can never be proven
|
|
51
|
+
// current on reconnect and must re-snapshot. Reads only; \`put\`/\`delete\`
|
|
52
|
+
// are writes and stay unstamped.
|
|
53
|
+
const kv: Kv = markUnvouchableReads(kvBinding ? createKv({ namespace: kvBinding as KVNamespaceLike }) : kvStub, options.onRead, [
|
|
54
|
+
"get",
|
|
55
|
+
"getRaw",
|
|
56
|
+
"getWithMetadata",
|
|
57
|
+
"list",
|
|
58
|
+
]);
|
|
59
|
+
`,configField:`
|
|
60
|
+
kv?: (env: Record<string, unknown>) => KVNamespaceLike;`,contextField:`
|
|
61
|
+
kv,`,importLines:['import type { Kv, KVNamespaceLike } from "@lunora/bindings/kv";','import { createKv } from "@lunora/bindings/kv";'],stub:l("kvStub: Kv",'throw new Error("ctx.kv: no KV binding found. Add a \\`kv_namespaces\\` binding (env.KV) to wrangler.jsonc, or pass \\`kv\\` to createShardDO().");',["delete","get","getRaw","getWithMetadata","list","put"])}:c,R=(e,t)=>e?{build:`
|
|
62
|
+
const flags: import("${t}").LunoraFlags = createFlags(flagsConfig, env, {
|
|
63
|
+
provider: () => config.flags?.(env),
|
|
64
|
+
targetingKey: () => flagsConfig.identify?.({ identity: identity ?? null, userId: userId ?? null }),
|
|
65
|
+
});
|
|
66
|
+
`,configField:`
|
|
67
|
+
flags?: (env: Record<string, unknown>) => import("${t}").Provider;`,contextField:`
|
|
68
|
+
flags,`,importLines:[`import { createFlags } from "${t}";`,'import flagsConfig from "../flags.js";'],stub:""}:c,N=e=>e?{build:`
|
|
69
|
+
const { notify, push } = createNotify(notifyConfig, env, { log, metrics });
|
|
70
|
+
`,configField:"",contextField:`
|
|
71
|
+
notify,
|
|
72
|
+
push,`,importLines:['import { createNotify } from "@lunora/notify";','import notifyConfig from "../notify.js";'],stub:""}:c,S=e=>e?{build:`
|
|
73
|
+
const envConfig = lunoraEnvContract.${e.exportName}(env);
|
|
74
|
+
`,configField:"",contextField:`
|
|
75
|
+
env: envConfig,`,importLines:['import * as lunoraEnvContract from "../env.js";'],stub:""}:c,L=e=>e?{build:`
|
|
76
|
+
const access = accessFacade(identity, userId);
|
|
77
|
+
`,configField:"",contextField:`
|
|
78
|
+
access,`,importLines:['import { accessFacade } from "@lunora/cloudflare-access/context";'],stub:""}:c,$=(e,t,n)=>{if(!t)return{constant:"",evaluateOverride:"",subscriptionOverride:""};const r=i=>`
|
|
79
|
+
const env = (this.env ?? {}) as Record<string, unknown>;
|
|
80
|
+
const flags: import("${n}").LunoraFlags = createFlags(flagsConfig, env, {
|
|
81
|
+
provider: () => config.flags?.(env),
|
|
82
|
+
targetingKey: ${i},
|
|
83
|
+
});`,o=`
|
|
84
|
+
/** Statically-discovered feature flags (\`ctx.flags.<type>("key")\` reads) served via \`__lunora_admin__:listFlags\` + the reactive \`__lunora_flags__:\` channel. */
|
|
85
|
+
const LUNORA_FLAG_KEYS = ${p(e,'ReadonlyArray<{ key: string; type: "boolean" | "number" | "object" | "string" }>')};
|
|
86
|
+
`,s=`
|
|
87
|
+
protected override async evaluateFlags(context?: Record<string, unknown>): Promise<FlagsResult> {${r("undefined")}
|
|
88
|
+
const evalContext = context as import("${n}").EvaluationContext | undefined;
|
|
89
|
+
const evaluations: FlagsResult["flags"] = [];
|
|
90
|
+
|
|
91
|
+
for (const entry of LUNORA_FLAG_KEYS) {
|
|
92
|
+
// eslint-disable-next-line no-await-in-loop -- flags evaluate sequentially; each shares the single memoized provider client
|
|
93
|
+
const details =
|
|
94
|
+
entry.type === "boolean"
|
|
95
|
+
? await flags.details.boolean(entry.key, false, evalContext)
|
|
96
|
+
: entry.type === "number"
|
|
97
|
+
? await flags.details.number(entry.key, 0, evalContext)
|
|
98
|
+
: entry.type === "string"
|
|
99
|
+
? await flags.details.string(entry.key, "", evalContext)
|
|
100
|
+
: await flags.details.object(entry.key, {}, evalContext);
|
|
101
|
+
|
|
102
|
+
evaluations.push({ errorCode: details.errorCode, key: entry.key, reason: details.reason, type: entry.type, value: details.value, variant: details.variant });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return { configured: true, flags: evaluations };
|
|
106
|
+
}
|
|
107
|
+
`,u=`
|
|
108
|
+
protected override runFlagSubscriptionRead(_functionPath: string, args: Record<string, unknown>, identity?: SubscriptionIdentity): Promise<unknown> {${r("() => flagsConfig.identify?.({ identity: identity?.identity ?? null, userId: identity?.userId ?? null })")}
|
|
109
|
+
const key = typeof args.key === "string" ? args.key : "";
|
|
110
|
+
|
|
111
|
+
// SECURITY: the reactive channel is public (any socket, no auth). Serve
|
|
112
|
+
// ONLY statically-discovered flag keys — an arbitrary client-supplied key
|
|
113
|
+
// would let a subscriber probe the value of internal/unreleased flags the
|
|
114
|
+
// app never exposes. Unknown key ⇒ the "nothing to deliver" sentinel.
|
|
115
|
+
// eslint-disable-next-line unicorn/no-null -- the base hook's "nothing to deliver" sentinel
|
|
116
|
+
if (key.length === 0 || !LUNORA_FLAG_KEYS.some((entry) => entry.key === key)) {
|
|
117
|
+
return Promise.resolve(null);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// SECURITY: evaluate under the socket's server-verified identity ONLY
|
|
121
|
+
// (the targetingKey resolved above). Client-supplied targeting context is
|
|
122
|
+
// NOT honored on this public channel — otherwise a subscriber could spoof
|
|
123
|
+
// targeting attributes (e.g. plan/role) to unlock a flag gated on them.
|
|
124
|
+
const context = undefined;
|
|
125
|
+
|
|
126
|
+
if (args.type === "number") {
|
|
127
|
+
return flags.number(key, typeof args.default === "number" ? args.default : 0, context);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (args.type === "string") {
|
|
131
|
+
return flags.string(key, typeof args.default === "string" ? args.default : "", context);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (args.type === "object") {
|
|
135
|
+
return flags.object(key, (args.default ?? {}) as import("${n}").JsonValue, context);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return flags.boolean(key, typeof args.default === "boolean" ? args.default : false, context);
|
|
139
|
+
}
|
|
140
|
+
`;return{constant:o,evaluateOverride:s,subscriptionOverride:u}},A=e=>e?{build:`
|
|
141
|
+
const analyticsBinding = config.analytics?.(env) ?? (env as Record<string, unknown>).ANALYTICS;
|
|
142
|
+
const analytics: AnalyticsClient = analyticsBinding ? createAnalytics(analyticsBinding as AnalyticsEngineDatasetLike) : analyticsStub;
|
|
143
|
+
`,configField:`
|
|
144
|
+
analytics?: (env: Record<string, unknown>) => AnalyticsEngineDatasetLike;`,contextField:`
|
|
145
|
+
analytics,`,importLines:['import type { AnalyticsClient, AnalyticsEngineDatasetLike } from "@lunora/bindings/analytics";','import { createAnalytics } from "@lunora/bindings/analytics";'],stub:l("analyticsStub: AnalyticsClient",'throw new Error("ctx.analytics: no Analytics Engine binding found. Add an \\`analytics_engine_datasets\\` binding (env.ANALYTICS) to wrangler.jsonc, or pass \\`analytics\\` to createShardDO().");',["track","writeDataPoint"],{sync:["track","writeDataPoint"]})}:c,F=e=>e?{build:`
|
|
146
|
+
const imagesBinding = config.images?.(env) ?? (env as Record<string, unknown>).IMAGES;
|
|
147
|
+
const images: Images = imagesBinding ? createImages({ binding: imagesBinding as ImagesBindingLike }) : imagesStub;
|
|
148
|
+
`,configField:`
|
|
149
|
+
images?: (env: Record<string, unknown>) => ImagesBindingLike;`,contextField:`
|
|
150
|
+
images,`,importLines:['import type { Images, ImagesBindingLike } from "@lunora/bindings/images";','import { createImages } from "@lunora/bindings/images";'],stub:l("imagesStub: Images",'throw new Error("ctx.images: no Images binding found. Add an \\`images\\` binding (env.IMAGES) to wrangler.jsonc, or pass \\`images\\` to createShardDO().");',["info","transform"])}:c,C=e=>e?{build:`
|
|
151
|
+
const sql: SqlClient = config.sql ? config.sql(env) : sqlStub;
|
|
152
|
+
`,configField:`
|
|
153
|
+
sql?: (env: Record<string, unknown>) => SqlClient;`,contextField:`
|
|
154
|
+
sql,`,importLines:['import type { SqlClient } from "@lunora/hyperdrive";'],stub:l("sqlStub: SqlClient",'throw new Error("ctx.sql: provide a \\`sql\\` config thunk that builds a SqlClient from your driver, e.g. \\`sql: (env) => fromPostgresJs(postgres(env.HYPERDRIVE.connectionString))\\`.");',["query"])}:c,_=e=>e?{build:`
|
|
155
|
+
const browser: Browser = config.browser ? config.browser(env) : browserStub;
|
|
156
|
+
`,configField:`
|
|
157
|
+
browser?: (env: Record<string, unknown>) => Browser;`,contextField:`
|
|
158
|
+
browser,`,importLines:['import type { Browser } from "@lunora/browser";'],stub:l("browserStub: Browser","throw new Error(\"ctx.browser: provide a \\`browser\\` config thunk, e.g. \\`browser: (env) => createBrowser({ binding: env.BROWSER, launch })\\` with \\`import { launch } from '@cloudflare/playwright'\\`. Session reuse (connect/sessions) additionally needs those two exports passed the same way.\");",["connect","content","launch","pdf","scrape","screenshot","sessions"])}:c,E=e=>e?{build:`
|
|
159
|
+
const r2sqlEnv = env as Record<string, unknown>;
|
|
160
|
+
const r2sqlAccountId = (r2sqlEnv.R2_SQL_ACCOUNT_ID ?? r2sqlEnv.CLOUDFLARE_ACCOUNT_ID) as string | undefined;
|
|
161
|
+
const r2sqlToken = r2sqlEnv.R2_SQL_TOKEN as string | undefined;
|
|
162
|
+
const r2sqlBucket = r2sqlEnv.R2_SQL_BUCKET as string | undefined;
|
|
163
|
+
const r2sql: R2SqlClient = config.r2sql
|
|
164
|
+
? config.r2sql(env)
|
|
165
|
+
: r2sqlAccountId && r2sqlToken && r2sqlBucket
|
|
166
|
+
? createR2Sql({ accountId: r2sqlAccountId, apiToken: r2sqlToken, bucket: r2sqlBucket })
|
|
167
|
+
: r2sqlStub;
|
|
168
|
+
`,configField:`
|
|
169
|
+
r2sql?: (env: Record<string, unknown>) => R2SqlClient;`,contextField:"",importLines:['import type { R2SqlClient } from "@lunora/bindings/r2sql";','import { createR2Sql } from "@lunora/bindings/r2sql";'],stub:l("r2sqlStub: R2SqlClient",'throw new Error("ctx.r2sql: no R2 SQL credentials found. Set \\`R2_SQL_TOKEN\\`, \\`R2_SQL_ACCOUNT_ID\\` (or \\`CLOUDFLARE_ACCOUNT_ID\\`), and \\`R2_SQL_BUCKET\\` in your env/.dev.vars, or pass an \\`r2sql\\` config thunk to createShardDO().");',["describe","explain","from","query","showDatabases","showTables"],{sync:["from"]})}:c,O=e=>e?{build:`
|
|
170
|
+
const pipelinesBinding = config.pipelines?.(env) ?? (env as Record<string, unknown>).PIPELINES;
|
|
171
|
+
const pipelines: PipelineClient = pipelinesBinding ? createPipelines({ binding: pipelinesBinding as PipelineBindingLike }) : pipelinesStub;
|
|
172
|
+
`,configField:`
|
|
173
|
+
pipelines?: (env: Record<string, unknown>) => PipelineBindingLike;`,contextField:"",importLines:['import type { PipelineBindingLike, PipelineClient } from "@lunora/bindings/pipelines";','import { createPipelines } from "@lunora/bindings/pipelines";'],stub:l("pipelinesStub: PipelineClient",'throw new Error("ctx.pipelines: no Pipelines binding found. Add a \\`pipelines\\` binding (env.PIPELINES) to wrangler.jsonc, or pass \\`pipelines\\` to createShardDO().");',["send"])}:c,P=(e,t)=>{if(e.length===0)return"";const n=t?`, ${JSON.stringify(t)}`:"",r=e.map(s=>(a(s.exportName,`container export "${s.exportName}"`),a(s.className,`container class "${s.className}"`),`/** Container DO for the \`${s.exportName}\` definition (binding \`${s.bindingName}\`). */
|
|
174
|
+
export class ${s.className} extends LunoraContainer {
|
|
175
|
+
public constructor(ctx: ConstructorParameters<typeof LunoraContainer>[0], env: Record<string, unknown>) {
|
|
176
|
+
super(ctx, env, ${s.exportName}, "${s.exportName}"${n});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
`)).join(`
|
|
180
|
+
`),o=e.map(s=>s.exportName).join(", ");return`${d}/**
|
|
181
|
+
* Container-enabled Durable Object classes for the containers declared in
|
|
182
|
+
* \`lunora/containers.ts\`. Re-export them from your worker entry — wrangler
|
|
183
|
+
* requires each \`containers[].class_name\` to be exported by the worker:
|
|
184
|
+
*
|
|
185
|
+
* \`export * from "./lunora/_generated/containers.js";\`
|
|
186
|
+
*
|
|
187
|
+
* \`ContainerProxy\` is re-exported alongside them: the egress-interception path
|
|
188
|
+
* (\`allowedHosts\`/\`deniedHosts\`/\`interceptHttps\` and the runtime
|
|
189
|
+
* \`handle.egress\` controls) routes container outbound traffic through this
|
|
190
|
+
* WorkerEntrypoint, so it too must be exported by the deployed worker.
|
|
191
|
+
*/
|
|
192
|
+
import { LunoraContainer } from "@lunora/container/do";
|
|
193
|
+
|
|
194
|
+
import { ${o} } from "../containers.js";
|
|
195
|
+
|
|
196
|
+
export { ContainerProxy } from "@lunora/container/do";
|
|
197
|
+
|
|
198
|
+
${r}`},q=(e,t)=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const r of e)a(r.exportName,`container export "${r.exportName}"`),a(r.bindingName,`container binding "${r.bindingName}"`);const n=e.map(r=>{const o=r.maxInstances===void 0?"":`, maxInstances: ${String(r.maxInstances)}`;return` { binding: "${r.bindingName}", exportName: "${r.exportName}"${o} },`}).join(`
|
|
199
|
+
`);return{build:`
|
|
200
|
+
const containers = createContainerContext(env, LUNORA_CONTAINERS, ${t?JSON.stringify(t):"undefined"}, this.getCurrentTraceparent(), this.getCurrentSampleErrors());
|
|
201
|
+
`,contextField:`
|
|
202
|
+
containers,`,importLines:['import type { ContainerBindingSpec } from "@lunora/container";','import { createContainerContext } from "@lunora/container";'],specs:`
|
|
203
|
+
/** Wiring specs for \`ctx.containers\` (codegen-derived from \`lunora/containers.ts\`). */
|
|
204
|
+
const LUNORA_CONTAINERS: ReadonlyArray<ContainerBindingSpec> = [
|
|
205
|
+
${n}
|
|
206
|
+
];
|
|
207
|
+
`}},I=e=>{if(e.length===0)return"";const t=e.map(r=>(a(r.exportName,`workflow export "${r.exportName}"`),a(r.className,`workflow class "${r.className}"`),`/** WorkflowEntrypoint for the \`${r.exportName}\` definition (binding \`${r.bindingName}\`). */
|
|
208
|
+
export class ${r.className} extends LunoraWorkflow<WorkflowParamsOf<typeof ${r.exportName}>, WorkflowOutputOf<typeof ${r.exportName}>> {
|
|
209
|
+
public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
210
|
+
super(ctx, env, ${r.exportName}, "${r.exportName}");
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
`)).join(`
|
|
214
|
+
`),n=e.map(r=>r.exportName).join(", ");return`${d}/**
|
|
215
|
+
* WorkflowEntrypoint classes for the workflows declared in
|
|
216
|
+
* \`lunora/workflows.ts\`. Re-export them from your worker entry — wrangler
|
|
217
|
+
* requires each \`workflows[].class_name\` to be exported by the worker:
|
|
218
|
+
*
|
|
219
|
+
* \`export * from "./lunora/_generated/workflows.js";\`
|
|
220
|
+
*/
|
|
221
|
+
import LunoraWorkflow from "@lunora/workflow/do";
|
|
222
|
+
|
|
223
|
+
import { ${n} } from "../workflows.js";
|
|
224
|
+
|
|
225
|
+
/** Params type carried by a \`defineWorkflow\` definition (its phantom \`__params\`), so each entrypoint keeps the authored \`ctx.params\` type. */
|
|
226
|
+
type WorkflowParamsOf<Definition> = Definition extends { __params?: infer Params }
|
|
227
|
+
? unknown extends Params
|
|
228
|
+
? Record<string, unknown>
|
|
229
|
+
: NonNullable<Params>
|
|
230
|
+
: Record<string, unknown>;
|
|
231
|
+
|
|
232
|
+
/** Output type carried by a \`defineWorkflow\` definition (its phantom \`__output\`), so each entrypoint keeps the authored return type. */
|
|
233
|
+
type WorkflowOutputOf<Definition> = Definition extends { __output?: infer Output } ? Output : unknown;
|
|
234
|
+
|
|
235
|
+
${t}`},B=e=>{if(e.length===0)return"";const n=e.filter(i=>i.voice).length>0,r=e.map(i=>{a(i.exportName,`agent export "${i.exportName}"`),a(i.className,`agent class "${i.className}"`);const g=`/** WorkflowEntrypoint for the \`${i.exportName}\` agent (binding \`${i.bindingName}\`). */
|
|
236
|
+
export class ${i.className} extends LunoraWorkflow<AgentRunInput, AgentRunResult> {
|
|
237
|
+
public constructor(ctx: ConstructorParameters<typeof LunoraWorkflow>[0], env: Record<string, unknown>) {
|
|
238
|
+
super(ctx, env, compileAgentWorkflow(${i.exportName}, "${i.exportName}"), "${i.exportName}");
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
`;if(!i.voice)return g;const m=i.voiceClassName??"",y=i.voiceBindingName??"";a(m,`agent voice class "${m}"`);const b=`
|
|
242
|
+
/** Voice-session Durable Object for the \`${i.exportName}\` agent (binding \`${y}\`). */
|
|
243
|
+
export class ${m} extends VoiceSessionDO {
|
|
244
|
+
public constructor(ctx: ConstructorParameters<typeof VoiceSessionDO>[0], env: Record<string, unknown>) {
|
|
245
|
+
super(ctx, env, ${i.exportName}, "${i.exportName}");
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
`;return`${g}${b}`}).join(`
|
|
249
|
+
`),o=e.map(i=>i.exportName).join(", ");return`${d}/**
|
|
250
|
+
* WorkflowEntrypoint classes for the agents declared in \`lunora/agents.ts\`.
|
|
251
|
+
* Each \`defineAgent\` compiles a replay-safe tool-loop onto a Cloudflare
|
|
252
|
+
* Workflow. Re-export them from your worker entry — wrangler requires each
|
|
253
|
+
* \`workflows[].class_name\` to be exported by the worker:
|
|
254
|
+
*
|
|
255
|
+
* \`export * from "./lunora/_generated/agents.js";\`${n?"\n *\n * Voice-enabled agents ALSO get a `VoiceSessionDO` subclass here — a real\n * Durable Object (unlike the Workflow), so wrangler needs both its\n * `durable_objects` binding and its `class_name` export (the same re-export\n * line covers it).":""}
|
|
256
|
+
*/
|
|
257
|
+
import LunoraWorkflow from "@lunora/workflow/do";
|
|
258
|
+
${n?'import { compileAgentWorkflow, VoiceSessionDO } from "@lunora/agent";':'import { compileAgentWorkflow } from "@lunora/agent";'}
|
|
259
|
+
import type { AgentRunInput, AgentRunResult } from "@lunora/agent";
|
|
260
|
+
|
|
261
|
+
import { ${o} } from "../agents.js";
|
|
262
|
+
|
|
263
|
+
${r}`},W=e=>{const t=e.filter(o=>o.mode==="push");if(t.length===0)return"";for(const o of t)a(o.exportName,`queue export "${o.exportName}"`);const n=t.map(o=>o.exportName).join(", "),r=t.map(o=>` ${JSON.stringify(o.name)}: { binding: ${JSON.stringify(o.bindingName)}, definition: ${o.exportName}, exportName: ${JSON.stringify(o.exportName)} },`).join(`
|
|
264
|
+
`);return`${d}/**
|
|
265
|
+
* Push-consumer registry for the queues declared in \`lunora/queues.ts\`. The
|
|
266
|
+
* composed worker's \`queue(batch, env, ctx)\` entry routes each delivered batch
|
|
267
|
+
* by \`batch.queue\` to the matching \`defineQueue\` handler. Wired automatically
|
|
268
|
+
* by \`defineApp\` — you don't import this directly.
|
|
269
|
+
*/
|
|
270
|
+
import type { QueueRegistry } from "@lunora/queue";
|
|
271
|
+
|
|
272
|
+
import { ${n} } from "../queues.js";
|
|
273
|
+
|
|
274
|
+
/** Stable wrangler queue name → { binding, definition, exportName } for batch routing. */
|
|
275
|
+
export const LUNORA_QUEUE_REGISTRY: QueueRegistry = {
|
|
276
|
+
${r}
|
|
277
|
+
};
|
|
278
|
+
`},D=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)a(n.exportName,`workflow export "${n.exportName}"`),a(n.bindingName,`workflow binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}" },`).join(`
|
|
279
|
+
`);return{build:`
|
|
280
|
+
const workflows = createWorkflowContext(env, LUNORA_WORKFLOWS);
|
|
281
|
+
`,contextField:`
|
|
282
|
+
workflows,`,importLines:['import type { WorkflowBindingSpec } from "@lunora/workflow";','import { createWorkflowContext } from "@lunora/workflow";'],specs:`
|
|
283
|
+
/** Wiring specs for \`ctx.workflows\` (codegen-derived from \`lunora/workflows.ts\`). */
|
|
284
|
+
const LUNORA_WORKFLOWS: ReadonlyArray<WorkflowBindingSpec> = [
|
|
285
|
+
${t}
|
|
286
|
+
];
|
|
287
|
+
`}},T=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)a(n.exportName,`queue export "${n.exportName}"`),a(n.bindingName,`queue binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}", name: ${JSON.stringify(n.name)} },`).join(`
|
|
288
|
+
`);return{build:`
|
|
289
|
+
const queues = createQueueContext(env, LUNORA_QUEUES);
|
|
290
|
+
`,contextField:`
|
|
291
|
+
queues,`,importLines:['import type { QueueBindingSpec } from "@lunora/queue";','import { createQueueContext } from "@lunora/queue";'],specs:`
|
|
292
|
+
/** Wiring specs for \`ctx.queues\` (codegen-derived from \`lunora/queues.ts\`). */
|
|
293
|
+
const LUNORA_QUEUES: ReadonlyArray<QueueBindingSpec> = [
|
|
294
|
+
${t}
|
|
295
|
+
];
|
|
296
|
+
`}},j=e=>{if(e.length===0)return{build:"",contextField:"",importLines:[],specs:""};for(const n of e)a(n.exportName,`agent export "${n.exportName}"`),a(n.bindingName,`agent binding "${n.bindingName}"`);const t=e.map(n=>` { binding: "${n.bindingName}", exportName: "${n.exportName}"${n.publicRun===!0?", publicRun: true":""} },`).join(`
|
|
297
|
+
`);return{build:`
|
|
298
|
+
const agents = createAgentContext(env, LUNORA_AGENTS);
|
|
299
|
+
`,contextField:`
|
|
300
|
+
agents,`,importLines:['import { createAgentContext } from "@lunora/agent";','import type { AgentBindingSpec } from "@lunora/agent";'],specs:`
|
|
301
|
+
/** Wiring specs for \`ctx.agents\` (codegen-derived from \`lunora/agents.ts\`). */
|
|
302
|
+
const LUNORA_AGENTS: ReadonlyArray<AgentBindingSpec> = [
|
|
303
|
+
${t}
|
|
304
|
+
];
|
|
305
|
+
`}},f=(e,t,n,r,o)=>({constant:`
|
|
306
|
+
${o}
|
|
307
|
+
const ${e} = ${p(r,t)};
|
|
308
|
+
`,override:`
|
|
309
|
+
protected override ${n}(): ${t} {
|
|
310
|
+
return ${e};
|
|
311
|
+
}
|
|
312
|
+
`}),M=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 f("LUNORA_WORKFLOWS_INFO","WorkflowsResult","workflowsMetadata",t,"/** Read-only declared-workflow metadata (discovered from `lunora/workflows.ts`) served via `__lunora_admin__:listWorkflows` for the studio's workflows view. */")},U=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 f("LUNORA_QUEUES_INFO","QueuesResult","queuesMetadata",t,"/** Read-only declared-queue metadata (discovered from `lunora/queues.ts`) served via `__lunora_admin__:listQueues` for the studio's queues view. */")},Q=e=>e?{imports:['import type { LunoraDatabaseLike as LunoraPaymentDbLike, LunoraPayment, PaymentsFromContextOptions } from "@lunora/payment";','import { paymentsFromContext } from "@lunora/payment";'],build:`
|
|
313
|
+
const payments: LunoraPayment = config.payment
|
|
314
|
+
? paymentsFromContext({ auth: { userId: userId ?? null }, db: db as unknown as LunoraPaymentDbLike }, config.payment(env))
|
|
315
|
+
: paymentStub;
|
|
316
|
+
`,configField:`
|
|
317
|
+
payment?: (env: Record<string, unknown>) => PaymentsFromContextOptions;`,contextField:`
|
|
318
|
+
payments,`,stub:l("paymentStub: LunoraPayment",'throw new Error("ctx.payments: no payment configured. Pass \\`payment\\` to createShardDO().");',["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"],{cast:" as unknown as LunoraPayment",sync:["attach","cancelSubscription","check","createCheckout","createPortalSession","handleWebhook","listBalances","listSubscriptions","track"]})}:{build:"",configField:"",contextField:"",imports:[],stub:""},K=e=>e?{imports:['import type { X402Pay, X402PayConfig } from "@lunora/x402/pay";','import { lazyX402Pay } from "@lunora/x402/pay";'],build:`
|
|
319
|
+
const x402: X402Pay = config.x402
|
|
320
|
+
? lazyX402Pay(config.x402(env), { getSecret: (name: string) => secrets.get(name) })
|
|
321
|
+
: x402Stub;
|
|
322
|
+
`,configField:`
|
|
323
|
+
x402?: (env: Record<string, unknown>) => X402PayConfig;`,stub:l("x402Stub: X402Pay",'throw new Error("ctx.x402: no pay rail configured. Pass \\`x402\\` to createShardDO().");',["fetch"],{cast:" as unknown as X402Pay",sync:["fetch"]})}:{build:"",configField:"",imports:[],stub:""},V=(e,t,n,r,o)=>["AdvisorProcedure","AdvisoryFinding","DatabaseWriterLike","DataMigrationLike","DispatchBookmark","ExportRow",...r?["FlagsResult"]:[],"ImportShardResult","KeyRange","MaskPoliciesResult","MigrationRunResult","QueryReadScope",...n?["QueuesResult"]:[],"RelatedPage","RunShardApplyCdcArgs","RunShardExportArgs","RunShardFindRelatedArgs","RunShardImportArgs","RunShardMigrationArgs","RlsPoliciesResult","RunShardRankBeforeArgs","RunShardRankPageArgs","RunShardWriteArgs","RunShardWriteResult","SchedulerLike",...o?["SearchBackfillProgress"]:[],"TransactionHeadroomTracker","SchemaLike","ShardDOState","ShardRankPageResult","SqlExec","StorageRulesResult","StudioFeaturesResult","SubscriptionIdentity","SystemReaderStorageLike","TelemetrySink",...e?["VectorBackfillProgress"]:[],...t?["WorkflowsResult"]:[],...e?["WriteHook"]:[]];export{I as A,W as B,w as a,R as b,$ as c,S as d,k as e,A as f,F as g,C as h,_ as i,E as j,O as k,T as l,q as m,D as n,j as o,Q as p,K as q,l as r,M as s,U as t,V as u,x as v,L as w,N as x,B as y,P as z};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import{LunoraError as l}from"@lunora/errors";import{acceptsAbsentIr as $}from"./LUNORA_ERROR_CODES-C2s0xWQD.mjs";const b=/^(?:"(?:[^"\\]|\\(?:["\\/bfnrt]|u[0-9A-Fa-f]{4}))*"|'[^'\\]*'|-?\d+(?:\.\d+)?|true|false|null)$/u,_=`// GENERATED by @lunora/codegen — do not edit.
|
|
2
|
+
// Run \`lunora codegen\` to regenerate.
|
|
3
|
+
|
|
4
|
+
`,w=(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"},p=/^[A-Za-z_$][\w$]*$/u,A=/^[\w./-]+$/u,y=(e,n)=>{if(!p.test(e))throw new l("INTERNAL",`@lunora/codegen: ${n} is not a valid JS identifier: ${JSON.stringify(e)}`)},I=e=>e.charAt(0).toUpperCase()+e.slice(1),u=e=>p.test(e)?e:JSON.stringify(e),R=e=>e==="__proto__"?`[${JSON.stringify(e)}]`:u(e),g={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"},T=e=>{if(e===void 0)return"unknown";if(!b.test(e))throw new l("INTERNAL",`@lunora/codegen: v.literal() argument is not a parseable string/number/boolean/null literal: ${JSON.stringify(e)}`);return e},t=e=>e.column?.notNull===!1?`${a(e)} | null`:a(e),a=e=>{const n=g[e.kind];if(n!==void 0)return n;switch(e.kind){case"array":return`Array<${e.inner?t(e.inner):"unknown"}>`;case"from":return e.tsType??"unknown";case"id":{const r=e.tableName??"_unknown_";return y(r,"v.id() table name"),`Id<"${r}">`}case"literal":return T(e.literalValue);case"object":return e.shape?`{ ${Object.entries(e.shape).map(([s,o])=>m(s,o)).join("; ")} }`:"Record<string, unknown>";case"optional":return`${e.inner?t(e.inner):"unknown"} | undefined`;case"record":{const r=e.keyType?t(e.keyType):"string",s=e.valueType?t(e.valueType):"unknown";return`Record<${r}, ${s}>`}case"union":return e.members&&e.members.length>0?e.members.map(r=>t(r)).join(" | "):"never";default:return"unknown"}},m=(e,n)=>{const r=u(e);if(n.kind==="optional"){const s=n.inner?t(n.inner):"unknown";return`${r}?: ${s}`}return $(n)?`${r}?: ${t(n)}`:`${r}: ${t(n)}`},O=e=>{const n=Object.entries(e);return n.length===0?"{}":`{ ${n.map(([r,s])=>m(r,s)).join("; ")} }`},d=e=>e.kind==="optional"||!!e.column?.hasDefault,E=e=>e.kind==="optional"&&e.inner?e.inner:e,N=e=>{y(e.name,"table name");const n=Object.entries(e.shape).map(([s,o])=>{const f=E(o),c=t(f),i=u(s);return d(o)?` ${i}?: ${c};`:` ${i}: ${c};`}).join(`
|
|
5
|
+
`),r=n?`
|
|
6
|
+
${n}
|
|
7
|
+
`:"";return`export interface Insert_${e.name} {
|
|
8
|
+
_id?: Id<"${e.name}">;
|
|
9
|
+
_creationTime?: number;${r}}`};export{_ as G,A as I,b as L,y as a,u as b,R as c,w as d,N as e,d as i,I as p,O as r,E as u,t as v};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/codegen",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.237",
|
|
4
4
|
"description": "Code generator for Lunora: emits _generated/{api,server,dataModel}.ts from your schema",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@lunora/advisor": "1.0.0-alpha.
|
|
50
|
-
"@lunora/agent": "1.0.0-alpha.
|
|
49
|
+
"@lunora/advisor": "1.0.0-alpha.170",
|
|
50
|
+
"@lunora/agent": "1.0.0-alpha.152",
|
|
51
51
|
"@lunora/container": "1.0.0-alpha.63",
|
|
52
52
|
"@lunora/errors": "1.0.0-alpha.47",
|
|
53
53
|
"@lunora/platform": "1.0.0-alpha.42",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import{G as o,U as n,o as l,e as p,a as A,b as E,c as S,d as c,f as d,g,h as u,p as C,i as h,q as D,j as f,k as G,l as R,m as _,n as b}from"./emit-DUpkZ68h.mjs";import"./declared-output-Iaar469J.mjs";import"./isD1GlobalTable-udvHAAzD.mjs";import"./paths-C-9fwEgQ.mjs";import"./LUNORA_ERROR_CODES-C2s0xWQD.mjs";export{o as GENERATED_HEADER,n as UMBRELLA_BASE_PACKAGES,l as buildStorageColumns,p as emitAgents,A as emitApi,E as emitCollections,S as emitContainers,c as emitCrons,d as emitDataModel,g as emitDrizzleSchema,u as emitFunctions,C as emitQueues,h as emitScheduler,D as emitSeed,f as emitServer,G as emitShard,R as emitVectors,_ as emitWorkflows,b as emitWranglerCronTriggers};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{G as c,r as u}from"./emit-DUpkZ68h.mjs";import{s as m}from"./paths-C-9fwEgQ.mjs";import{validatorIrToJsonSchema as p,objectSchema as l,LUNORA_ERROR_CODES as d}from"./LUNORA_ERROR_CODES-C2s0xWQD.mjs";const i="1.3.2",R={description:"Result is TS-inferred from the function's return type (no `.output()` declared); best-effort — any JSON."},h=e=>{const o=m(e.filePath),n=`${o}:${e.exportName}`;return{description:`Invoke the \`${e.kind}\` \`${n}\` over the Lunora RPC envelope (POST /_lunora/rpc, body \`{ "functionPath": "${n}", "args": { … } }\`).`,errors:d.map((r,s)=>({code:-32e3-s,data:{code:r},message:r})),name:n,params:[{description:"The function's argument object (the RPC envelope's `args`).",name:"args",required:Object.keys(e.args).length>0,schema:l(e.args)}],result:{name:"result",schema:e.output?p(e.output):R},summary:`${e.kind}: ${n}`,"x-lunora-function-kind":e.kind,"x-tags":[{name:o}]}},g=e=>{const o=e.version??"0.0.0",r=e.functions.filter(t=>t.visibility!=="internal"&&t.kind!=="stream").map(t=>h(t)).toSorted((t,a)=>t.name.localeCompare(a.name));return{info:{description:"Auto-generated from @lunora/values-typed functions by @lunora/codegen. Do not edit — run `lunora codegen` to regenerate.",title:"Lunora RPC",version:o},methods:r,openrpc:i}},v=e=>`${JSON.stringify(g(e),void 0,2)}
|
|
2
|
-
`,$=e=>`${c}export const openRpcSpec = ${u(e,"Record<string, unknown>")};
|
|
3
|
-
`;export{i as OPENRPC_VERSION,g as buildOpenRpcDocument,v as emitOpenRpc,$ as emitOpenRpcModule};
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{G as S,r as O}from"./emit-DUpkZ68h.mjs";import{s as p}from"./paths-C-9fwEgQ.mjs";import{LUNORA_ERROR_CODES as E,objectSchema as h,validatorIrToJsonSchema as u}from"./LUNORA_ERROR_CODES-C2s0xWQD.mjs";const A="/_lunora/rest",P=["authorization","cf-access-jwt-assertion","cookie","payment-signature","x-payment"],f=["x-d1-bookmark","x-lunora-shard-key"],T=e=>[...P,...(e.credentialHeaders??[]).map(t=>t.toLowerCase())],g=e=>Number.isFinite(e)?Math.max(0,Math.floor(e)):0,y=(...e)=>{const t=[];for(const r of e)for(const o of r?.split(",")??[]){const s=o.trim().toLowerCase();s!==""&&!t.includes(s)&&t.push(s)}return t.length===0?void 0:t.join(", ")},b=(e,t)=>{const r=[t,`max-age=${String(g(e.maxAge))}`];return e.staleWhileRevalidate!==void 0&&r.push(`stale-while-revalidate=${String(g(e.staleWhileRevalidate))}`),r.join(", ")},x=e=>e.scope==="public"?y(e.vary,...T(e),...f):y(e.vary,...f),k=e=>{const t=e.indexOf(":");if(!(t<=0||t>=e.length-1||e.indexOf(":",t+1)!==-1))return{name:e.slice(t+1),namespace:e.slice(0,t)}},N=e=>{const t=k(e);if(t!==void 0)return`${A}/${t.namespace}/${t.name}`},q=e=>e==="query"?"GET":"POST",m="#/components/responses/LunoraError",v=/:([A-Za-z_$][\w$]*)/gu,_=e=>[...e.matchAll(v)].map(t=>t[1]),j=e=>e.replaceAll(v,"{$1}"),l=e=>e.kind==="optional"?e.inner??e:e,C=e=>{const t=new Set(_(e.path)),r=[];for(const[o,s]of Object.entries(e.searchParams)){const c=l(s);r.push({description:`Query parameter \`${o}\``,in:"query",name:o,required:s.kind!=="optional",schema:u(c)})}for(const[o,s]of Object.entries(e.params)){const c=l(s);r.push({description:`Path parameter \`${o}\``,in:t.has(o)?"path":"query",name:o,required:t.has(o)?!0:s.kind!=="optional",schema:u(c)})}return r},$=e=>e?{content:{"application/json":{schema:u(e)}},description:"Successful response."}:{content:{"application/json":{schema:{description:"Return shape is TS-inferred (no `.output()` declared); best-effort — any JSON."}}},description:"Successful response. The return shape is TypeScript-inferred and not declared via `.output()`, so it is documented best-effort."},w=e=>{const t=p(e.filePath),r=C(e),o={description:`${e.stream?"Streaming (SSE) ":""}HTTP route handler \`${e.exportName}\` (${e.method} ${e.path}).`,operationId:`${e.method.toLowerCase()}_${p(e.path)}`,responses:{200:$(e.output),204:{description:"No content (handler returned `undefined`)."},default:{$ref:m}},summary:`${e.method} ${e.path}`,tags:[t]};return r.length>0&&(o.parameters=r),Object.keys(e.body).length>0&&(o.requestBody={content:{"application/json":{schema:h(e.body)}},required:!0}),e.stream&&(o["x-lunora-stream"]="text/event-stream"),o},D=e=>{const t=p(e.filePath),r=`${t}:${e.exportName}`,o={additionalProperties:!1,properties:{args:h(e.args),functionPath:{const:r,type:"string"},shardKey:{description:"Optional shard key; omitted routes to the default shard.",type:"string"}},required:["functionPath"],type:"object"};return{operation:{description:`Invoke the \`${e.kind}\` \`${r}\` over the Lunora RPC envelope (POST /_lunora/rpc).`,operationId:r,requestBody:{content:{"application/json":{schema:o}},required:!0},responses:{200:$(e.output),default:{$ref:m}},summary:`${e.kind}: ${r}`,tags:[t],"x-lunora-function-kind":e.kind},pathKey:`/_lunora/rpc#${r}`}},L=(e,t)=>{if(e===void 0||t!=="get"||e.scope===void 0||e.maxAge===void 0)return{};const r={maxAge:e.maxAge,scope:e.scope,...e.staleWhileRevalidate===void 0?{}:{staleWhileRevalidate:e.staleWhileRevalidate},...e.tag===void 0?{}:{tag:e.tag},...e.vary===void 0?{}:{vary:e.vary}},o={"Cache-Control":{description:r.scope==="public"?"Caching policy. `public` applies only to an uncredentialed request — a request carrying `Authorization` or `Cookie` is always answered `private`.":"Caching policy. Restricted to the caller's own cache; never stored by a shared/edge cache.",schema:{example:b(r,r.scope),type:"string"}}};r.tag!==void 0&&(o["Cache-Tag"]={description:"Purge tag for `ctx.cache.purge({ tags: [...] })`.",schema:{example:r.tag,type:"string"}});const s=x(r);return s!==void 0&&(o.Vary={description:"Request headers this response varies by. The endpoint's own negotiated headers are merged in at runtime.",schema:{example:s,type:"string"}}),{headers:o}},I=e=>{const t=p(e.filePath),r=`${t}:${e.exportName}`,o=N(r);if(o===void 0)return;const s=q(e.kind),c=s==="GET",d={description:`Public REST endpoint for the \`${e.kind}\` \`${r}\` (opt-in via \`.expose({ rest: true })\`). Routed through the procedure, so auth / RLS / validators are enforced.`,operationId:`rest_${p(o)}`,responses:{200:{content:{"application/json":{schema:{description:"Procedure result. The shape is TS-inferred from the return type; best-effort — any JSON."}}},description:"Successful result (TypeScript-inferred return shape, documented best-effort).",...L(e.expose?.cache,c?"get":"post")},default:{$ref:m}},summary:`${s} ${o}`,tags:[t],"x-lunora-function-kind":e.kind};if(c){const n=Object.entries(e.args).map(([a,i])=>{const R=l(i);return{description:`Argument \`${a}\` (JSON-encoded for non-string values).`,in:"query",name:a,required:i.kind!=="optional",schema:u(R)}});return n.length>0&&(d.parameters=n),{method:"get",operation:d,path:o}}return d.requestBody={content:{"application/json":{schema:h(e.args)}},required:Object.keys(e.args).length>0},{method:"post",operation:d,path:o}},F=e=>{const t=e.version??"0.0.0",r={},o=new Set;for(const n of e.httpRoutes){const a=j(n.path),i=r[a]??{};i[n.method.toLowerCase()]=w(n),r[a]=i,o.add(p(n.filePath))}const s=e.functions.filter(n=>n.visibility!=="internal"&&n.kind!=="stream");for(const n of s){const{operation:a,pathKey:i}=D(n);r[i]={post:a},o.add(p(n.filePath))}for(const n of s){if(n.expose?.rest!==!0)continue;const a=I(n);if(a===void 0)continue;const i=r[a.path]??{};i[a.method]=a.operation,r[a.path]=i}const c=[...o].toSorted((n,a)=>n.localeCompare(a)).map(n=>({description:`Operations declared in \`lunora/${n}\`.`,name:n}));return{components:{responses:{LunoraError:{content:{"application/json":{schema:{additionalProperties:!1,description:"Standard Lunora error envelope.",properties:{error:{additionalProperties:!1,properties:{code:{description:"Machine-readable error code. Clients switch on this value.",enum:E,type:"string"},message:{description:"Human-readable error message (never echoes internal details).",type:"string"}},required:["code","message"],type:"object"}},required:["error"],type:"object"}}},description:"A Lunora error response. The HTTP status reflects the error code (e.g. BAD_REQUEST→400, UNAUTHORIZED→401, FORBIDDEN→403, NOT_FOUND→404)."}}},info:{description:"Auto-generated from @lunora/values-typed functions by @lunora/codegen. Do not edit — run `lunora codegen` to regenerate.",title:"Lunora API",version:t},openapi:"3.1.0",paths:r,tags:c}},U=e=>`${JSON.stringify(F(e),void 0,2)}
|
|
2
|
-
`,B=e=>`${S}export const openApiSpec = ${O(e,"Record<string, unknown>")};
|
|
3
|
-
`;export{F as buildOpenApiDocument,U as emitOpenApi,B as emitOpenApiModule};
|