@lunora/vite 1.0.0-alpha.70 → 1.0.0-alpha.71

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.
Files changed (3) hide show
  1. package/dist/index.d.mts +310 -314
  2. package/dist/index.d.ts +310 -314
  3. package/package.json +7 -7
package/dist/index.d.ts CHANGED
@@ -7,39 +7,39 @@ import { AddressInfo } from 'node:net';
7
7
  /** Options forwarded to `@cloudflare/vite-plugin`'s cloudflare plugin. */
8
8
  type CloudflarePluginOptions = Record<string, unknown>;
9
9
  /**
10
- * Options forwarded to `@visulima/vite-overlay`'s error-overlay plugin. Derived
11
- * from the plugin's own factory signature so it tracks the real shape
12
- * (`forwardConsole`, `forwardedConsoleMethods`, `reactPluginName`,
13
- * `solutionFinders`, `showBallonButton`, `vuePluginName`, …).
14
- */
10
+ * Options forwarded to `@visulima/vite-overlay`'s error-overlay plugin. Derived
11
+ * from the plugin's own factory signature so it tracks the real shape
12
+ * (`forwardConsole`, `forwardedConsoleMethods`, `reactPluginName`,
13
+ * `solutionFinders`, `showBallonButton`, `vuePluginName`, …).
14
+ */
15
15
  type OverlayPluginOptions = NonNullable<Parameters<typeof errorOverlayPlugin>[0]>;
