@lunora/vite 1.0.0-alpha.2 → 1.0.0-alpha.200

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 (33) hide show
  1. package/LICENSE.md +6 -0
  2. package/README.md +19 -2
  3. package/__assets__/package-og.svg +1 -1
  4. package/dist/index.d.mts +448 -262
  5. package/dist/index.d.ts +448 -262
  6. package/dist/index.mjs +3 -153
  7. package/dist/packem_shared/CLASS_A_WIRING-CEzeqjr2.mjs +33 -0
  8. package/dist/packem_shared/LUNORA_API_UPDATED_EVENT-CO2Rv2re.mjs +1 -0
  9. package/dist/packem_shared/STUDIO_PATH-UztnV2ca.mjs +1 -0
  10. package/dist/packem_shared/WORKER_STARTUP_HINT-COlRTY32.mjs +5 -0
  11. package/dist/packem_shared/checkLunoraProxy-C9M8c5eS.mjs +1 -0
  12. package/dist/packem_shared/codegen-plugin-dg384k5b.mjs +3 -0
  13. package/dist/packem_shared/codegenPlugin-Ce_SRTEe.mjs +1 -0
  14. package/dist/packem_shared/containerLogsPlugin-CWkqSCL3.mjs +1 -0
  15. package/dist/packem_shared/devStatePlugin-CcFV-eBl.mjs +1 -0
  16. package/dist/packem_shared/devVariablesPlugin-DY_bJXsX.mjs +1 -0
  17. package/dist/packem_shared/log-DE48L4Oz.mjs +1 -0
  18. package/dist/packem_shared/logStreamPlugin-DtOu5VX8.mjs +3 -0
  19. package/dist/packem_shared/lunoraSolutionFinder--J0x2mAM.mjs +1 -0
  20. package/dist/packem_shared/planViteRemoteBindings-E3GdC6pY.mjs +1 -0
  21. package/dist/packem_shared/server-close-Qoh4i6Ay.mjs +1 -0
  22. package/dist/packem_shared/wranglerValidatorPlugin-BdKLAEoq.mjs +3 -0
  23. package/package.json +9 -10
  24. package/dist/packem_shared/augmentWorkerStartupError-DhsXUW8k.mjs +0 -81
  25. package/dist/packem_shared/buildStudioUrl-5ppCdBHa.mjs +0 -210
  26. package/dist/packem_shared/codegenPlugin-BAyt6iWS.mjs +0 -210
  27. package/dist/packem_shared/createCommandProbe-Coo6bgVz.mjs +0 -36
  28. package/dist/packem_shared/devVariablesPlugin-BRWbWHhq.mjs +0 -20
  29. package/dist/packem_shared/frameworkComposePlugin-Cja0SF6x.mjs +0 -96
  30. package/dist/packem_shared/logStreamPlugin-CqvZ17kd.mjs +0 -61
  31. package/dist/packem_shared/planViteRemoteBindings-QN5ncUS1.mjs +0 -50
  32. package/dist/packem_shared/reconcileWranglerCrons-PxGwfCp_.mjs +0 -29
  33. package/dist/packem_shared/wranglerValidatorPlugin-Cf0nLP7-.mjs +0 -63
package/dist/index.d.mts CHANGED
@@ -1,176 +1,230 @@
1
1
  import { CodegenOptions } from '@lunora/codegen';
2
2
  import errorOverlayPlugin from '@visulima/vite-overlay';
3
3
  import { Plugin } from 'vite';
4
- import { FrameworkDetection, DetectedFramework, materializeRemoteWranglerConfig, readProjectRemotePreference } from '@lunora/config';
4
+ import { FrameworkDetection, DetectedFramework, readProjectRemotePreference } from '@lunora/config';
5
5
  export { type DetectedFramework, type FrameworkClass, type FrameworkDetection, detectFramework } from '@lunora/config';
6
+ import { materializeRemoteWranglerConfig } from '@lunora/config/cloudflare';
7
+ export { type ReconcileCronsResult as ReconcileResult, reconcileWranglerCrons } from '@lunora/config/cloudflare';
6
8
  import { AddressInfo } from 'node:net';
7
9
  /** Options forwarded to `@cloudflare/vite-plugin`'s cloudflare plugin. */
8
10
  type CloudflarePluginOptions = Record<string, unknown>;
9
11
  /**
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
- */
12
+ * Options forwarded to `@visulima/vite-overlay`'s error-overlay plugin. Derived
13
+ * from the plugin's own factory signature so it tracks the real shape
14
+ * (`forwardConsole`, `forwardedConsoleMethods`, `reactPluginName`,
15
+ * `solutionFinders`, `showBallonButton`, `vuePluginName`, …).
16
+ */
15
17
  type OverlayPluginOptions = NonNullable<Parameters<typeof errorOverlayPlugin>[0]>;
