@lunora/vite 1.0.0-alpha.13 → 1.0.0-alpha.131

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