16
16
  interface LunoraPluginOptions {
17
17
  /**
18
- * Allow a client-named NON-default shard / cross-shard fan-out WITHOUT an
19
- * `authorizeShard`/`authorizeFanOut` callback. The auto-composed class-A worker
20
- * (`virtual:lunora/worker`) default-denies such access (403 `FORBIDDEN_SHARD`);
21
- * set this `true` to opt into open access — only safe when every table is
22
- * protected by per-row RLS. A production sharded app should configure
23
- * `authorizeShard` instead (via a hand-written class-B worker). Defaults to `false`.
24
- */
18
+ * Allow a client-named NON-default shard / cross-shard fan-out WITHOUT an
19
+ * `authorizeShard`/`authorizeFanOut` callback. The auto-composed class-A worker
20
+ * (`virtual:lunora/worker`) default-denies such access (403 `FORBIDDEN_SHARD`);
21
+ * set this `true` to opt into open access — only safe when every table is
22
+ * protected by per-row RLS. A production sharded app should configure
23
+ * `authorizeShard` instead (via a hand-written class-B worker). Defaults to `false`.
24
+ */
25
25
  allowUnauthenticatedShardAccess?: boolean;
26
26
  /**
27
- * Which machine-readable API spec(s) codegen emits into `_generated/`.
28
- * `"openapi"` (default) writes `openapi.json` (OpenAPI 3.1; RPC + REST),
29
- * `"openrpc"` writes `openrpc.json` (OpenRPC 1.x; RPC-only), `"both"` writes
30
- * both, and `"none"` writes neither. Forwarded to `runCodegen({ apiSpec })`;
31
- * the value set is derived from `CodegenOptions` so it can't drift.
32
- */
27
+ * Which machine-readable API spec(s) codegen emits into `_generated/`.
28
+ * `"openapi"` (default) writes `openapi.json` (OpenAPI 3.1; RPC + REST),
29
+ * `"openrpc"` writes `openrpc.json` (OpenRPC 1.x; RPC-only), `"both"` writes
30
+ * both, and `"none"` writes neither. Forwarded to `runCodegen({ apiSpec })`;
31
+ * the value set is derived from `CodegenOptions` so it can't drift.
32
+ */
33
33
  apiSpec?: CodegenOptions["apiSpec"];
34
34
  /** Pass through to `@cloudflare/vite-plugin`. Pass `false` to opt out. Defaults to `true`. */
35
35
  cloudflare?: boolean | CloudflarePluginOptions;
36
36
  /** Directory name (relative to `projectRoot`) where generated files are written. Defaults to `"lunora/_generated"`. */
37
37
  generatedDir?: string;
38
38
  /**
39
- * Inject `@visulima/vite-overlay` for runtime errors (dev only). Pass
40
- * `false` to opt out, or an options object to forward to the overlay.
41
- * Defaults to `true`.
42
- */
39
+ * Inject `@visulima/vite-overlay` for runtime errors (dev only). Pass
40
+ * `false` to opt out, or an options object to forward to the overlay.
41
+ * Defaults to `true`.
42
+ */
43
43
  overlay?: boolean | OverlayPluginOptions;
44
44
  /** Project root containing the `lunora/` directory. Defaults to `process.cwd()`. */
45
45
  projectRoot?: string;
@@ -63,127 +63,125 @@ interface ResolvedLunoraPluginOptions {
63
63
  validateWrangler: boolean;
64
64
  }
65
65
  /**
66
- * The plugins `lunora()` returns. A mutable `Plugin[]` (not `ReadonlyArray`) so
67
- * it slots directly into Vite's `plugins` — which recursively flattens nested
68
- * plugin arrays — without a spread: `plugins: [lunora()]`.
69
- */
66
+ * The plugins `lunora()` returns. A mutable `Plugin[]` (not `ReadonlyArray`) so
67
+ * it slots directly into Vite's `plugins` — which recursively flattens nested
68
+ * plugin arrays — without a spread: `plugins: [lunora()]`.
69
+ */
70
70
  type LunoraPlugins = Plugin[];
71
71
  /**
72
- * Vite plugin that runs `@lunora/codegen` on startup and on file changes
73
- * inside the lunora schema directory.
74
- */
72
+ * Vite plugin that runs `@lunora/codegen` on startup and on file changes
73
+ * inside the lunora schema directory.
74
+ */
75
75
  declare const codegenPlugin: (options: ResolvedLunoraPluginOptions) => Plugin;
76
76
  /**
77
- * Dev-only plugin that tails the local dev containers' own stdout/stderr in the
78
- * Vite terminal.
79
- *
80
- * `@cloudflare/vite-plugin` builds and runs each declared container locally via
81
- * Docker (image `cloudflare-dev/&lt;class>:&lt;id>`) but only forwards the *worker's*
82
- * console — the container process's own output is otherwise invisible. This
83
- * plugin attaches to those Docker log streams (via `@lunora/config`'s
84
- * `streamContainerLogs`, which lazy-loads `dockerode`) and prints each line
85
- * through Vite's logger, branded and tagged `container:&lt;name>`.
86
- *
87
- * A no-op when the project declares no containers (the common case): discovery
88
- * returns an empty list, so `dockerode` is never imported and no Docker work
89
- * starts. Set `LUNORA_CONTAINER_LOGS=0` to opt out. A missing/stopped Docker
90
- * engine degrades to a single warning rather than breaking dev.
91
- */
77
+ * Dev-only plugin that tails the local dev containers' own stdout/stderr in the
78
+ * Vite terminal.
79
+ *
80
+ * `@cloudflare/vite-plugin` builds and runs each declared container locally via
81
+ * Docker (image `cloudflare-dev/&lt;class>:&lt;id>`) but only forwards the *worker's*
82
+ * console — the container process's own output is otherwise invisible. This
83
+ * plugin attaches to those Docker log streams (via `@lunora/config`'s
84
+ * `streamContainerLogs`, which lazy-loads `dockerode`) and prints each line
85
+ * through Vite's logger, branded and tagged `container:&lt;name>`.
86
+ *
87
+ * A no-op when the project declares no containers (the common case): discovery
88
+ * returns an empty list, so `dockerode` is never imported and no Docker work
89
+ * starts. Set `LUNORA_CONTAINER_LOGS=0` to opt out. A missing/stopped Docker
90
+ * engine degrades to a single warning rather than breaking dev.
91
+ */
92
92
  declare const containerLogsPlugin: (options: ResolvedLunoraPluginOptions) => Plugin;
93
93
  /** Vite plugin (serve-only) that writes the dev-server state record on listen and clears it on close. */
94
94
  declare const devStatePlugin: (options: ResolvedLunoraPluginOptions) => Plugin;
95
95
  /**
96
- * Dev-only Vite plugin that prepares `.dev.vars` before the worker boots.
97
- * `@cloudflare/vite-plugin` loads `.dev.vars` into the worker's `env`, but the
98
- * file is gitignored — so a fresh clone has none and the worker throws on the
99
- * first required secret (e.g. `AUTH_SECRET is required`). Two steps, both shared
100
- * with `lunora dev` via `@lunora/config`.
101
- *
102
- * First, {@link ensureDevVariables}: when a `.dev.vars.example` exists, prompt
103
- * to generate `.dev.vars` from it with secrets auto-filled. Second,
104
- * {@link fillDevSecrets}: fill any empty/placeholder secret already in
105
- * `.dev.vars` (a `lunora add`-scaffolded project writes secrets blank) and
106
- * ensure `LUNORA_ADMIN_TOKEN` is present + generated — so the worker boots with
107
- * working secrets and the Studio authenticates without its login gate. No
108
- * prompt: it only generates locally-derivable values and never overwrites a real
109
- * one.
110
- *
111
- * Runs in `configResolved` (awaited by Vite) so it completes before the
112
- * Cloudflare plugin reads the file. Non-interactive runs decline silently.
113
- */
96
+ * Dev-only Vite plugin that prepares `.dev.vars` before the worker boots.
97
+ * `@cloudflare/vite-plugin` loads `.dev.vars` into the worker's `env`, but the
98
+ * file is gitignored — so a fresh clone has none and the worker throws on the
99
+ * first required secret (e.g. `AUTH_SECRET is required`). Two steps, both shared
100
+ * with `lunora dev` via `@lunora/config`.
101
+ *
102
+ * First, {@link ensureDevVariables}: when a `.dev.vars.example` exists, prompt
103
+ * to generate `.dev.vars` from it with secrets auto-filled. Second,
104
+ * {@link fillDevSecrets}: fill any empty/placeholder secret already in
105
+ * `.dev.vars` (a `lunora add`-scaffolded project writes secrets blank) and
106
+ * ensure `LUNORA_ADMIN_TOKEN` is present + generated — so the worker boots with
107
+ * working secrets and the Studio authenticates without its login gate. No
108
+ * prompt: it only generates locally-derivable values and never overwrites a real
109
+ * one.
110
+ *
111
+ * Runs in `configResolved` (awaited by Vite) so it completes before the
112
+ * Cloudflare plugin reads the file. Non-interactive runs decline silently.
113
+ */
114
114
  declare const devVariablesPlugin: (options: ResolvedLunoraPluginOptions) => Plugin;
115
115
  /**
116
- * Worker env var the dev tooling sets so the Lunora runtime recognises a
117
- * development deployment (`@lunora/do`'s `isDevEnvironment`) and therefore
118
- * streams every RPC dispatch summary to the terminal by default — the
119
- * `lunora dev` CLI sets the same var via `wrangler dev --var`.
120
- *
121
- * It is injected ONLY during `vite` serve, never a production `vite build`, so
122
- * it can never leak into a deployed worker. A `WORKER_ENV` the user already
123
- * declares (in `wrangler.jsonc` `[vars]` or `.dev.vars`) takes precedence, so
124
- * this only fills the gap when none is set.
125
- */
116
+ * Worker env var the dev tooling sets so the Lunora runtime recognises a
117
+ * development deployment (`@lunora/do`'s `isDevEnvironment`) and therefore
118
+ * streams every RPC dispatch summary to the terminal by default — the
119
+ * `lunora dev` CLI sets the same var via `wrangler dev --var`.
120
+ *
121
+ * It is injected ONLY during `vite` serve, never a production `vite build`, so
122
+ * it can never leak into a deployed worker. A `WORKER_ENV` the user already
123
+ * declares (in `wrangler.jsonc` `[vars]` or `.dev.vars`) takes precedence, so
124
+ * this only fills the gap when none is set.
125
+ */
126
126
  declare const DEV_WORKER_ENV_VAR = "WORKER_ENV";
127
127
  declare const DEV_WORKER_ENV_VALUE = "development";
128
- /** The structural slice of `@cloudflare/vite-plugin`'s worker config we read/write. */
129
128
  /**
130
- * Wrap the cloudflare-plugin options so the dev worker's `vars` gain a
131
- * `WORKER_ENV` of `development` when — and only when — `isServe()` reports a
132
- * `vite` serve. Any `config` customizer the caller already supplied is
133
- * preserved and applied first; an existing `WORKER_ENV` wins, so a user
134
- * override is never clobbered.
135
- */
129
+ * Wrap the cloudflare-plugin options so the dev worker's `vars` gain a
130
+ * `WORKER_ENV` of `development` when — and only when — `isServe()` reports a
131
+ * `vite` serve. Any `config` customizer the caller already supplied is
132
+ * preserved and applied first; an existing `WORKER_ENV` wins, so a user
133
+ * override is never clobbered.
134
+ */
136
135
  declare const withDevWorkerEnv: (options: CloudflarePluginOptions, isServe: () => boolean) => CloudflarePluginOptions;
137
136
  /**
138
- * A Vite plugin that captures the resolved command (`serve` vs `build`) so
139
- * {@link withDevWorkerEnv} injects the dev var only during `vite`, plus an
140
- * `isServe` probe sharing the same closure. `enforce: "pre"` so the command is
141
- * captured before the cloudflare plugin resolves its worker config.
142
- */
137
+ * A Vite plugin that captures the resolved command (`serve` vs `build`) so
138
+ * {@link withDevWorkerEnv} injects the dev var only during `vite`, plus an
139
+ * `isServe` probe sharing the same closure. `enforce: "pre"` so the command is
140
+ * captured before the cloudflare plugin resolves its worker config.
141
+ */
143
142
  declare const createCommandProbe: () => {
144
143
  isServe: () => boolean;
145
144
  plugin: Plugin;
146
145
  };
147
146
  /**
148
- * Mutable, plugin-shared context. The `lunora()` factory creates one instance
149
- * and threads it through every Lunora sub-plugin, so detection runs once and
150
- * downstream plugins (codegen, composition, the dev hint) read the same result
151
- * without re-scanning `package.json`. PLAN4 §2.4.
152
- */
147
+ * Mutable, plugin-shared context. The `lunora()` factory creates one instance
148
+ * and threads it through every Lunora sub-plugin, so detection runs once and
149
+ * downstream plugins (codegen, composition, the dev hint) read the same result
150
+ * without re-scanning `package.json`. PLAN4 §2.4.
151
+ */
153
152
  interface LunoraPluginContext {
154
153
  /** The detected framework + class, populated during `config` / `configResolved`. `undefined` until detection runs. */
155
154
  framework?: FrameworkDetection;
156
155
  }
157
- /** Create an empty shared context object for one `lunora()` invocation. */
158
156
  /**
159
- * The virtual module id the Lunora plugin resolves to a generated, class-A
160
- * worker entry. A class-A template points its wrangler `main` at this id (or
161
- * re-exports it from a one-line `src/server.ts`) and never hand-writes
162
- * `createWorker({ httpRouter })` — the plugin composes the framework's SSR
163
- * handler under `composeWorker`'s `httpRouter` seam for it.
164
- *
165
- * Exposed publicly so `@lunora/cli`'s build/deploy path and the templates can
166
- * reference the same constant rather than re-typing the literal.
167
- */
157
+ * The virtual module id the Lunora plugin resolves to a generated, class-A
158
+ * worker entry. A class-A template points its wrangler `main` at this id (or
159
+ * re-exports it from a one-line `src/server.ts`) and never hand-writes
160
+ * `createWorker({ httpRouter })` — the plugin composes the framework's SSR
161
+ * handler under `composeWorker`'s `httpRouter` seam for it.
162
+ *
163
+ * Exposed publicly so `@lunora/cli`'s build/deploy path and the templates can
164
+ * reference the same constant rather than re-typing the literal.
165
+ */
168
166
  declare const LUNORA_WORKER_VIRTUAL_ID: string;
169
167
  /**
170
- * Per-class-A-framework wiring the generated worker entry needs: how to obtain
171
- * the framework's SSR handler as a `composeWorker`-compatible `httpRouter`.
172
- *
173
- * `imports` is the full import statement(s) the generated entry needs (each
174
- * framework controls its own import shape — a namespace import, or a named one);
175
- * `handler` is a JS expression (evaluated in the generated module's scope, where
176
- * `imports`' symbols are in scope) that yields an `HttpRouterLike`
177
- * (`{ fetch(request, env?, ctx?) }`). Both are data — not codegen branches — so
178
- * the set of supported class-A frameworks is one readable table and adding a
179
- * framework is a pure data edit.
180
- *
181
- * Honesty note: these handler expressions encode each framework's *documented*
182
- * Cloudflare SSR-handler shape — the same expressions the hand-wired template
183
- * entries use today (React Router's `createRequestHandler` over its virtual
184
- * server build; SolidStart's `cloudflare-module` handler; TanStack Start's
185
- * server entry). The plugin just emits them so the developer doesn't.
186
- */
168
+ * Per-class-A-framework wiring the generated worker entry needs: how to obtain
169
+ * the framework's SSR handler as a `composeWorker`-compatible `httpRouter`.
170
+ *
171
+ * `imports` is the full import statement(s) the generated entry needs (each
172
+ * framework controls its own import shape — a namespace import, or a named one);
173
+ * `handler` is a JS expression (evaluated in the generated module's scope, where
174
+ * `imports`' symbols are in scope) that yields an `HttpRouterLike`
175
+ * (`{ fetch(request, env?, ctx?) }`). Both are data — not codegen branches — so
176
+ * the set of supported class-A frameworks is one readable table and adding a
177
+ * framework is a pure data edit.
178
+ *
179
+ * Honesty note: these handler expressions encode each framework's *documented*
180
+ * Cloudflare SSR-handler shape — the same expressions the hand-wired template
181
+ * entries use today (React Router's `createRequestHandler` over its virtual
182
+ * server build; SolidStart's `cloudflare-module` handler; TanStack Start's
183
+ * server entry). The plugin just emits them so the developer doesn't.
184
+ */
187
185
  interface ClassAWiring {
188
186
  /** JS expression yielding the `httpRouter` ({ fetch }), referencing symbols brought in by `imports`. */
189
187
  handler: string;
@@ -192,83 +190,83 @@ interface ClassAWiring {
192
190
  }
193
191
  declare const CLASS_A_WIRING: Readonly<Partial<Record<DetectedFramework, ClassAWiring>>>;
194
192
  /**
195
- * Whether the detected framework is one the plugin can auto-compose. Only
196
- * class-A frameworks with a known SSR-handler wiring qualify; everything else
197
- * (class B/C, `none`) falls back to the existing flow.
198
- */
193
+ * Whether the detected framework is one the plugin can auto-compose. Only
194
+ * class-A frameworks with a known SSR-handler wiring qualify; everything else
195
+ * (class B/C, `none`) falls back to the existing flow.
196
+ */
199
197
  declare const isAutoComposable: (context: LunoraPluginContext) => boolean;
200
198
  /**
201
- * Build the source of the virtual class-A worker entry. Pure (no fs / no Vite),
202
- * so the emitted composition is unit-testable in isolation.
203
- *
204
- * The emitted module imports the framework SSR handler + the project's
205
- * generated artifacts (functions registry, OpenAPI doc, `createShardDO`) and
206
- * composes them through `composeWorker` — reserved `/_lunora/*` paths route to
207
- * Lunora, everything else falls through to the framework SSR handler. The
208
- * `generatedImportBase` MUST be an absolute filesystem path to the `_generated`
209
- * directory. Virtual modules have no real filesystem path, so relative specifiers
210
- * like `./lunora/_generated/functions` cannot be resolved by Vite/rolldown from a
211
- * virtual module id. Absolute paths are resolved correctly in all environments
212
- * (Vite 8 + rolldown 1.x confirmed).
213
- */
199
+ * Build the source of the virtual class-A worker entry. Pure (no fs / no Vite),
200
+ * so the emitted composition is unit-testable in isolation.
201
+ *
202
+ * The emitted module imports the framework SSR handler + the project's
203
+ * generated artifacts (functions registry, OpenAPI doc, `createShardDO`) and
204
+ * composes them through `composeWorker` — reserved `/_lunora/*` paths route to
205
+ * Lunora, everything else falls through to the framework SSR handler. The
206
+ * `generatedImportBase` MUST be an absolute filesystem path to the `_generated`
207
+ * directory. Virtual modules have no real filesystem path, so relative specifiers
208
+ * like `./lunora/_generated/functions` cannot be resolved by Vite/rolldown from a
209
+ * virtual module id. Absolute paths are resolved correctly in all environments
210
+ * (Vite 8 + rolldown 1.x confirmed).
211
+ */
214
212
  declare const buildWorkerEntrySource: (framework: DetectedFramework, generatedImportBase: string, hasContainers?: boolean, useUmbrella?: boolean, allowUnauthenticatedShardAccess?: boolean) => string;
215
213
  /**
216
- * Vite plugin that auto-composes a detected class-A meta-framework's SSR
217
- * handler with Lunora into one Cloudflare Worker (PLAN4 §2.4 / §3 class-A row).
218
- *
219
- * Mechanism: it resolves the {@link LUNORA_WORKER_VIRTUAL_ID} virtual module to
220
- * a generated worker entry that wires the framework SSR handler under
221
- * `composeWorker`'s `httpRouter` seam — so the developer never writes
222
- * `createWorker({ httpRouter })`. The composed worker is an ordinary module
223
- * entry, so it HMRs under `@cloudflare/vite-plugin` exactly like a hand-written
224
- * one (PLAN4 M5 risk #5): the virtual entry only imports the framework handler
225
- * and the generated artifacts, both of which the framework's plugin + codegen
226
- * already make HMR-aware.
227
- *
228
- * Safety: it is a strict no-op unless `context.framework.class === "A"` with a
229
- * known wiring. For class-C (SPA) projects and undetected frameworks it
230
- * resolves/loads nothing. `cloudflare: false` does NOT disable the virtual
231
- * entry — it only means "don't add the Cloudflare Vite plugin a second time"
232
- * (the user supplied it themselves); the composed worker must still be
233
- * resolvable so the user-supplied CF plugin can find the wrangler `main`.
234
- */
214
+ * Vite plugin that auto-composes a detected class-A meta-framework's SSR
215
+ * handler with Lunora into one Cloudflare Worker (PLAN4 §2.4 / §3 class-A row).
216
+ *
217
+ * Mechanism: it resolves the {@link LUNORA_WORKER_VIRTUAL_ID} virtual module to
218
+ * a generated worker entry that wires the framework SSR handler under
219
+ * `composeWorker`'s `httpRouter` seam — so the developer never writes
220
+ * `createWorker({ httpRouter })`. The composed worker is an ordinary module
221
+ * entry, so it HMRs under `@cloudflare/vite-plugin` exactly like a hand-written
222
+ * one (PLAN4 M5 risk #5): the virtual entry only imports the framework handler
223
+ * and the generated artifacts, both of which the framework's plugin + codegen
224
+ * already make HMR-aware.
225
+ *
226
+ * Safety: it is a strict no-op unless `context.framework.class === "A"` with a
227
+ * known wiring. For class-C (SPA) projects and undetected frameworks it
228
+ * resolves/loads nothing. `cloudflare: false` does NOT disable the virtual
229
+ * entry — it only means "don't add the Cloudflare Vite plugin a second time"
230
+ * (the user supplied it themselves); the composed worker must still be
231
+ * resolvable so the user-supplied CF plugin can find the wrangler `main`.
232
+ */
235
233
  declare const frameworkComposePlugin: (options: ResolvedLunoraPluginOptions, context: LunoraPluginContext) => Plugin;
236
234
  /**
237
- * The custom HMR event the Lunora Vite plugin sends on the client environment's
238
- * hot channel after a successful codegen run, in place of the old blanket
239
- * browser `full-reload`. The generated `api`/`server` modules are just
240
- * `FunctionReference` metadata, so Vite's granular module HMR re-imports the
241
- * changed `_generated/*` in place; this event is a non-destructive nudge that
242
- * lets open WebSocket subscriptions, optimistic state, the offline queue, and
243
- * form state survive a schema save.
244
- *
245
- * Kept in its own module (a single source of truth) so the codegen plugin —
246
- * whose sole export is the plugin factory — can reference it without becoming a
247
- * mixed default+named module, and so any future client-side listener can agree
248
- * on the exact string.
249
- *
250
- * There is no first-party client listener yet: `@lunora/client` / `@lunora/react`
251
- * ship as pre-bundled, side-effect-free dependencies where `import.meta.hot` is
252
- * `undefined` at runtime (Vite's dep optimizer), so a listener there would be
253
- * dead (and tree-shaken) code. A future app-local or codegen-emitted listener
254
- * can import this constant to re-validate active queries over the live socket.
255
- */
235
+ * The custom HMR event the Lunora Vite plugin sends on the client environment's
236
+ * hot channel after a successful codegen run, in place of the old blanket
237
+ * browser `full-reload`. The generated `api`/`server` modules are just
238
+ * `FunctionReference` metadata, so Vite's granular module HMR re-imports the
239
+ * changed `_generated/*` in place; this event is a non-destructive nudge that
240
+ * lets open WebSocket subscriptions, optimistic state, the offline queue, and
241
+ * form state survive a schema save.
242
+ *
243
+ * Kept in its own module (a single source of truth) so the codegen plugin —
244
+ * whose sole export is the plugin factory — can reference it without becoming a
245
+ * mixed default+named module, and so any future client-side listener can agree
246
+ * on the exact string.
247
+ *
248
+ * There is no first-party client listener yet: `@lunora/client` / `@lunora/react`
249
+ * ship as pre-bundled, side-effect-free dependencies where `import.meta.hot` is
250
+ * `undefined` at runtime (Vite's dep optimizer), so a listener there would be
251
+ * dead (and tree-shaken) code. A future app-local or codegen-emitted listener
252
+ * can import this constant to re-validate active queries over the live socket.
253
+ */
256
254
  declare const LUNORA_API_UPDATED_EVENT = "lunora:api-updated";
257
255
  /**
258
- * Vite plugin (serve-only) that formats Lunora worker logs in the terminal.
259
- * Patches `process.stdout`/`process.stderr` fresh for each dev-server generation
260
- * and restores them when that server closes.
261
- */
256
+ * Vite plugin (serve-only) that formats Lunora worker logs in the terminal.
257
+ * Patches `process.stdout`/`process.stderr` fresh for each dev-server generation
258
+ * and restores them when that server closes.
259
+ */
262
260
  declare const logStreamPlugin: () => Plugin;
263
261
  /** The decision a {@link planViteRemoteBindings} call returns. */
264
262
  interface ViteRemotePlan {
265
263
  /** Idempotent disposer for the temp config; always present + safe to call. */
266
264
  cleanup: () => void;
267
265
  /**
268
- * Absolute path to the materialized temp wrangler config to hand the
269
- * cloudflare plugin's `configPath`, or `undefined` when remote mode is off
270
- * or nothing was materialized (no eligible binding, no wrangler file, …).
271
- */
266
+ * Absolute path to the materialized temp wrangler config to hand the
267
+ * cloudflare plugin's `configPath`, or `undefined` when remote mode is off
268
+ * or nothing was materialized (no eligible binding, no wrangler file, …).
269
+ */
272
270
  configPath?: string;
273
271
  /** Whether remote mode was requested for this dev session. */
274
272
  enabled: boolean;
@@ -287,179 +285,177 @@ interface PlanViteRemoteOptions {
287
285
  remoteEnv?: string;
288
286
  }
289
287
  /**
290
- * Decide whether the Vite dev worker uses remote bindings and, if so,
291
- * materialize the temp config. Pure decision + a single fs write via the
292
- * injected materializer; returns a `cleanup` for the dev server's close hook.
293
- *
294
- * There is no `--remote` flag on the Vite path (Vite has no Lunora CLI flags),
295
- * so the precedence reduces to `LUNORA_REMOTE` env > `lunora.json` `remote`.
296
- */
288
+ * Decide whether the Vite dev worker uses remote bindings and, if so,
289
+ * materialize the temp config. Pure decision + a single fs write via the
290
+ * injected materializer; returns a `cleanup` for the dev server's close hook.
291
+ *
292
+ * There is no `--remote` flag on the Vite path (Vite has no Lunora CLI flags),
293
+ * so the precedence reduces to `LUNORA_REMOTE` env > `lunora.json` `remote`.
294
+ */
297
295
  declare const planViteRemoteBindings: (options: PlanViteRemoteOptions) => ViteRemotePlan;
298
296
  /**
299
- * Wrap the cloudflare-plugin options so the dev worker loads the materialized
300
- * remote temp config (via `configPath`) when — and only when — remote mode is
301
- * on and a temp config was materialized. A `configPath` the caller already set
302
- * wins (their explicit choice).
303
- *
304
- * Pure decision only — the serve-vs-build gate lives in
305
- * {@link remoteBindingsConfigPlugin}'s `config` hook, because the resolved Vite
306
- * `command` is unknown at plugin-factory time (when this runs). An eager serve
307
- * check here would always read `command` as undefined and strip `configPath`.
308
- */
297
+ * Wrap the cloudflare-plugin options so the dev worker loads the materialized
298
+ * remote temp config (via `configPath`) when — and only when — remote mode is
299
+ * on and a temp config was materialized. A `configPath` the caller already set
300
+ * wins (their explicit choice).
301
+ *
302
+ * Pure decision only — the serve-vs-build gate lives in
303
+ * {@link remoteBindingsConfigPlugin}'s `config` hook, because the resolved Vite
304
+ * `command` is unknown at plugin-factory time (when this runs). An eager serve
305
+ * check here would always read `command` as undefined and strip `configPath`.
306
+ */
309
307
  declare const withRemoteBindings: (options: CloudflarePluginOptions, plan: ViteRemotePlan) => CloudflarePluginOptions;
310
308
  /**
311
- * A `enforce: "pre"` plugin whose `config` hook injects the materialized remote
312
- * temp config into the cloudflare plugin's `configPath` — but only on a `vite`
313
- * serve, never a production build (so the deployed worker is never affected).
314
- *
315
- * The deferral is the whole point: at plugin-factory time Vite has not yet told
316
- * us `serve` vs `build`, so the check must run in a `config` hook (where
317
- * `env.command` is known). It mutates the SAME options object handed to
318
- * `cloudflare()` in place — the cloudflare plugin reads `pluginConfig.configPath`
319
- * lazily inside its own `config` hook, which runs after this `enforce: "pre"`
320
- * one, so the injection takes effect. An eager factory-time serve check (the old
321
- * behaviour) always saw `command` undefined and silently dropped the path, so
322
- * remote bindings never activated on `vite dev`.
323
- *
324
- * When remote mode was requested but nothing materialized (no eligible binding,
325
- * no wrangler file, …), the plan's `reason` is logged so the degradation isn't
326
- * silent.
327
- */
309
+ * A `enforce: "pre"` plugin whose `config` hook injects the materialized remote
310
+ * temp config into the cloudflare plugin's `configPath` — but only on a `vite`
311
+ * serve, never a production build (so the deployed worker is never affected).
312
+ *
313
+ * The deferral is the whole point: at plugin-factory time Vite has not yet told
314
+ * us `serve` vs `build`, so the check must run in a `config` hook (where
315
+ * `env.command` is known). It mutates the SAME options object handed to
316
+ * `cloudflare()` in place — the cloudflare plugin reads `pluginConfig.configPath`
317
+ * lazily inside its own `config` hook, which runs after this `enforce: "pre"`
318
+ * one, so the injection takes effect. An eager factory-time serve check (the old
319
+ * behaviour) always saw `command` undefined and silently dropped the path, so
320
+ * remote bindings never activated on `vite dev`.
321
+ *
322
+ * When remote mode was requested but nothing materialized (no eligible binding,
323
+ * no wrangler file, …), the plan's `reason` is logged so the degradation isn't
324
+ * silent.
325
+ */
328
326
  declare const remoteBindingsConfigPlugin: (options: CloudflarePluginOptions, plan: ViteRemotePlan) => Plugin;
329
327
  /**
330
- * A tiny Vite plugin that runs the remote temp-config disposer when the dev
331
- * server tears down (`buildEnd` fires on close in serve; `closeBundle` covers
332
- * the build/close path). Idempotent cleanup means firing on both is safe.
333
- */
328
+ * A tiny Vite plugin that runs the remote temp-config disposer when the dev
329
+ * server tears down (`buildEnd` fires on close in serve; `closeBundle` covers
330
+ * the build/close path). Idempotent cleanup means firing on both is safe.
331
+ */
334
332
  declare const remoteBindingsCleanupPlugin: (cleanup: () => void) => Plugin;
335
333
  /**
336
- * A `@visulima/vite-overlay` solution finder. Derived from the overlay's own
337
- * options type so the shape can't drift from the installed package. The overlay
338
- * runs every finder it's given (custom finders first, then its built-ins),
339
- * sorted by `priority` descending, and shows the first non-`undefined` result.
340
- *
341
- * Note: this type (and {@link Solution}) is re-exported from `@lunora/vite` and
342
- * intentionally tracks the installed `@visulima/vite-overlay` — if a future
343
- * overlay release changes the finder contract, that surfaces here as a compile
344
- * error rather than a silent drift.
345
- */
334
+ * A `@visulima/vite-overlay` solution finder. Derived from the overlay's own
335
+ * options type so the shape can't drift from the installed package. The overlay
336
+ * runs every finder it's given (custom finders first, then its built-ins),
337
+ * sorted by `priority` descending, and shows the first non-`undefined` result.
338
+ *
339
+ * Note: this type (and {@link Solution}) is re-exported from `@lunora/vite` and
340
+ * intentionally tracks the installed `@visulima/vite-overlay` — if a future
341
+ * overlay release changes the finder contract, that surfaces here as a compile
342
+ * error rather than a silent drift.
343
+ */
346
344
  type SolutionFinder = NonNullable<OverlayPluginOptions["solutionFinders"]>[number];
347
345
  /** What a finder may return: a Markdown-rendered `{ header?, body }`, or `undefined` to defer. */
348
346
  type Solution = NonNullable<Awaited<ReturnType<SolutionFinder["handle"]>>>;
349
347
  /**
350
- * Lunora's solution finder for the dev error overlay. A single finder that
351
- * delegates to `@lunora/codegen`'s shared rule table (the same table the
352
- * standalone `lunora dev` CLI prints to the terminal) and returns the first
353
- * match — so one `priority` slot covers every Lunora rule and the overlay's
354
- * built-in finders still run for anything we don't recognize (we return
355
- * `undefined`).
356
- *
357
- * Priority is high so a Lunora-specific hint wins over the overlay's generic
358
- * finder for the same error; a user's own finder can still outrank it with a
359
- * higher `priority`.
360
- */
348
+ * Lunora's solution finder for the dev error overlay. A single finder that
349
+ * delegates to `@lunora/codegen`'s shared rule table (the same table the
350
+ * standalone `lunora dev` CLI prints to the terminal) and returns the first
351
+ * match — so one `priority` slot covers every Lunora rule and the overlay's
352
+ * built-in finders still run for anything we don't recognize (we return
353
+ * `undefined`).
354
+ *
355
+ * Priority is high so a Lunora-specific hint wins over the overlay's generic
356
+ * finder for the same error; a user's own finder can still outrank it with a
357
+ * higher `priority`.
358
+ */
361
359
  declare const lunoraSolutionFinder: SolutionFinder;
362
360
  /** The finders Lunora injects into the overlay by default. */
363
361
  declare const lunoraSolutionFinders: ReadonlyArray<SolutionFinder>;
364
362
  /** Dev-server path the studio SPA is served from. */
365
363
  declare const STUDIO_PATH = "/__lunora";
366
- /** Static asset routes the studio document references. */
367
-
368
364
  /**
369
- * Build the user-facing studio URL from the dev server's resolved address.
370
- * Pure so it can be unit-tested without a live server. Prefers Vite's own
371
- * `resolvedUrls.local` (honours `host` / `base` / https); falls back to the raw
372
- * socket address, bracketing IPv6 and normalising the wildcard host.
373
- */
365
+ * Build the user-facing studio URL from the dev server's resolved address.
366
+ * Pure so it can be unit-tested without a live server. Prefers Vite's own
367
+ * `resolvedUrls.local` (honours `host` / `base` / https); falls back to the raw
368
+ * socket address, bracketing IPv6 and normalising the wildcard host.
369
+ */
374
370
  declare const buildStudioUrl: (input: {
375
371
  address?: AddressInfo | string;
376
372
  base?: string;
377
373
  resolvedLocal?: string;
378
374
  }) => string;
379
375
  /**
380
- * Vite plugin that serves the composed Lunora studio at
381
- * {@link STUDIO_PATH} during dev and prints its URL once the server is
382
- * listening. Dev-only (`apply: "serve"`); it adds nothing to production builds.
383
- *
384
- * Because `lunora dev` spawns Vite, this makes the studio available on
385
- * `lunora dev` and on a plain `vite` with no per-project files. The studio
386
- * is served as a prebuilt static bundle, independent of the host app.
387
- */
376
+ * Vite plugin that serves the composed Lunora studio at
377
+ * {@link STUDIO_PATH} during dev and prints its URL once the server is
378
+ * listening. Dev-only (`apply: "serve"`); it adds nothing to production builds.
379
+ *
380
+ * Because `lunora dev` spawns Vite, this makes the studio available on
381
+ * `lunora dev` and on a plain `vite` with no per-project files. The studio
382
+ * is served as a prebuilt static bundle, independent of the host app.
383
+ */
388
384
  declare const studioPlugin: () => Plugin;
389
385
  /**
390
- * When a module under `lunora/` throws while the Worker entry is first
391
- * evaluated, `@cloudflare/vite-plugin` surfaces the failure from deep inside
392
- * its `runner-worker` running in `workerd`. The real error crosses a workerd
393
- * RPC boundary on the way out, which drops the user-code stack frames — so all
394
- * the dev server sees is a bare, file-less message like:
395
- *
396
- * ```
397
- * TypeError: Cannot read properties of undefined (reading 'string')
398
- * at runInRunnerObject (workers/runner-worker/index.js:107:3)
399
- * at getWorkerEntryExportTypes (workers/runner-worker/index.js:246:24)
400
- * ```
401
- *
402
- * The classic cause is a **circular import**: a `lunora/` query/mutation/action
403
- * module runs `mutation({ args: { x: v.string() } })` at the top level while the
404
- * module it imported `v`/`query`/`mutation` from is still mid-initialization, so
405
- * those bindings read as `undefined`. The message names a validator method
406
- * (`'string'`, `'id'`, …) but never the file.
407
- *
408
- * We can't recover the dropped frames at this layer, but we can recognise the
409
- * shape of the failure and append an actionable hint pointing at the likely
410
- * cause — turning a dead-end stack into something a user can act on.
411
- */
386
+ * When a module under `lunora/` throws while the Worker entry is first
387
+ * evaluated, `@cloudflare/vite-plugin` surfaces the failure from deep inside
388
+ * its `runner-worker` running in `workerd`. The real error crosses a workerd
389
+ * RPC boundary on the way out, which drops the user-code stack frames — so all
390
+ * the dev server sees is a bare, file-less message like:
391
+ *
392
+ * ```
393
+ * TypeError: Cannot read properties of undefined (reading 'string')
394
+ * at runInRunnerObject (workers/runner-worker/index.js:107:3)
395
+ * at getWorkerEntryExportTypes (workers/runner-worker/index.js:246:24)
396
+ * ```
397
+ *
398
+ * The classic cause is a **circular import**: a `lunora/` query/mutation/action
399
+ * module runs `mutation({ args: { x: v.string() } })` at the top level while the
400
+ * module it imported `v`/`query`/`mutation` from is still mid-initialization, so
401
+ * those bindings read as `undefined`. The message names a validator method
402
+ * (`'string'`, `'id'`, …) but never the file.
403
+ *
404
+ * We can't recover the dropped frames at this layer, but we can recognise the
405
+ * shape of the failure and append an actionable hint pointing at the likely
406
+ * cause — turning a dead-end stack into something a user can act on.
407
+ */
412
408
  declare const WORKER_STARTUP_HINT: string;
413
409
  /**
414
- * True when `error` looks like a Worker-entry evaluation failure routed through
415
- * `@cloudflare/vite-plugin`'s runner worker (the stack references the runner
416
- * worker / export-types probe). Kept narrow so we only annotate this specific
417
- * class of dev-startup error.
418
- */
410
+ * True when `error` looks like a Worker-entry evaluation failure routed through
411
+ * `@cloudflare/vite-plugin`'s runner worker (the stack references the runner
412
+ * worker / export-types probe). Kept narrow so we only annotate this specific
413
+ * class of dev-startup error.
414
+ */
419
415
  declare const isWorkerEntryEvalError: (error: unknown) => boolean;
420
416
  /**
421
- * Append {@link WORKER_STARTUP_HINT} to a recognised Worker-entry eval error
422
- * (idempotently). Any other value is returned untouched.
423
- */
417
+ * Append {@link WORKER_STARTUP_HINT} to a recognised Worker-entry eval error
418
+ * (idempotently). Any other value is returned untouched.
419
+ */
424
420
  declare const augmentWorkerStartupError: (error: unknown) => unknown;
425
421
  /**
426
- * Wrap the startup hooks of `@cloudflare/vite-plugin`'s plugins so a Worker-entry
427
- * evaluation failure carries the Lunora hint. Returns a new array; the input
428
- * plugins are shallow-cloned (never mutated in place) so re-using the cloudflare
429
- * plugin instances elsewhere stays safe.
430
- */
422
+ * Wrap the startup hooks of `@cloudflare/vite-plugin`'s plugins so a Worker-entry
423
+ * evaluation failure carries the Lunora hint. Returns a new array; the input
424
+ * plugins are shallow-cloned (never mutated in place) so re-using the cloudflare
425
+ * plugin instances elsewhere stays safe.
426
+ */
431
427
  declare const withWorkerStartupHint: (plugins: ReadonlyArray<Plugin>) => Plugin[];
432
428
  /**
433
- * Vite plugin that validates the project's `wrangler.jsonc` against the
434
- * bindings implied by `lunora/schema.ts`. Throws (Vite renders nicely) on
435
- * missing requirements during `configResolved`. Delegates the parsing /
436
- * validation logic to `@lunora/config` so the rules stay in lockstep with
437
- * the CLI (`lunora deploy`).
438
- */
429
+ * Vite plugin that validates the project's `wrangler.jsonc` against the
430
+ * bindings implied by `lunora/schema.ts`. Throws (Vite renders nicely) on
431
+ * missing requirements during `configResolved`. Delegates the parsing /
432
+ * validation logic to `@lunora/config` so the rules stay in lockstep with
433
+ * the CLI (`lunora deploy`).
434
+ */
439
435
  declare const wranglerValidatorPlugin: (options: ResolvedLunoraPluginOptions) => Plugin;
440
436
  /**
441
- * Resolve the `overlay` toggle into the overlay plugin's options — or `false` to
442
- * skip it. Lunora's solution finders are **prepended** so they run before the
443
- * overlay's built-ins; a user's own finders are appended and can still win per
444
- * error via a strictly higher `priority` (equal priority keeps Lunora first,
445
- * since the overlay sorts stably). Lunora also forwards both `error` AND `warn`
446
- * console calls by default (the overlay's own default is `["error"]` only) so
447
- * Lunora's branded `warn` advisories surface in the browser too — the user can
448
- * override `forwardedConsoleMethods`.
449
- */
437
+ * Resolve the `overlay` toggle into the overlay plugin's options — or `false` to
438
+ * skip it. Lunora's solution finders are **prepended** so they run before the
439
+ * overlay's built-ins; a user's own finders are appended and can still win per
440
+ * error via a strictly higher `priority` (equal priority keeps Lunora first,
441
+ * since the overlay sorts stably). Lunora also forwards both `error` AND `warn`
442
+ * console calls by default (the overlay's own default is `["error"]` only) so
443
+ * Lunora's branded `warn` advisories surface in the browser too — the user can
444
+ * override `forwardedConsoleMethods`.
445
+ */
450
446
  declare const resolveOverlayOption: (overlay: LunoraPluginOptions["overlay"]) => false | OverlayPluginOptions;
451
447
  /**
452
- * Lunora Vite plugin. Returns a flat array of Vite plugins that:
453
- *
454
- * 1. Run `@lunora/codegen` on startup + on schema file changes.
455
- * 2. Validate the project's `wrangler.jsonc` against the schema's implied bindings.
456
- * 3. Inject `@visulima/vite-overlay` for runtime error overlays (unless `overlay: false`).
457
- * 4. Include `@cloudflare/vite-plugin` so users get one-import setup (unless `cloudflare: false`).
458
- *
459
- * `@cloudflare/vite-plugin` and `@visulima/vite-overlay` are direct dependencies,
460
- * so they're imported statically — opt out per-feature via the options rather
461
- * than relying on whether they're installed.
462
- */
448
+ * Lunora Vite plugin. Returns a flat array of Vite plugins that:
449
+ *
450
+ * 1. Run `@lunora/codegen` on startup + on schema file changes.
451
+ * 2. Validate the project's `wrangler.jsonc` against the schema's implied bindings.
452
+ * 3. Inject `@visulima/vite-overlay` for runtime error overlays (unless `overlay: false`).
453
+ * 4. Include `@cloudflare/vite-plugin` so users get one-import setup (unless `cloudflare: false`).
454
+ *
455
+ * `@cloudflare/vite-plugin` and `@visulima/vite-overlay` are direct dependencies,
456
+ * so they're imported statically — opt out per-feature via the options rather
457
+ * than relying on whether they're installed.
458
+ */
463
459
  declare const lunora: (options?: LunoraPluginOptions) => LunoraPlugins;
464
460
  declare const VERSION: string;
465
461
  export { CLASS_A_WIRING, type ClassAWiring, type CloudflarePluginOptions, DEV_WORKER_ENV_VALUE, DEV_WORKER_ENV_VAR, LUNORA_API_UPDATED_EVENT, LUNORA_WORKER_VIRTUAL_ID, type LunoraPluginOptions, type LunoraPlugins, type OverlayPluginOptions, type PlanViteRemoteOptions, type ResolvedLunoraPluginOptions, STUDIO_PATH, type Solution, type SolutionFinder, VERSION, type ViteRemotePlan, WORKER_STARTUP_HINT, augmentWorkerStartupError, buildStudioUrl, buildWorkerEntrySource, codegenPlugin, containerLogsPlugin, createCommandProbe, devStatePlugin, devVariablesPlugin, frameworkComposePlugin, isAutoComposable, isWorkerEntryEvalError, logStreamPlugin, lunora, lunoraSolutionFinder, lunoraSolutionFinders, planViteRemoteBindings, remoteBindingsCleanupPlugin, remoteBindingsConfigPlugin, resolveOverlayOption, studioPlugin, withDevWorkerEnv, withRemoteBindings, withWorkerStartupHint, wranglerValidatorPlugin };