18
+ /**
19
+ * Shard Durable Object configuration for the AUTO-COMPOSED class-A worker.
20
+ *
21
+ * A class-A app (TanStack Start, vinext, React Router, SolidStart) has no
22
+ * hand-written worker entry — that is what makes it class A — so it never calls
23
+ * the generated `defineApp()` builder and never reaches `createShardDO(config)`.
24
+ * The composed entry emitted `createShardDO()` bare, which left `cdc` and the
25
+ * whole reactive query cache unreachable for every class-A template no matter
26
+ * what the app wanted. `vite.config.ts` is the one place such an app configures
27
+ * Lunora, so it is where these land — the same route
28
+ * {@link LunoraPluginOptions.allowUnauthenticatedShardAccess} already takes into
29
+ * the same emitted entry.
30
+ *
31
+ * Deliberately only the PLAIN-DATA half of the generated `ShardDOConfig`. The
32
+ * rest of that type is `(env) => …` factories (`scheduler`, `storage`,
33
+ * `vectors`, …) which cannot be written in a config object and which a class-A
34
+ * app reaches by writing its own entry instead.
35
+ *
36
+ * Ignored for class B/C: those pass their config to `createShardDO` directly (or
37
+ * through `defineApp`), and an explicit argument there is unaffected by this.
38
+ */
39
+ interface LunoraShardConfig {
40
+ /** Opt into change-data-capture: every write records a post-image to `__cdc_log`. Backs streaming export, replay-PITR, and shard-local `defineShape` replication. Off by default. */
41
+ cdc?: boolean;
42
+ /** Ceiling on the join keys one relation-crossing `where` predicate may pre-resolve via semijoin before failing closed. Omit for the engine default. */
43
+ maxRelationKeys?: number;
44
+ /**
45
+ * Enable the per-shard reactive query cache: `true` for the defaults, or an
46
+ * options object to tune the caps. Query results are memoized by
47
+ * `(functionPath, args, identity)` and invalidated by the ctx-db write hooks
48
+ * before the subscription broadcast, so a subscriber never observes a
49
+ * pre-write value. Omitted (or `false`) keeps every dispatch re-running its
50
+ * handler.
51
+ */
52
+ reactiveCache?: boolean | {
53
+ maxBytes?: number;
54
+ maxEntries?: number;
55
+ };
56
+ /** Resolution policy for a relation-crossing `where` whose child is co-located in this shard: `"auto"` (cost-based, the engine default), `"always"` (inline correlated EXISTS) or `"never"` (universal semijoin). All three return identical rows. */
57
+ relationExistsPushDown?: "always" | "auto" | "never";
58
+ }
16
59
  interface LunoraPluginOptions {
17
60
  /**
18
- * Which machine-readable API spec(s) codegen emits into `_generated/`.
19
- * `"openapi"` (default) writes `openapi.json` (OpenAPI 3.1; RPC + REST),
20
- * `"openrpc"` writes `openrpc.json` (OpenRPC 1.x; RPC-only), `"both"` writes
21
- * both, and `"none"` writes neither. Forwarded to `runCodegen({ apiSpec })`;
22
- * the value set is derived from `CodegenOptions` so it can't drift.
23
- */
61
+ * Allow a client-named NON-default shard / cross-shard fan-out WITHOUT an
62
+ * `authorizeShard`/`authorizeFanOut` callback. The auto-composed class-A worker
63
+ * (`virtual:lunora/worker`) default-denies such access (403 `FORBIDDEN_SHARD`);
64
+ * set this `true` to opt into open access — only safe when every table is
65
+ * protected by per-row RLS. A production sharded app should configure
66
+ * `authorizeShard` instead (via a hand-written class-B worker). Defaults to `false`.
67
+ */
68
+ allowUnauthenticatedShardAccess?: boolean;
69
+ /**
70
+ * Which machine-readable API spec(s) codegen emits into `_generated/`.
71
+ * `"openapi"` (default) writes `openapi.json` (OpenAPI 3.1; RPC + REST),
72
+ * `"openrpc"` writes `openrpc.json` (OpenRPC 1.x; RPC-only), `"both"` writes
73
+ * both, and `"none"` writes neither. Forwarded to `runCodegen({ apiSpec })`;
74
+ * the value set is derived from `CodegenOptions` so it can't drift.
75
+ */
24
76
  apiSpec?: CodegenOptions["apiSpec"];
25
77
  /** Pass through to `@cloudflare/vite-plugin`. Pass `false` to opt out. Defaults to `true`. */
26
78
  cloudflare?: boolean | CloudflarePluginOptions;
27
- /** Directory name (relative to `projectRoot`) where generated files are written. Defaults to `"lunora/_generated"`. */
28
- generatedDir?: string;
29
79
  /**
30
- * Inject `@visulima/vite-overlay` for runtime errors (dev only). Pass
31
- * `false` to opt out, or an options object to forward to the overlay.
32
- * Defaults to `true`.
33
- */
80
+ * Inject `@visulima/vite-overlay` for runtime errors (dev only). Pass
81
+ * `false` to opt out, or an options object to forward to the overlay.
82
+ * Defaults to `true`.
83
+ */
34
84
  overlay?: boolean | OverlayPluginOptions;
35
85
  /** Project root containing the `lunora/` directory. Defaults to `process.cwd()`. */
36
86
  projectRoot?: string;
37
87
  /** Directory name (relative to `projectRoot`) containing `schema.ts` and function files. Defaults to `"lunora"`. */
38
88
  schemaDir?: string;
89
+ /**
90
+ * Shard DO configuration baked into the auto-composed class-A worker entry —
91
+ * see {@link LunoraShardConfig}. The ONLY way a class-A app can set `cdc` or
92
+ * enable the reactive query cache, since it has no worker entry to call
93
+ * `createShardDO(config)` from. Ignored for class B/C. Defaults to `{}`
94
+ * (byte-identical composed output).
95
+ */
96
+ shard?: LunoraShardConfig;
39
97
  /** Serve the Lunora studio at `/__lunora` during dev. Pass `false` to opt out. Defaults to `true`. */
40
98
  studio?: boolean;
99
+ /**
100
+ * Deploy target the emitted `ctx.*` surface is tailored to. Defaults to
101
+ * `"target"` in `lunora.json`, then `"cloudflare"` — so an existing project
102
+ * emits byte-identical output.
103
+ *
104
+ * Set it here only to override the project config for one build — keeping
105
+ * this and `lunora deploy` on the same target is what the shared resolution
106
+ * in `@lunora/config` exists to guarantee.
107
+ */
108
+ target?: string;
41
109
  /** Validate that `wrangler.jsonc` declares the bindings the schema implies. Defaults to `true`. */
42
110
  validateWrangler?: boolean;
43
111
  }
44
112
  /** Resolved options after merging defaults. */
45
113
  interface ResolvedLunoraPluginOptions {
114
+ allowUnauthenticatedShardAccess: boolean;
46
115
  apiSpec: NonNullable<CodegenOptions["apiSpec"]>;
47
116
  cloudflare: false | CloudflarePluginOptions;
117
+ /**
118
+ * Where codegen writes `_generated/*`, always `<schemaDir>/_generated`.
119
+ *
120
+ * NOT a user option: codegen hardcodes that path (`run-codegen` joins
121
+ * `lunoraDirectory` with `"_generated"`), so a settable override was a no-op
122
+ * everywhere except `frameworkComposePlugin`, which uses it as the composed
123
+ * class-A worker's import base — where a non-default value pointed the
124
+ * emitted imports at a directory nothing writes and broke class-A dev and
125
+ * build. Derived, so the import base cannot disagree with the emitter.
126
+ */
48
127
  generatedDir: string;
49
128
  overlay: false | OverlayPluginOptions;
50
129
  projectRoot: string;
51
130
  schemaDir: string;
131
+ shard: LunoraShardConfig;
52
132
  studio: boolean;
133
+ target: string;
53
134
  validateWrangler: boolean;
54
135
  }
55
136
  /**
56
- * The plugins `lunora()` returns. A mutable `Plugin[]` (not `ReadonlyArray`) so
57
- * it slots directly into Vite's `plugins` — which recursively flattens nested
58
- * plugin arrays — without a spread: `plugins: [lunora()]`.
59
- */
137
+ * The plugins `lunora()` returns. A mutable `Plugin[]` (not `ReadonlyArray`) so
138
+ * it slots directly into Vite's `plugins` — which recursively flattens nested
139
+ * plugin arrays — without a spread: `plugins: [lunora()]`.
140
+ */
60
141
  type LunoraPlugins = Plugin[];
61
142
  /**
62
- * Vite plugin that runs `@lunora/codegen` on startup and on file changes
63
- * inside the lunora schema directory.
64
- */
143
+ * Vite plugin that runs `@lunora/codegen` on startup and on file changes
144
+ * inside the lunora schema directory.
145
+ */
65
146
  declare const codegenPlugin: (options: ResolvedLunoraPluginOptions) => Plugin;
66
- interface ReconcileResult {
67
- /** `true` when `wrangler.jsonc` was rewritten. */
68
- changed: boolean;
69
- /** Human-readable reason when reconciliation was skipped (for logging). */
70
- reason?: string;
71
- /** Resolved wrangler path, or `undefined` when none was found. */
72
- wranglerPath?: string;
73
- }
74
147
  /**
75
- * Reconcile the codegen-derived cron schedules into the project's
76
- * `wrangler.jsonc` `triggers.crons` array, preserving comments and formatting
77
- * via `jsonc-parser`'s structural edits.
78
- *
79
- * When `triggers.crons` already matches `cronTriggers`, nothing is written (so
80
- * we don't churn the file or trip the dev server's file watcher). When the
81
- * project declares no crons, a stale non-empty array is cleared so removed
82
- * crons stop firing.
83
- *
84
- * This intentionally writes the SAME `triggers.crons` shape the
85
- * `@lunora/config` validator accepts, so the wrangler validator never fights
86
- * the generated value.
87
- */
88
- declare const reconcileWranglerCrons: (projectRoot: string, cronTriggers: ReadonlyArray<string>) => ReconcileResult;
148
+ * Dev-only plugin that tails the local dev containers' own stdout/stderr in the
149
+ * Vite terminal.
150
+ *
151
+ * `@cloudflare/vite-plugin` builds and runs each declared container locally via
152
+ * Docker (image `cloudflare-dev/<class>:<id>`) but only forwards the *worker's*
153
+ * console — the container process's own output is otherwise invisible. This
154
+ * plugin attaches to those Docker log streams (via `@lunora/config`'s
155
+ * `streamContainerLogs`, which lazy-loads `dockerode`) and prints each line
156
+ * through Vite's logger, branded and tagged `container:<name>`.
157
+ *
158
+ * A no-op when the project declares no containers (the common case): discovery
159
+ * returns an empty list, so `dockerode` is never imported and no Docker work
160
+ * starts. Set `LUNORA_CONTAINER_LOGS=0` to opt out. A missing/stopped Docker
161
+ * engine degrades to a single warning rather than breaking dev.
162
+ */
163
+ declare const containerLogsPlugin: (options: ResolvedLunoraPluginOptions) => Plugin;
164
+ /** Vite plugin (serve-only) that writes the dev-server state record on listen and clears it on close. */
165
+ declare const devStatePlugin: (options: ResolvedLunoraPluginOptions) => Plugin;
89
166
  /**
90
- * Dev-only Vite plugin that offers to scaffold `.dev.vars` before the worker
91
- * boots. `@cloudflare/vite-plugin` loads `.dev.vars` into the worker's `env`,
92
- * but the file is gitignored — so a fresh clone has none and the worker throws
93
- * on the first required secret (e.g. `AUTH_SECRET is required`). When a
94
- * `.dev.vars.example` exists, we prompt to generate `.dev.vars` from it with
95
- * secrets auto-filled. Identical behaviour to `lunora dev` — both call
96
- * `ensureDevVariables` from `@lunora/config`.
97
- *
98
- * Runs in `configResolved` (awaited by Vite) so it completes before the
99
- * Cloudflare plugin reads the file. Non-interactive runs decline silently.
100
- */
167
+ * Dev-only Vite plugin that prepares `.dev.vars` before the worker boots.
168
+ * `@cloudflare/vite-plugin` loads `.dev.vars` into the worker's `env`, but the
169
+ * file is gitignored — so a fresh clone has none and the worker throws on the
170
+ * first required secret (e.g. `AUTH_SECRET is required`). Three steps, the first
171
+ * two shared with `lunora dev` via `@lunora/config`.
172
+ *
173
+ * First, {@link ensureDevVariables}: when a `.dev.vars.example` exists, prompt
174
+ * to generate `.dev.vars` from it with secrets auto-filled. Second,
175
+ * {@link fillDevSecrets}: fill any empty/placeholder secret already in
176
+ * `.dev.vars` that Lunora can mint locally (a `lunora add`-scaffolded project
177
+ * writes secrets blank) and ensure `LUNORA_ADMIN_TOKEN` is present + generated —
178
+ * so the worker boots with working secrets and the Studio authenticates without
179
+ * its login gate. No prompt: it only generates locally-derivable values and
180
+ * never overwrites a real one. Third, {@link ensureDevWorkerEnv}.
181
+ *
182
+ * Runs in `configResolved` (awaited by Vite) so it completes before the
183
+ * Cloudflare plugin reads the file. Non-interactive runs decline silently.
184
+ * Skipped under `vite preview`, which resolves with `command: "serve"` and so
185
+ * runs `apply: "serve"` plugins too — previewing a built app must not prompt to
186
+ * scaffold, or write, a dev secrets file.
187
+ */
101
188
  declare const devVariablesPlugin: (options: ResolvedLunoraPluginOptions) => Plugin;
102
189
  /**
103
- * Worker env var the dev tooling sets so the Lunora runtime recognises a
104
- * development deployment (`@lunora/do`'s `isDevEnvironment`) and therefore
105
- * streams every RPC dispatch summary to the terminal by default — the
106
- * `lunora dev` CLI sets the same var via `wrangler dev --var`.
107
- *
108
- * It is injected ONLY during `vite` serve, never a production `vite build`, so
109
- * it can never leak into a deployed worker. A `WORKER_ENV` the user already
110
- * declares (in `wrangler.jsonc` `[vars]` or `.dev.vars`) takes precedence, so
111
- * this only fills the gap when none is set.
112
- */
113
- declare const DEV_WORKER_ENV_VAR = "WORKER_ENV";
114
- declare const DEV_WORKER_ENV_VALUE = "development";
115
- /** The structural slice of `@cloudflare/vite-plugin`'s worker config we read/write. */
116
- /**
117
- * Wrap the cloudflare-plugin options so the dev worker's `vars` gain a
118
- * `WORKER_ENV` of `development` when — and only when — `isServe()` reports a
119
- * `vite` serve. Any `config` customizer the caller already supplied is
120
- * preserved and applied first; an existing `WORKER_ENV` wins, so a user
121
- * override is never clobbered.
122
- */
123
- declare const withDevWorkerEnv: (options: CloudflarePluginOptions, isServe: () => boolean) => CloudflarePluginOptions;
124
- /**
125
- * A Vite plugin that captures the resolved command (`serve` vs `build`) so
126
- * {@link withDevWorkerEnv} injects the dev var only during `vite`, plus an
127
- * `isServe` probe sharing the same closure. `enforce: "pre"` so the command is
128
- * captured before the cloudflare plugin resolves its worker config.
129
- */
130
- declare const createCommandProbe: () => {
131
- isServe: () => boolean;
132
- plugin: Plugin;
133
- };
134
- /**
135
- * Mutable, plugin-shared context. The `lunora()` factory creates one instance
136
- * and threads it through every Lunora sub-plugin, so detection runs once and
137
- * downstream plugins (codegen, composition, the dev hint) read the same result
138
- * without re-scanning `package.json`. PLAN4 §2.4.
139
- */
190
+ * Mutable, plugin-shared context. The `lunora()` factory creates one instance
191
+ * and threads it through every Lunora sub-plugin, so detection runs once and
192
+ * downstream plugins (codegen, composition, the dev hint) read the same result
193
+ * without re-scanning `package.json`. PLAN4 §2.4.
194
+ */
140
195
  interface LunoraPluginContext {
141
196
  /** The detected framework + class, populated during `config` / `configResolved`. `undefined` until detection runs. */
142
197
  framework?: FrameworkDetection;
143
198
  }
144
- /** Create an empty shared context object for one `lunora()` invocation. */
145
199
  /**
146
- * The virtual module id the Lunora plugin resolves to a generated, class-A
147
- * worker entry. A class-A template points its wrangler `main` at this id (or
148
- * re-exports it from a one-line `src/server.ts`) and never hand-writes
149
- * `createWorker({ httpRouter })` — the plugin composes the framework's SSR
150
- * handler under `composeWorker`'s `httpRouter` seam for it.
151
- *
152
- * Exposed publicly so `@lunora/cli`'s build/deploy path and the templates can
153
- * reference the same constant rather than re-typing the literal.
154
- */
200
+ * The virtual module id the Lunora plugin resolves to a generated, class-A
201
+ * worker entry. A class-A template points its wrangler `main` at this id (or
202
+ * re-exports it from a one-line `src/server.ts`) and never hand-writes
203
+ * `createWorker({ httpRouter })` — the plugin composes the framework's SSR
204
+ * handler under `composeWorker`'s `httpRouter` seam for it.
205
+ *
206
+ * Exposed publicly so `@lunora/cli`'s build/deploy path and the templates can
207
+ * reference the same constant rather than re-typing the literal.
208
+ */
155
209
  declare const LUNORA_WORKER_VIRTUAL_ID: string;
156
210
  /**
157
- * Per-class-A-framework wiring the generated worker entry needs: how to obtain
158
- * the framework's SSR handler as a `composeWorker`-compatible `httpRouter`.
159
- *
160
- * `imports` is the full import statement(s) the generated entry needs (each
161
- * framework controls its own import shape — a namespace import, or a named one);
162
- * `handler` is a JS expression (evaluated in the generated module's scope, where
163
- * `imports`' symbols are in scope) that yields an `HttpRouterLike`
164
- * (`{ fetch(request, env?, ctx?) }`). Both are data — not codegen branches — so
165
- * the set of supported class-A frameworks is one readable table and adding a
166
- * framework is a pure data edit.
167
- *
168
- * Honesty note: these handler expressions encode each framework's *documented*
169
- * Cloudflare SSR-handler shape — the same expressions the hand-wired template
170
- * entries use today (React Router's `createRequestHandler` over its virtual
171
- * server build; SolidStart's `cloudflare-module` handler; TanStack Start's
172
- * server entry). The plugin just emits them so the developer doesn't.
173
- */
211
+ * Per-class-A-framework wiring the generated worker entry needs: how to obtain
212
+ * the framework's SSR handler as a `composeWorker`-compatible `httpRouter`.
213
+ *
214
+ * `imports` is the full import statement(s) the generated entry needs (each
215
+ * framework controls its own import shape — a namespace import, or a named one);
216
+ * `handler` is a JS expression (evaluated in the generated module's scope, where
217
+ * `imports`' symbols are in scope) that yields an `HttpRouterLike`
218
+ * (`{ fetch(request, env?, ctx?) }`). Both are data — not codegen branches — so
219
+ * the set of supported class-A frameworks is one readable table and adding a
220
+ * framework is a pure data edit.
221
+ *
222
+ * Honesty note: these handler expressions encode each framework's *documented*
223
+ * Cloudflare SSR-handler shape — the same expressions the hand-wired template
224
+ * entries use today (React Router's `createRequestHandler` over its virtual
225
+ * server build; SolidStart's `cloudflare-module` handler; TanStack Start's
226
+ * server entry). The plugin just emits them so the developer doesn't.
227
+ */
174
228
  interface ClassAWiring {
175
229
  /** JS expression yielding the `httpRouter` ({ fetch }), referencing symbols brought in by `imports`. */
176
230
  handler: string;
@@ -179,62 +233,105 @@ interface ClassAWiring {
179
233
  }
180
234
  declare const CLASS_A_WIRING: Readonly<Partial<Record<DetectedFramework, ClassAWiring>>>;
181
235
  /**
182
- * Whether the detected framework is one the plugin can auto-compose. Only
183
- * class-A frameworks with a known SSR-handler wiring qualify; everything else
184
- * (class B/C, `none`) falls back to the existing flow.
185
- */
236
+ * Whether the detected framework is one the plugin can auto-compose. Only
237
+ * class-A frameworks with a known SSR-handler wiring qualify; everything else
238
+ * (class B/C, `none`) falls back to the existing flow.
239
+ */
186
240
  declare const isAutoComposable: (context: LunoraPluginContext) => boolean;
187
241
  /**
188
- * Build the source of the virtual class-A worker entry. Pure (no fs / no Vite),
189
- * so the emitted composition is unit-testable in isolation.
190
- *
191
- * The emitted module imports the framework SSR handler + the project's
192
- * generated artifacts (functions registry, OpenAPI doc, `createShardDO`) and
193
- * composes them through `composeWorker` — reserved `/_lunora/*` paths route to
194
- * Lunora, everything else falls through to the framework SSR handler. The
195
- * `generatedImportBase` MUST be an absolute filesystem path to the `_generated`
196
- * directory. Virtual modules have no real filesystem path, so relative specifiers
197
- * like `./lunora/_generated/functions` cannot be resolved by Vite/rolldown from a
198
- * virtual module id. Absolute paths are resolved correctly in all environments
199
- * (Vite 8 + rolldown 1.x confirmed).
200
- */
201
- declare const buildWorkerEntrySource: (framework: DetectedFramework, generatedImportBase: string, hasContainers?: boolean) => string;
242
+ * The `_generated/` modules whose exported classes wrangler validates a
243
+ * `class_name` against: container Durable Objects, workflow entrypoints, and
244
+ * agent (workflow) entrypoints — the same three kinds `reconcile-bindings`
245
+ * writes into `wrangler.jsonc`. The composed entry star-re-exports each module
246
+ * the project actually has.
247
+ */
248
+ declare const GENERATED_CLASS_MODULES: readonly ["agents", "containers", "workflows"];
249
+ /** One {@link GENERATED_CLASS_MODULES} entry. */
250
+ type GeneratedClassModule = (typeof GENERATED_CLASS_MODULES)[number];
251
+ /**
252
+ * Build the source of the virtual class-A worker entry. Pure (no fs / no Vite),
253
+ * so the emitted composition is unit-testable in isolation.
254
+ *
255
+ * The emitted module imports the framework SSR handler + the project's
256
+ * generated artifacts (functions registry, OpenAPI doc, `createShardDO`) and
257
+ * composes them through `composeWorker` — reserved `/_lunora/*` paths route to
258
+ * Lunora, everything else falls through to the framework SSR handler. The
259
+ * `generatedImportBase` MUST be an absolute filesystem path to the `_generated`
260
+ * directory. Virtual modules have no real filesystem path, so relative specifiers
261
+ * like `./lunora/_generated/functions` cannot be resolved by Vite/rolldown from a
262
+ * virtual module id. Absolute paths are resolved correctly in all environments
263
+ * (Vite 8 + rolldown 1.x confirmed).
264
+ */
265
+ declare const buildWorkerEntrySource: (framework: DetectedFramework, generatedImportBase: string, classModules?: ReadonlyArray<GeneratedClassModule>, useUmbrella?: boolean, allowUnauthenticatedShardAccess?: boolean, shard?: LunoraShardConfig) => string;
202
266
  /**
203
- * Vite plugin that auto-composes a detected class-A meta-framework's SSR
204
- * handler with Lunora into one Cloudflare Worker (PLAN4 §2.4 / §3 class-A row).
205
- *
206
- * Mechanism: it resolves the {@link LUNORA_WORKER_VIRTUAL_ID} virtual module to
207
- * a generated worker entry that wires the framework SSR handler under
208
- * `composeWorker`'s `httpRouter` seam — so the developer never writes
209
- * `createWorker({ httpRouter })`. The composed worker is an ordinary module
210
- * entry, so it HMRs under `@cloudflare/vite-plugin` exactly like a hand-written
211
- * one (PLAN4 M5 risk #5): the virtual entry only imports the framework handler
212
- * and the generated artifacts, both of which the framework's plugin + codegen
213
- * already make HMR-aware.
214
- *
215
- * Safety: it is a strict no-op unless `context.framework.class === "A"` with a
216
- * known wiring. For class-C (SPA) projects and undetected frameworks it
217
- * resolves/loads nothing. `cloudflare: false` does NOT disable the virtual
218
- * entry — it only means "don't add the Cloudflare Vite plugin a second time"
219
- * (the user supplied it themselves); the composed worker must still be
220
- * resolvable so the user-supplied CF plugin can find the wrangler `main`.
221
- */
267
+ * Vite plugin that auto-composes a detected class-A meta-framework's SSR
268
+ * handler with Lunora into one Cloudflare Worker (PLAN4 §2.4 / §3 class-A row).
269
+ *
270
+ * Mechanism: it resolves the {@link LUNORA_WORKER_VIRTUAL_ID} virtual module to
271
+ * a generated worker entry that wires the framework SSR handler under
272
+ * `composeWorker`'s `httpRouter` seam — so the developer never writes
273
+ * `createWorker({ httpRouter })`. The composed worker is an ordinary module
274
+ * entry, so it HMRs under `@cloudflare/vite-plugin` exactly like a hand-written
275
+ * one (PLAN4 M5 risk #5): the virtual entry only imports the framework handler
276
+ * and the generated artifacts, both of which the framework's plugin + codegen
277
+ * already make HMR-aware.
278
+ *
279
+ * Safety: it is a strict no-op unless `context.framework.class === "A"` with a
280
+ * known wiring. For class-C (SPA) projects and undetected frameworks it
281
+ * resolves/loads nothing. `cloudflare: false` does NOT disable the virtual
282
+ * entry — it only means "don't add the Cloudflare Vite plugin a second time"
283
+ * (the user supplied it themselves); the composed worker must still be
284
+ * resolvable so the user-supplied CF plugin can find the wrangler `main`. The
285
+ * vinext template depends on exactly that, so making this plugin honour the
286
+ * option would break it.
287
+ */
222
288
  declare const frameworkComposePlugin: (options: ResolvedLunoraPluginOptions, context: LunoraPluginContext) => Plugin;
223
289
  /**
224
- * Vite plugin (serve-only) that formats Lunora worker logs in the terminal.
225
- * Patches `process.stdout`/`process.stderr` once the dev server is configured
226
- * and restores them when it closes.
227
- */
290
+ * The custom HMR event the Lunora Vite plugin sends on the client environment's
291
+ * hot channel after a successful codegen run, in place of the old blanket
292
+ * browser `full-reload`. The generated `api`/`server` modules are just
293
+ * `FunctionReference` metadata, so Vite's granular module HMR re-imports the
294
+ * changed `_generated/*` in place; this event is a non-destructive nudge that
295
+ * lets open WebSocket subscriptions, optimistic state, the offline queue, and
296
+ * form state survive a schema save.
297
+ *
298
+ * Kept in its own module (a single source of truth) so the codegen plugin —
299
+ * whose sole export is the plugin factory — can reference it without becoming a
300
+ * mixed default+named module, and so any future client-side listener can agree
301
+ * on the exact string.
302
+ *
303
+ * There is no first-party client listener yet: `@lunora/client` / `@lunora/react`
304
+ * ship as pre-bundled, side-effect-free dependencies where `import.meta.hot` is
305
+ * `undefined` at runtime (Vite's dep optimizer), so a listener there would be
306
+ * dead (and tree-shaken) code. A future app-local or codegen-emitted listener
307
+ * can import this constant to re-validate active queries over the live socket.
308
+ */
309
+ declare const LUNORA_API_UPDATED_EVENT = "lunora:api-updated";
310
+ /**
311
+ * Vite plugin (serve-only) that formats Lunora worker logs in the terminal.
312
+ * Patches `process.stdout`/`process.stderr` fresh for each dev-server generation
313
+ * and restores them when that server closes.
314
+ */
228
315
  declare const logStreamPlugin: () => Plugin;
316
+ /**
317
+ * Warnings for one proxy table. Pure + exported so the behavior is unit-testable
318
+ * without booting a dev server.
319
+ */
320
+ declare const checkLunoraProxy: (proxy: Record<string, unknown> | undefined, label: string) => string[];
321
+ /**
322
+ * Warn when a dev/preview proxy routes `/_lunora/*` without `ws: true` (or with an
323
+ * origin-rewriting `changeOrigin`). See the module docs.
324
+ */
325
+ declare const proxyCheckPlugin: () => Plugin;
229
326
  /** The decision a {@link planViteRemoteBindings} call returns. */
230
327
  interface ViteRemotePlan {
231
328
  /** Idempotent disposer for the temp config; always present + safe to call. */
232
329
  cleanup: () => void;
233
330
  /**
234
- * Absolute path to the materialized temp wrangler config to hand the
235
- * cloudflare plugin's `configPath`, or `undefined` when remote mode is off
236
- * or nothing was materialized (no eligible binding, no wrangler file, …).
237
- */
331
+ * Absolute path to the materialized temp wrangler config to hand the
332
+ * cloudflare plugin's `configPath`, or `undefined` when remote mode is off
333
+ * or nothing was materialized (no eligible binding, no wrangler file, …).
334
+ */
238
335
  configPath?: string;
239
336
  /** Whether remote mode was requested for this dev session. */
240
337
  enabled: boolean;
@@ -253,122 +350,211 @@ interface PlanViteRemoteOptions {
253
350
  remoteEnv?: string;
254
351
  }
255
352
  /**
256
- * Decide whether the Vite dev worker uses remote bindings and, if so,
257
- * materialize the temp config. Pure decision + a single fs write via the
258
- * injected materializer; returns a `cleanup` for the dev server's close hook.
259
- *
260
- * There is no `--remote` flag on the Vite path (Vite has no Lunora CLI flags),
261
- * so the precedence reduces to `LUNORA_REMOTE` env > `lunora.json` `remote`.
262
- */
353
+ * Decide whether the Vite dev worker uses remote bindings and, if so,
354
+ * materialize the temp config. Pure decision + a single fs write via the
355
+ * injected materializer; returns a `cleanup` for the dev server's close hook.
356
+ *
357
+ * There is no `--remote` flag on the Vite path (Vite has no Lunora CLI flags),
358
+ * so the precedence reduces to `LUNORA_REMOTE` env > `lunora.json` `remote`.
359
+ *
360
+ * Call this from a `config` hook, never at plugin-factory time — see
361
+ * {@link remoteBindingsPlugin} for the two defects that timing caused.
362
+ */
263
363
  declare const planViteRemoteBindings: (options: PlanViteRemoteOptions) => ViteRemotePlan;
264
364
  /**
265
- * Wrap the cloudflare-plugin options so the dev worker loads the materialized
266
- * remote temp config (via `configPath`) when — and only when — remote mode is
267
- * on AND it's a `vite` serve. A `configPath` the caller already set wins (their
268
- * explicit choice), and during a production build nothing is injected, so the
269
- * deployed worker is never affected.
270
- *
271
- * Returns the wrapped options plus the plan, so `index.ts` can register the
272
- * cleanup on a close hook. Materialization happens lazily inside the `configPath`
273
- * resolution path: it's only meaningful during serve, but computing it eagerly
274
- * is harmless (the materializer is a no-op when disabled) and keeps the wiring
275
- * simple — the plan is computed once here.
276
- */
277
- declare const withRemoteBindings: (options: CloudflarePluginOptions, isServe: () => boolean, plan: ViteRemotePlan) => CloudflarePluginOptions;
365
+ * Wrap the cloudflare-plugin options so the dev worker loads the materialized
366
+ * remote temp config (via `configPath`) when — and only when — remote mode is
367
+ * on and a temp config was materialized. A `configPath` the caller already set
368
+ * wins (their explicit choice).
369
+ *
370
+ * Pure decision only — the serve-vs-build gate lives in
371
+ * {@link remoteBindingsPlugin}'s `config` hook, because the resolved Vite
372
+ * `command` is unknown at plugin-factory time. An eager serve check there would
373
+ * always read `command` as undefined and strip `configPath`.
374
+ */
375
+ declare const withRemoteBindings: (options: CloudflarePluginOptions, plan: ViteRemotePlan) => CloudflarePluginOptions;
376
+ /**
377
+ * A `enforce: "pre"` plugin that materializes the remote temp wrangler config
378
+ * and injects it into the cloudflare plugin's `configPath` — but only on a
379
+ * `vite` serve, never a production build (so the deployed worker is never
380
+ * affected) — then disposes the temp file when the dev server tears down.
381
+ *
382
+ * Both halves are deferred into the `config` hook, and each deferral closes a
383
+ * defect of its own.
384
+ *
385
+ * The command check: at plugin-factory time Vite has not yet resolved `serve`
386
+ * vs `build`, so it has to run here. An eager factory-time check always read
387
+ * `command` as undefined and stripped `configPath`, so remote bindings never
388
+ * activated on `vite dev` at all.
389
+ *
390
+ * The materialization: the temp config is a COPY of `wrangler.jsonc`, and
391
+ * Lunora provisions the bindings the project's code implies from
392
+ * `bindingsProvisionPlugin`'s own `config` hook — earlier in this same phase,
393
+ * since both are `enforce: "pre"` and that plugin is registered first. (It is a
394
+ * plugin of its own, registered unconditionally, precisely so this copy is not a
395
+ * binding short whenever `validateWrangler` is off — `wranglerValidatorPlugin`
396
+ * only validates, and is registered after this one.) Copying
397
+ * the file at factory time therefore snapshotted it BEFORE that write, and the
398
+ * dev worker booted against a config missing the binding Lunora had just added:
399
+ * a `vite dev` that logged `inferred bindings → AI (Workers AI)`, passed
400
+ * validation, and served a worker with no `env.AI`. That is the remote twin of
401
+ * the local defect the reconcile's move into `config` fixed.
402
+ *
403
+ * The injection mutates the SAME options object handed to `cloudflare()` in
404
+ * place — the cloudflare plugin reads `pluginConfig.configPath` lazily inside
405
+ * its own `config` hook, which runs after this `enforce: "pre"` one, so the
406
+ * injection takes effect.
407
+ *
408
+ * The disposer reads the CURRENT plan rather than a factory-time capture,
409
+ * because no plan exists until `config` has run.
410
+ *
411
+ * When remote mode was requested but nothing materialized (no eligible binding,
412
+ * no wrangler file, …), the plan's `reason` is logged so the degradation isn't
413
+ * silent.
414
+ *
415
+ * `options` is `undefined` on the BYO path (`cloudflare: false`), where the
416
+ * project constructs `cloudflare()` itself and Lunora has no options object to
417
+ * inject into: the materialized path is printed with what to do with it, rather
418
+ * than leaving `LUNORA_REMOTE` looking like it took effect.
419
+ */
420
+ declare const remoteBindingsPlugin: (options: CloudflarePluginOptions | undefined, planOptions: PlanViteRemoteOptions) => Plugin;
278
421
  /**
279
- * A tiny Vite plugin that runs the remote temp-config disposer when the dev
280
- * server tears down (`buildEnd` fires on close in serve; `closeBundle` covers
281
- * the build/close path). Idempotent cleanup means firing on both is safe.
282
- */
283
- declare const remoteBindingsCleanupPlugin: (cleanup: () => void) => Plugin;
422
+ * A `@visulima/vite-overlay` solution finder. Derived from the overlay's own
423
+ * options type so the shape can't drift from the installed package. The overlay
424
+ * runs every finder it's given (custom finders first, then its built-ins),
425
+ * sorted by `priority` descending, and shows the first non-`undefined` result.
426
+ *
427
+ * Note: this type (and {@link Solution}) is re-exported from `@lunora/vite` and
428
+ * intentionally tracks the installed `@visulima/vite-overlay` — if a future
429
+ * overlay release changes the finder contract, that surfaces here as a compile
430
+ * error rather than a silent drift.
431
+ */
432
+ type SolutionFinder = NonNullable<OverlayPluginOptions["solutionFinders"]>[number];
433
+ /** What a finder may return: a Markdown-rendered `{ header?, body }`, or `undefined` to defer. */
434
+ type Solution = NonNullable<Awaited<ReturnType<SolutionFinder["handle"]>>>;
435
+ /**
436
+ * Lunora's solution finder for the dev error overlay. A single finder that
437
+ * delegates to `@lunora/codegen`'s shared rule table (the same table the
438
+ * standalone `lunora dev` CLI prints to the terminal) and returns the first
439
+ * match — so one `priority` slot covers every Lunora rule and the overlay's
440
+ * built-in finders still run for anything we don't recognize (we return
441
+ * `undefined`).
442
+ *
443
+ * Priority is high so a Lunora-specific hint wins over the overlay's generic
444
+ * finder for the same error; a user's own finder can still outrank it with a
445
+ * higher `priority`.
446
+ */
447
+ declare const lunoraSolutionFinder: SolutionFinder;
448
+ /** The finders Lunora injects into the overlay by default. */
449
+ declare const lunoraSolutionFinders: ReadonlyArray<SolutionFinder>;
284
450
  /** Dev-server path the studio SPA is served from. */
285
451
  declare const STUDIO_PATH = "/__lunora";
286
- /** Static asset routes the studio document references. */
287
-
288
452
  /**
289
- * Build the user-facing studio URL from the dev server's resolved address.
290
- * Pure so it can be unit-tested without a live server. Prefers Vite's own
291
- * `resolvedUrls.local` (honours `host` / `base` / https); falls back to the raw
292
- * socket address, bracketing IPv6 and normalising the wildcard host.
293
- */
453
+ * Build the user-facing studio URL from the dev server's resolved address.
454
+ * Pure so it can be unit-tested without a live server. Prefers Vite's own
455
+ * `resolvedUrls.local` (honours `host` / `base` / https); falls back to the raw
456
+ * socket address, bracketing IPv6 and normalising the wildcard host.
457
+ */
294
458
  declare const buildStudioUrl: (input: {
295
459
  address?: AddressInfo | string;
296
460
  base?: string;
297
461
  resolvedLocal?: string;
298
462
  }) => string;
299
463
  /**
300
- * Vite plugin that serves the composed Lunora studio at
301
- * {@link STUDIO_PATH} during dev and prints its URL once the server is
302
- * listening. Dev-only (`apply: "serve"`); it adds nothing to production builds.
303
- *
304
- * Because `lunora dev` spawns Vite, this makes the studio available on
305
- * `lunora dev` and on a plain `vite` with no per-project files. The studio
306
- * is served as a prebuilt static bundle, independent of the host app.
307
- */
308
- declare const studioPlugin: () => Plugin;
464
+ * Vite plugin that serves the composed Lunora studio at
465
+ * {@link STUDIO_PATH} during dev and prints its URL once the server is
466
+ * listening. Dev-only (`apply: "serve"`); it adds nothing to production builds.
467
+ *
468
+ * Because `lunora dev` spawns Vite, this makes the studio available on
469
+ * `lunora dev` and on a plain `vite` with no per-project files. The studio
470
+ * is served as a prebuilt static bundle, independent of the host app.
471
+ */
472
+ declare const studioPlugin: (options: ResolvedLunoraPluginOptions) => Plugin;
309
473
  /**
310
- * When a module under `lunora/` throws while the Worker entry is first
311
- * evaluated, `@cloudflare/vite-plugin` surfaces the failure from deep inside
312
- * its `runner-worker` running in `workerd`. The real error crosses a workerd
313
- * RPC boundary on the way out, which drops the user-code stack frames — so all
314
- * the dev server sees is a bare, file-less message like:
315
- *
316
- * ```
317
- * TypeError: Cannot read properties of undefined (reading 'string')
318
- * at runInRunnerObject (workers/runner-worker/index.js:107:3)
319
- * at getWorkerEntryExportTypes (workers/runner-worker/index.js:246:24)
320
- * ```
321
- *
322
- * The classic cause is a **circular import**: a `lunora/` query/mutation/action
323
- * module runs `mutation({ args: { x: v.string() } })` at the top level while the
324
- * module it imported `v`/`query`/`mutation` from is still mid-initialization, so
325
- * those bindings read as `undefined`. The message names a validator method
326
- * (`'string'`, `'id'`, …) but never the file.
327
- *
328
- * We can't recover the dropped frames at this layer, but we can recognise the
329
- * shape of the failure and append an actionable hint pointing at the likely
330
- * cause — turning a dead-end stack into something a user can act on.
331
- */
474
+ * When a module under `lunora/` throws while the Worker entry is first
475
+ * evaluated, `@cloudflare/vite-plugin` surfaces the failure from deep inside
476
+ * its `runner-worker` running in `workerd`. The real error crosses a workerd
477
+ * RPC boundary on the way out, which drops the user-code stack frames — so all
478
+ * the dev server sees is a bare, file-less message like:
479
+ *
480
+ * ```
481
+ * TypeError: Cannot read properties of undefined (reading 'string')
482
+ * at runInRunnerObject (workers/runner-worker/index.js:107:3)
483
+ * at getWorkerEntryExportTypes (workers/runner-worker/index.js:246:24)
484
+ * ```
485
+ *
486
+ * The classic cause is a **circular import**: a `lunora/` query/mutation/action
487
+ * module runs `mutation({ args: { x: v.string() } })` at the top level while the
488
+ * module it imported `v`/`query`/`mutation` from is still mid-initialization, so
489
+ * those bindings read as `undefined`. The message names a validator method
490
+ * (`'string'`, `'id'`, …) but never the file.
491
+ *
492
+ * We can't recover the dropped frames at this layer, but we can recognise the
493
+ * shape of the failure and append an actionable hint pointing at the likely
494
+ * cause — turning a dead-end stack into something a user can act on.
495
+ */
332
496
  declare const WORKER_STARTUP_HINT: string;
333
497
  /**
334
- * True when `error` looks like a Worker-entry evaluation failure routed through
335
- * `@cloudflare/vite-plugin`'s runner worker (the stack references the runner
336
- * worker / export-types probe). Kept narrow so we only annotate this specific
337
- * class of dev-startup error.
338
- */
498
+ * True when `error` looks like a Worker-entry evaluation failure routed through
499
+ * `@cloudflare/vite-plugin`'s runner worker (the stack references the runner
500
+ * worker / export-types probe). Kept narrow so we only annotate this specific
501
+ * class of dev-startup error.
502
+ */
339
503
  declare const isWorkerEntryEvalError: (error: unknown) => boolean;
340
504
  /**
341
- * Append {@link WORKER_STARTUP_HINT} to a recognised Worker-entry eval error
342
- * (idempotently). Any other value is returned untouched.
343
- */
505
+ * Append {@link WORKER_STARTUP_HINT} to a recognised Worker-entry eval error
506
+ * (idempotently). Any other value is returned untouched.
507
+ */
344
508
  declare const augmentWorkerStartupError: (error: unknown) => unknown;
345
509
  /**
346
- * Wrap the startup hooks of `@cloudflare/vite-plugin`'s plugins so a Worker-entry
347
- * evaluation failure carries the Lunora hint. Returns a new array; the input
348
- * plugins are shallow-cloned (never mutated in place) so re-using the cloudflare
349
- * plugin instances elsewhere stays safe.
350
- */
510
+ * Wrap the startup hooks of `@cloudflare/vite-plugin`'s plugins so a Worker-entry
511
+ * evaluation failure carries the Lunora hint. Returns a new array; the input
512
+ * plugins are shallow-cloned (never mutated in place) so re-using the cloudflare
513
+ * plugin instances elsewhere stays safe.
514
+ */
351
515
  declare const withWorkerStartupHint: (plugins: ReadonlyArray<Plugin>) => Plugin[];
352
516
  /**
353
- * Vite plugin that validates the project's `wrangler.jsonc` against the
354
- * bindings implied by `lunora/schema.ts`. Throws (Vite renders nicely) on
355
- * missing requirements during `configResolved`. Delegates the parsing /
356
- * validation logic to `@lunora/config` so the rules stay in lockstep with
357
- * the CLI (`lunora deploy`).
358
- */
517
+ * Vite plugin that validates the project's `wrangler.jsonc` against the
518
+ * bindings implied by `lunora/schema.ts`. Throws (Vite renders nicely) on
519
+ * missing requirements during `configResolved`. Delegates the parsing /
520
+ * validation logic to `@lunora/config` so the rules stay in lockstep with
521
+ * the CLI (`lunora deploy`).
522
+ *
523
+ * Provisioning runs BEFORE this, in `bindingsProvisionPlugin`'s `config` hook,
524
+ * which is the order `lunora dev` uses (infer → reconcile, no validation pass):
525
+ * the bindings this check requires are the ones Lunora writes itself, so
526
+ * validating first killed the dev server the first time a project declared a
527
+ * `.global()` table or a container. That plugin is registered unconditionally and
528
+ * ahead of this one — the write is not optional the way the check is, and it must
529
+ * land in `config` to reach the worker at all (see its docblock).
530
+ *
531
+ * Skipped under `vite preview`, which resolves with `command: "serve"` and so
532
+ * runs `apply: "serve"` plugins: previewing a built app must not probe Docker.
533
+ */
359
534
  declare const wranglerValidatorPlugin: (options: ResolvedLunoraPluginOptions) => Plugin;
360
535
  /**
361
- * Lunora Vite plugin. Returns a flat array of Vite plugins that:
362
- *
363
- * 1. Run `@lunora/codegen` on startup + on schema file changes.
364
- * 2. Validate the project's `wrangler.jsonc` against the schema's implied bindings.
365
- * 3. Inject `@visulima/vite-overlay` for runtime error overlays (unless `overlay: false`).
366
- * 4. Include `@cloudflare/vite-plugin` so users get one-import setup (unless `cloudflare: false`).
367
- *
368
- * `@cloudflare/vite-plugin` and `@visulima/vite-overlay` are direct dependencies,
369
- * so they're imported statically — opt out per-feature via the options rather
370
- * than relying on whether they're installed.
371
- */
536
+ * Resolve the `overlay` toggle into the overlay plugin's options — or `false` to
537
+ * skip it. Lunora's solution finders are **prepended** so they run before the
538
+ * overlay's built-ins; a user's own finders are appended and can still win per
539
+ * error via a strictly higher `priority` (equal priority keeps Lunora first,
540
+ * since the overlay sorts stably). Lunora also forwards both `error` AND `warn`
541
+ * console calls by default (the overlay's own default is `["error"]` only) so
542
+ * Lunora's branded `warn` advisories surface in the browser too — the user can
543
+ * override `forwardedConsoleMethods`.
544
+ */
545
+ declare const resolveOverlayOption: (overlay: LunoraPluginOptions["overlay"]) => false | OverlayPluginOptions;
546
+ /**
547
+ * Lunora Vite plugin. Returns a flat array of Vite plugins that:
548
+ *
549
+ * 1. Run `@lunora/codegen` on startup + on schema file changes.
550
+ * 2. Validate the project's `wrangler.jsonc` against the schema's implied bindings.
551
+ * 3. Inject `@visulima/vite-overlay` for runtime error overlays (unless `overlay: false`).
552
+ * 4. Include `@cloudflare/vite-plugin` so users get one-import setup (unless `cloudflare: false`).
553
+ *
554
+ * `@cloudflare/vite-plugin` and `@visulima/vite-overlay` are direct dependencies,
555
+ * so they're imported statically — opt out per-feature via the options rather
556
+ * than relying on whether they're installed.
557
+ */
372
558
  declare const lunora: (options?: LunoraPluginOptions) => LunoraPlugins;
373
- declare const VERSION = "0.0.0";
374
- export { CLASS_A_WIRING, type ClassAWiring, type CloudflarePluginOptions, DEV_WORKER_ENV_VALUE, DEV_WORKER_ENV_VAR, LUNORA_WORKER_VIRTUAL_ID, type LunoraPluginOptions, type LunoraPlugins, type OverlayPluginOptions, type PlanViteRemoteOptions, type ReconcileResult, type ResolvedLunoraPluginOptions, STUDIO_PATH, VERSION, type ViteRemotePlan, WORKER_STARTUP_HINT, augmentWorkerStartupError, buildStudioUrl, buildWorkerEntrySource, codegenPlugin, createCommandProbe, devVariablesPlugin, frameworkComposePlugin, isAutoComposable, isWorkerEntryEvalError, logStreamPlugin, lunora, planViteRemoteBindings, reconcileWranglerCrons, remoteBindingsCleanupPlugin, studioPlugin, withDevWorkerEnv, withRemoteBindings, withWorkerStartupHint, wranglerValidatorPlugin };
559
+ declare const VERSION: string;
560
+ export { CLASS_A_WIRING, type ClassAWiring, type CloudflarePluginOptions, GENERATED_CLASS_MODULES, type GeneratedClassModule, LUNORA_API_UPDATED_EVENT, LUNORA_WORKER_VIRTUAL_ID, type LunoraPluginOptions, type LunoraPlugins, type LunoraShardConfig, type OverlayPluginOptions, type PlanViteRemoteOptions, type ResolvedLunoraPluginOptions, STUDIO_PATH, type Solution, type SolutionFinder, VERSION, type ViteRemotePlan, WORKER_STARTUP_HINT, augmentWorkerStartupError, buildStudioUrl, buildWorkerEntrySource, checkLunoraProxy, codegenPlugin, containerLogsPlugin, devStatePlugin, devVariablesPlugin, frameworkComposePlugin, isAutoComposable, isWorkerEntryEvalError, logStreamPlugin, lunora, lunoraSolutionFinder, lunoraSolutionFinders, planViteRemoteBindings, proxyCheckPlugin, remoteBindingsPlugin, resolveOverlayOption, studioPlugin, withRemoteBindings, withWorkerStartupHint, wranglerValidatorPlugin };