@oselvar/sveltekit-add-worker-exports 0.3.4 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +59 -23
- package/dist/index.d.ts +8 -0
- package/dist/index.js +71 -55
- package/package.json +5 -7
- package/dist/hooks.d.ts +0 -10
- package/dist/hooks.js +0 -9
package/README.md
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
# @oselvar/sveltekit-add-worker-exports
|
|
2
2
|
|
|
3
|
-
A Vite plugin that makes any class-based Cloudflare Worker export (Durable Objects, Workflows, `WorkerEntrypoint` RPC, voice agents, …) work with SvelteKit on Cloudflare, in both dev and production.
|
|
3
|
+
A Vite plugin that makes any class-based Cloudflare Worker export (Durable Objects, Workflows, `WorkerEntrypoint` RPC, voice agents, …) and any non-fetch handler (`scheduled`, `queue`, `email`, `tail`, `trace`) work with SvelteKit on Cloudflare, in both dev and production.
|
|
4
4
|
|
|
5
|
-
**Build mode:** SvelteKit's `adapter-cloudflare` generates `_worker.js` with only a default export (the fetch handler). Cloudflare Workers requires class-based bindings (Durable Objects, Workflows, `WorkerEntrypoint`, etc.) to be **named exports**. This plugin post-processes the build output to merge
|
|
5
|
+
**Build mode:** SvelteKit's `adapter-cloudflare` generates `_worker.js` with only a default export (the fetch handler). Cloudflare Workers requires class-based bindings (Durable Objects, Workflows, `WorkerEntrypoint`, etc.) to be **named exports**, and non-fetch handlers (`scheduled`, `queue`, `email`, …) to be **methods on the default export**. This plugin post-processes the build output to merge both kinds onto SvelteKit's worker.
|
|
6
6
|
|
|
7
|
-
**Dev mode:** `getPlatformProxy` (used by `adapter-cloudflare` in dev) can't run internal Durable Objects, Workflows, or other class-based bindings. This plugin starts a separate wrangler dev server that runs the real worker with hot-reload. SvelteKit `+server.ts` handlers call bindings through `platform.env.MY_BINDING.<rpc>()` as usual — the plugin rewrites those bindings to point at the sidecar via wrangler's dev registry, so cross-worker calls Just Work. WebSocket clients in dev connect to the sidecar directly on a separate port — see [WebSockets](#websockets) below.
|
|
7
|
+
**Dev mode:** `getPlatformProxy` (used by `adapter-cloudflare` in dev) can't run internal Durable Objects, Workflows, or other class-based bindings. This plugin starts a separate wrangler dev server that runs the real worker with hot-reload. SvelteKit `+server.ts` handlers call bindings through `platform.env.MY_BINDING.<rpc>()` as usual — the plugin rewrites those bindings to point at the sidecar via wrangler's dev registry, so cross-worker calls Just Work. WebSocket clients in dev connect to the sidecar directly on a separate port — see [WebSockets](#websockets) below. The sidecar also exposes `/__scheduled` so `scheduled` handlers can be fired manually in dev — see [Scheduled, queue, email, tail handlers](#scheduled-queue-email-tail-handlers).
|
|
8
8
|
|
|
9
9
|
## What this works with
|
|
10
10
|
|
|
11
|
-
The plugin is binding-agnostic: if Cloudflare resolves it through a named class export plus a `wrangler.jsonc` binding, the plugin handles it. Confirmed working:
|
|
11
|
+
The plugin is binding-agnostic: if Cloudflare resolves it through a named class export plus a `wrangler.jsonc` binding, or through a method on the default export, the plugin handles it. Confirmed working:
|
|
12
12
|
|
|
13
13
|
- Durable Objects
|
|
14
14
|
- Workflows (`WorkflowEntrypoint`)
|
|
15
15
|
- Voice agents
|
|
16
|
+
- `scheduled` (cron triggers) — see [Scheduled, queue, email, tail handlers](#scheduled-queue-email-tail-handlers)
|
|
16
17
|
|
|
17
|
-
It should also work with `WorkerEntrypoint` RPC and any future class-based export that follows the same export-plus-binding pattern. The examples below use Durable Objects and Workflows because they're the most common, but the wiring is the same for any class-based entrypoint — export the class from your entry point, declare the binding in `wrangler.jsonc`, and call it via `platform.env.MY_BINDING` in your routes.
|
|
18
|
+
It should also work with `WorkerEntrypoint` RPC and any future class-based export that follows the same export-plus-binding pattern, as well as `queue`, `email`, `tail`, and `trace` — anything Cloudflare invokes as a method on the worker's default export. The examples below use Durable Objects and Workflows because they're the most common, but the wiring is the same for any class-based entrypoint — export the class from your entry point, declare the binding in `wrangler.jsonc`, and call it via `platform.env.MY_BINDING` in your routes.
|
|
18
19
|
|
|
19
20
|
## Install
|
|
20
21
|
|
|
@@ -111,6 +112,32 @@ A handy shortcut is to add a `preview` script to `package.json`:
|
|
|
111
112
|
|
|
112
113
|
> Note: `vite preview` is *not* suitable here — it only serves static assets and cannot run Durable Objects. Always use `wrangler dev` to preview the production worker.
|
|
113
114
|
|
|
115
|
+
## Scheduled, queue, email, tail handlers
|
|
116
|
+
|
|
117
|
+
Cloudflare invokes non-fetch handlers (`scheduled`, `queue`, `email`, `tail`, `trace`) as methods on the worker's default export, not as named exports. Put them on the `default` export of your entry point and the plugin merges them onto the production worker's default alongside SvelteKit's fetch handler:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
// src/lib/server/index.ts
|
|
121
|
+
export { MyDurableObject } from './MyDurableObject';
|
|
122
|
+
export default {
|
|
123
|
+
async scheduled(event: ScheduledEvent, env: Env, ctx: ExecutionContext) {
|
|
124
|
+
// runs from the cron triggers in wrangler.jsonc
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
If you also need a dev-only `fetch` (e.g. for WebSocket upgrades), put it on the same default — the plugin keeps the non-`fetch` handlers and drops `fetch` in production. See [WebSockets](#websockets) below for the full shape.
|
|
130
|
+
|
|
131
|
+
### Firing scheduled in dev
|
|
132
|
+
|
|
133
|
+
Wrangler dev never auto-fires crons — `triggers.crons` in `wrangler.jsonc` is only honored on the real Cloudflare edge. The plugin enables `testScheduled` on the sidecar so you can invoke the handler manually:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
curl 'http://localhost:8787/__scheduled?cron=*+*+*+*+*'
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The `cron` query parameter (URL-encoded — `+` instead of spaces) is what gets passed to your handler as `event.cron`. Stdout from the sidecar lands in the vite terminal.
|
|
140
|
+
|
|
114
141
|
## WebSockets
|
|
115
142
|
|
|
116
143
|
`vite dev` doesn't proxy WebSocket upgrades to the wrangler-dev sidecar, so in dev mode the browser needs to connect to the sidecar directly. The plugin exposes the sidecar's port as a compile-time constant `__DEV_WORKER_PORT__` for exactly this.
|
|
@@ -132,12 +159,15 @@ export async function forwardWebSocket<T extends Rpc.DurableObjectBranded | unde
|
|
|
132
159
|
}
|
|
133
160
|
```
|
|
134
161
|
|
|
135
|
-
|
|
162
|
+
Put a `fetch` on the entry's default export so the dev sidecar can receive the direct connection:
|
|
136
163
|
|
|
137
164
|
```typescript
|
|
138
|
-
// src/lib/server/
|
|
165
|
+
// src/lib/server/index.ts
|
|
139
166
|
import { forwardWebSocket } from './forwardWebSocket';
|
|
140
167
|
|
|
168
|
+
export { MyDurableObject } from './MyDurableObject';
|
|
169
|
+
export { MyWorkflow } from './MyWorkflow';
|
|
170
|
+
|
|
141
171
|
export default {
|
|
142
172
|
async fetch(request: Request, env: Env): Promise<Response> {
|
|
143
173
|
const match = new URL(request.url).pathname.match(/^\/ws\/(.+)$/);
|
|
@@ -147,16 +177,7 @@ export default {
|
|
|
147
177
|
};
|
|
148
178
|
```
|
|
149
179
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
// src/lib/server/index.ts
|
|
154
|
-
export { MyDurableObject } from './MyDurableObject';
|
|
155
|
-
export { MyWorkflow } from './MyWorkflow';
|
|
156
|
-
export { default } from './devHandler';
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
In production, the dev handler is *not* used — SvelteKit serves the same path through a `+server.ts` route, which delegates to the same helper:
|
|
180
|
+
In production this `fetch` is dropped (SvelteKit owns request handling — the plugin's merge strips it). The same path is served through a `+server.ts` route that delegates to the same helper:
|
|
160
181
|
|
|
161
182
|
```typescript
|
|
162
183
|
// src/routes/ws/[id]/+server.ts
|
|
@@ -211,11 +232,14 @@ The plugin runs in the `closeBundle` hook (after SvelteKit's adapter has generat
|
|
|
211
232
|
|
|
212
233
|
1. Bundles your `entryPoint` with esbuild into `_extra_exports.js`
|
|
213
234
|
2. Renames the original `_worker.js` to `_sveltekit_worker.js`
|
|
214
|
-
3. Creates a new `_worker.js` that re-exports
|
|
235
|
+
3. Creates a new `_worker.js` that re-exports the named exports and merges the entry's `default` handlers (`scheduled`, `queue`, `email`, …) onto the SvelteKit default:
|
|
215
236
|
|
|
216
237
|
```javascript
|
|
217
|
-
|
|
238
|
+
import sveltekitWorker from './_sveltekit_worker.js';
|
|
239
|
+
import * as extra from './_extra_exports.js';
|
|
218
240
|
export * from './_extra_exports.js';
|
|
241
|
+
const { fetch: _ignored, ...extraHandlers } = extra.default ?? {};
|
|
242
|
+
export default { ...sveltekitWorker, ...extraHandlers };
|
|
219
243
|
```
|
|
220
244
|
|
|
221
245
|
The operation is idempotent -- if `_sveltekit_worker.js` already exists, the plugin skips.
|
|
@@ -231,10 +255,10 @@ The plugin reads your wrangler config, creates a temporary config with `main` po
|
|
|
231
255
|
|
|
232
256
|
### Generating typed bindings
|
|
233
257
|
|
|
234
|
-
The dev plugin creates a temporary `.
|
|
258
|
+
The dev plugin creates a temporary `.dev-worker-wrangler.jsonc` with `main` pointing to your source entry point. Use it to generate fully generic Cloudflare types:
|
|
235
259
|
|
|
236
260
|
```bash
|
|
237
|
-
wrangler types --config .
|
|
261
|
+
wrangler types --config .dev-worker-wrangler.jsonc
|
|
238
262
|
```
|
|
239
263
|
|
|
240
264
|
This produces typed DO bindings like `DurableObjectNamespace<MyDurableObject>` instead of the untyped `DurableObjectNamespace` you get from the default `wrangler.jsonc` (whose `main` points to the SvelteKit build output, which doesn't exist during dev).
|
|
@@ -244,17 +268,29 @@ Add this to your `package.json` scripts for convenience:
|
|
|
244
268
|
```json
|
|
245
269
|
{
|
|
246
270
|
"scripts": {
|
|
247
|
-
"types": "wrangler types --config .
|
|
271
|
+
"types": "wrangler types --config .dev-worker-wrangler.jsonc"
|
|
248
272
|
}
|
|
249
273
|
}
|
|
250
274
|
```
|
|
251
275
|
|
|
252
|
-
Note: the `.
|
|
276
|
+
Note: the `.dev-worker-wrangler.jsonc` file is generated when the dev server starts. Run `pnpm dev` at least once before running `wrangler types`.
|
|
253
277
|
|
|
254
278
|
## Why this exists
|
|
255
279
|
|
|
256
280
|
SvelteKit's adapter-cloudflare does not support named exports from the worker entry point ([sveltejs/kit#1712](https://github.com/sveltejs/kit/issues/1712)) — which blocks every class-based Cloudflare binding, not just Durable Objects. Additionally, `getPlatformProxy` (used for local dev) cannot run internal class-based bindings because it uses an empty worker script.
|
|
257
281
|
|
|
282
|
+
## When this plugin can be retired
|
|
283
|
+
|
|
284
|
+
This plugin is a stopgap. The single blocker for retirement is [sveltejs/kit#15627](https://github.com/sveltejs/kit/pull/15627) — which replaces `adapter-cloudflare`'s custom build with `@cloudflare/vite-plugin`. Open as of writing. Closes [#1712](https://github.com/sveltejs/kit/issues/1712), [#10496](https://github.com/sveltejs/kit/issues/10496), [#13692](https://github.com/sveltejs/kit/issues/13692), [#2963](https://github.com/sveltejs/kit/issues/2963), [#13300](https://github.com/sveltejs/kit/issues/13300), [#1519](https://github.com/sveltejs/kit/issues/1519).
|
|
285
|
+
|
|
286
|
+
Once that PR lands, `@cloudflare/vite-plugin` handles everything this plugin does, natively:
|
|
287
|
+
|
|
288
|
+
- **Build:** the plugin bundles a single worker entry that exports `default` + named classes directly — no `_worker.js` post-processing, no second esbuild pass to merge exports.
|
|
289
|
+
- **Dev:** Durable Objects and Workflows run in the same worker as SvelteKit on real workerd, hot-reloaded — no sidecar via `unstable_startWorker`, no platform-proxy `script_name` rewrite, no separate WebSocket port, no dev registry routing.
|
|
290
|
+
- **Types:** `wrangler types` resolves typed bindings (`DurableObjectNamespace<MyDO>`) from the user entry, no `.dev-worker-wrangler.jsonc` indirection.
|
|
291
|
+
|
|
292
|
+
Side note: [cloudflare/workers-sdk#14013](https://github.com/cloudflare/workers-sdk/pull/14013) introduces an experimental `cloudflare.config.ts` flow (typed `exports` API) where the Durable Object branch currently throws `"Durable Object exports are not currently supported."` (see [`convert.ts`](https://github.com/cloudflare/workers-sdk/blob/main/packages/config/src/convert.ts)) and Workflows are commented out. This is a separate, opt-in config surface — the standard `wrangler.jsonc` path that kit#15627 uses already supports DO and Workflow named exports, so this limitation does **not** gate retirement.
|
|
293
|
+
|
|
258
294
|
## License
|
|
259
295
|
|
|
260
296
|
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,14 @@
|
|
|
21
21
|
* @see https://github.com/sveltejs/kit/issues/1712
|
|
22
22
|
*/
|
|
23
23
|
import type { Plugin } from 'vite';
|
|
24
|
+
/**
|
|
25
|
+
* Parses a wrangler config file. Picks the parser by extension:
|
|
26
|
+
* `.toml` uses smol-toml; everything else (`.jsonc`, `.json`, or no
|
|
27
|
+
* extension) uses jsonc-parser, which handles plain JSON fine.
|
|
28
|
+
*
|
|
29
|
+
* Exported for tests; the dev plugin uses it via the configureServer hook.
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseWranglerConfig(path: string, contents: string): unknown;
|
|
24
32
|
export interface AddWorkerExportsOptions {
|
|
25
33
|
/** File that exports Durable Object and/or Workflow classes */
|
|
26
34
|
entryPoint: string;
|
package/dist/index.js
CHANGED
|
@@ -23,20 +23,23 @@
|
|
|
23
23
|
import { build } from 'esbuild';
|
|
24
24
|
import { existsSync } from 'node:fs';
|
|
25
25
|
import { access, readFile, rename, writeFile, unlink } from 'node:fs/promises';
|
|
26
|
+
import { builtinModules as NODE_BUILTINS } from 'node:module';
|
|
26
27
|
import { homedir } from 'node:os';
|
|
27
28
|
import { join, resolve } from 'node:path';
|
|
28
29
|
import { parse as parseJsonc } from 'jsonc-parser';
|
|
30
|
+
import { getNodeCompat } from 'miniflare';
|
|
31
|
+
import { parse as parseToml } from 'smol-toml';
|
|
32
|
+
/**
|
|
33
|
+
* Parses a wrangler config file. Picks the parser by extension:
|
|
34
|
+
* `.toml` uses smol-toml; everything else (`.jsonc`, `.json`, or no
|
|
35
|
+
* extension) uses jsonc-parser, which handles plain JSON fine.
|
|
36
|
+
*
|
|
37
|
+
* Exported for tests; the dev plugin uses it via the configureServer hook.
|
|
38
|
+
*/
|
|
39
|
+
export function parseWranglerConfig(path, contents) {
|
|
40
|
+
return path.endsWith('.toml') ? parseToml(contents) : parseJsonc(contents);
|
|
41
|
+
}
|
|
29
42
|
const DEFAULT_DEV_PORT = 8787;
|
|
30
|
-
const NODE_BUILTINS = [
|
|
31
|
-
'assert', 'async_hooks', 'buffer', 'child_process', 'cluster', 'console',
|
|
32
|
-
'constants', 'crypto', 'dgram', 'diagnostics_channel', 'dns', 'domain',
|
|
33
|
-
'events', 'fs', 'fs/promises', 'http', 'http2', 'https', 'inspector',
|
|
34
|
-
'module', 'net', 'os', 'path', 'path/posix', 'path/win32', 'perf_hooks',
|
|
35
|
-
'process', 'punycode', 'querystring', 'readline', 'repl', 'stream',
|
|
36
|
-
'stream/consumers', 'stream/promises', 'stream/web', 'string_decoder',
|
|
37
|
-
'sys', 'timers', 'timers/promises', 'tls', 'trace_events', 'tty', 'url',
|
|
38
|
-
'util', 'util/types', 'v8', 'vm', 'wasi', 'worker_threads', 'zlib'
|
|
39
|
-
];
|
|
40
43
|
/**
|
|
41
44
|
* Mirrors wrangler's internal getRegistryPath() — wrangler doesn't export it.
|
|
42
45
|
* Workers register themselves under this path so cross-worker `script_name`
|
|
@@ -117,9 +120,22 @@ function buildPlugin(options) {
|
|
|
117
120
|
],
|
|
118
121
|
outfile: exportsPath
|
|
119
122
|
});
|
|
120
|
-
// Rename original worker and create merged entry point
|
|
123
|
+
// Rename original worker and create merged entry point.
|
|
124
|
+
//
|
|
125
|
+
// `export *` re-exports named exports only, so class-based bindings
|
|
126
|
+
// (DOs, Workflows, WorkerEntrypoint) from `_extra_exports.js` flow
|
|
127
|
+
// through. Non-fetch handlers (scheduled, queue, email, tail, trace)
|
|
128
|
+
// live on the user entry's `default` export — Cloudflare invokes
|
|
129
|
+
// them as methods on the worker's default object, not as named
|
|
130
|
+
// exports — so we spread them onto the SvelteKit default. `fetch`
|
|
131
|
+
// is dropped from the user default because SvelteKit owns request
|
|
132
|
+
// handling in production.
|
|
121
133
|
await rename(workerPath, sveltekitPath);
|
|
122
|
-
await writeFile(workerPath, `
|
|
134
|
+
await writeFile(workerPath, `import sveltekitWorker from './_sveltekit_worker.js';\n` +
|
|
135
|
+
`import * as extra from './_extra_exports.js';\n` +
|
|
136
|
+
`export * from './_extra_exports.js';\n` +
|
|
137
|
+
`const { fetch: _ignored, ...extraHandlers } = extra.default ?? {};\n` +
|
|
138
|
+
`export default { ...sveltekitWorker, ...extraHandlers };\n`);
|
|
123
139
|
}
|
|
124
140
|
};
|
|
125
141
|
}
|
|
@@ -128,11 +144,12 @@ function devPlugin(options) {
|
|
|
128
144
|
let worker = null;
|
|
129
145
|
let tempConfigPath = null;
|
|
130
146
|
let proxyConfigPath = null;
|
|
131
|
-
let typesConfigPath = null;
|
|
132
147
|
async function readRawConfig() {
|
|
133
148
|
const { unstable_readConfig } = await import('wrangler');
|
|
134
149
|
const parsed = unstable_readConfig(options.wranglerConfig ? { config: options.wranglerConfig } : {});
|
|
135
|
-
|
|
150
|
+
const path = parsed.configPath;
|
|
151
|
+
const contents = await readFile(path, 'utf-8');
|
|
152
|
+
return { path, contents };
|
|
136
153
|
}
|
|
137
154
|
return {
|
|
138
155
|
name: 'add-worker-exports-dev',
|
|
@@ -146,16 +163,28 @@ function devPlugin(options) {
|
|
|
146
163
|
},
|
|
147
164
|
async configureServer(server) {
|
|
148
165
|
const { unstable_startWorker } = await import('wrangler');
|
|
149
|
-
const
|
|
150
|
-
const
|
|
166
|
+
const { path: configPath, contents } = await readRawConfig();
|
|
167
|
+
const baseConfig = parseWranglerConfig(configPath, contents);
|
|
168
|
+
const sidecarName = `${baseConfig.name ?? 'sveltekit'}-dev-worker`;
|
|
169
|
+
// When CLOUDFLARE_ENV is set, wrangler suffixes the registered
|
|
170
|
+
// worker name with `-${env}` (see appendEnvName in wrangler), so
|
|
171
|
+
// cross-worker `script_name` lookups must use the suffixed name.
|
|
172
|
+
// We don't suffix `devConfig.name` itself — wrangler does that
|
|
173
|
+
// based on CLOUDFLARE_ENV when starting the sidecar.
|
|
174
|
+
const envName = process.env.CLOUDFLARE_ENV;
|
|
175
|
+
const registeredSidecarName = envName ? `${sidecarName}-${envName}` : sidecarName;
|
|
151
176
|
// Copy the raw config and override main, name, and dev port
|
|
152
|
-
const devConfig =
|
|
177
|
+
const devConfig = structuredClone(baseConfig);
|
|
153
178
|
devConfig.name = sidecarName;
|
|
154
179
|
devConfig.main = options.entryPoint;
|
|
155
180
|
devConfig.dev = { ...devConfig.dev, port: devPort };
|
|
156
181
|
delete devConfig.assets;
|
|
182
|
+
// The user can also pass this file to `wrangler types --config
|
|
183
|
+
// .dev-worker-wrangler.jsonc` to get typed bindings like
|
|
184
|
+
// DurableObjectNamespace<EchoDO> resolved from the source entry.
|
|
185
|
+
const devConfigJson = JSON.stringify(devConfig, null, '\t');
|
|
157
186
|
tempConfigPath = resolve('.dev-worker-wrangler.jsonc');
|
|
158
|
-
await writeFile(tempConfigPath,
|
|
187
|
+
await writeFile(tempConfigPath, devConfigJson);
|
|
159
188
|
// Write a wrangler config for adapter-cloudflare's getPlatformProxy
|
|
160
189
|
// (used by vite dev for platform.env). It can't run internal DOs or
|
|
161
190
|
// Workflows itself -- those are served by the sidecar above. Rewrite
|
|
@@ -163,30 +192,32 @@ function devPlugin(options) {
|
|
|
163
192
|
// (script_name pointing at the sidecar) so platform.env.MY_DO and
|
|
164
193
|
// platform.env.MY_WORKFLOW calls in +server.ts reach the sidecar via
|
|
165
194
|
// the wrangler dev registry.
|
|
166
|
-
const proxyConfig =
|
|
167
|
-
|
|
168
|
-
|
|
195
|
+
const proxyConfig = structuredClone(baseConfig);
|
|
196
|
+
// Wrangler does not merge per-env `durable_objects`/`workflows`/
|
|
197
|
+
// `migrations` arrays with the top-level — the selected env wholly
|
|
198
|
+
// overrides them. So we patch only the scope wrangler will actually
|
|
199
|
+
// use: top-level when no env, env[envName] when CLOUDFLARE_ENV is set.
|
|
200
|
+
const activeScope = envName ? proxyConfig.env?.[envName] : proxyConfig;
|
|
201
|
+
if (envName && !activeScope) {
|
|
202
|
+
throw new Error(`CLOUDFLARE_ENV="${envName}" but no \`env.${envName}\` block in the wrangler config`);
|
|
203
|
+
}
|
|
204
|
+
if (activeScope.durable_objects?.bindings) {
|
|
205
|
+
activeScope.durable_objects.bindings = activeScope.durable_objects.bindings.map((b) => b.script_name ? b : { ...b, script_name: registeredSidecarName });
|
|
169
206
|
}
|
|
170
|
-
if (Array.isArray(
|
|
171
|
-
|
|
207
|
+
if (Array.isArray(activeScope.workflows)) {
|
|
208
|
+
activeScope.workflows = activeScope.workflows.map((w) => w.script_name ? w : { ...w, script_name: registeredSidecarName });
|
|
172
209
|
}
|
|
173
|
-
delete
|
|
210
|
+
delete activeScope.migrations;
|
|
174
211
|
proxyConfigPath = resolve('.platform-proxy-wrangler.jsonc');
|
|
175
212
|
await writeFile(proxyConfigPath, JSON.stringify(proxyConfig, null, '\t'));
|
|
176
|
-
// A third config used only by `wrangler types`. Identical to the dev
|
|
177
|
-
// config but kept separate so the user can run `wrangler types
|
|
178
|
-
// --config .types-worker-wrangler.jsonc` to get typed bindings like
|
|
179
|
-
// DurableObjectNamespace<EchoDO> resolved from the source entry.
|
|
180
|
-
const typesConfig = parseJsonc(rawJson);
|
|
181
|
-
typesConfig.name = sidecarName;
|
|
182
|
-
typesConfig.main = options.entryPoint;
|
|
183
|
-
typesConfig.dev = { ...typesConfig.dev, port: devPort };
|
|
184
|
-
delete typesConfig.assets;
|
|
185
|
-
typesConfigPath = resolve('.types-worker-wrangler.jsonc');
|
|
186
|
-
await writeFile(typesConfigPath, JSON.stringify(typesConfig, null, '\t'));
|
|
187
213
|
worker = await unstable_startWorker({
|
|
188
214
|
config: tempConfigPath,
|
|
189
|
-
|
|
215
|
+
// `testScheduled` mounts a `/__scheduled` endpoint on the sidecar
|
|
216
|
+
// so cron handlers can be invoked manually in dev — wrangler dev
|
|
217
|
+
// never auto-fires crons. Curl
|
|
218
|
+
// `http://localhost:<devPort>/__scheduled?cron=*+*+*+*+*` to
|
|
219
|
+
// trigger your `scheduled` handler.
|
|
220
|
+
dev: { registry: getWranglerRegistryPath(), testScheduled: true },
|
|
190
221
|
build: {
|
|
191
222
|
nodejsCompatMode: (parsedConfig) => getNodejsCompatMode(parsedConfig.compatibility_date, parsedConfig.compatibility_flags)
|
|
192
223
|
}
|
|
@@ -202,9 +233,6 @@ function devPlugin(options) {
|
|
|
202
233
|
if (proxyConfigPath) {
|
|
203
234
|
await unlink(proxyConfigPath).catch(() => { });
|
|
204
235
|
}
|
|
205
|
-
if (typesConfigPath) {
|
|
206
|
-
await unlink(typesConfigPath).catch(() => { });
|
|
207
|
-
}
|
|
208
236
|
});
|
|
209
237
|
}
|
|
210
238
|
};
|
|
@@ -219,23 +247,11 @@ async function exists(path) {
|
|
|
219
247
|
}
|
|
220
248
|
}
|
|
221
249
|
/**
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
* compat plugin and warns about `node:*` imports even when
|
|
250
|
+
* wrangler's `unstable_startWorker` does not derive this from the config
|
|
251
|
+
* flags automatically — without it, wrangler falls back to the legacy
|
|
252
|
+
* nodejs compat plugin and warns about `node:*` imports even when
|
|
226
253
|
* `nodejs_compat` is enabled.
|
|
227
254
|
*/
|
|
228
255
|
function getNodejsCompatMode(compatibilityDate, compatibilityFlags = []) {
|
|
229
|
-
|
|
230
|
-
const hasCompatV2 = compatibilityFlags.includes('nodejs_compat_v2');
|
|
231
|
-
const hasNoCompatV2 = compatibilityFlags.includes('no_nodejs_compat_v2');
|
|
232
|
-
const hasAls = compatibilityFlags.includes('nodejs_als');
|
|
233
|
-
const date = compatibilityDate ?? '2000-01-01';
|
|
234
|
-
if (hasCompatV2 || (hasCompat && date >= '2024-09-23' && !hasNoCompatV2))
|
|
235
|
-
return 'v2';
|
|
236
|
-
if (hasCompat)
|
|
237
|
-
return 'v1';
|
|
238
|
-
if (hasAls)
|
|
239
|
-
return 'als';
|
|
240
|
-
return null;
|
|
256
|
+
return getNodeCompat(compatibilityDate, [...compatibilityFlags]).mode;
|
|
241
257
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oselvar/sveltekit-add-worker-exports",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Vite plugin that adds Durable Object and Workflow exports to SvelteKit Cloudflare workers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -10,10 +10,6 @@
|
|
|
10
10
|
".": {
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"import": "./dist/index.js"
|
|
13
|
-
},
|
|
14
|
-
"./hooks": {
|
|
15
|
-
"types": "./dist/hooks.d.ts",
|
|
16
|
-
"import": "./dist/hooks.js"
|
|
17
13
|
}
|
|
18
14
|
},
|
|
19
15
|
"files": [
|
|
@@ -48,15 +44,17 @@
|
|
|
48
44
|
"release-it": "^20.2.0",
|
|
49
45
|
"typescript": "^6.0.3",
|
|
50
46
|
"vite": "^8.0.16",
|
|
47
|
+
"vitest": "^4.1.8",
|
|
51
48
|
"wrangler": "^4.98.0"
|
|
52
49
|
},
|
|
53
50
|
"scripts": {
|
|
54
51
|
"build": "tsc",
|
|
55
|
-
"test": "tsc --noEmit",
|
|
52
|
+
"test": "vitest run && tsc --noEmit",
|
|
56
53
|
"prepublishOnly": "tsc",
|
|
57
54
|
"release": "release-it"
|
|
58
55
|
},
|
|
59
56
|
"dependencies": {
|
|
60
|
-
"jsonc-parser": "^3.3.1"
|
|
57
|
+
"jsonc-parser": "^3.3.1",
|
|
58
|
+
"smol-toml": "^1.6.1"
|
|
61
59
|
}
|
|
62
60
|
}
|
package/dist/hooks.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SvelteKit `Handle` re-exported for users.
|
|
3
|
-
*
|
|
4
|
-
* Kept as a no-op for backwards compatibility. Wrangler 4.98.0 fixed
|
|
5
|
-
* cross-worker workflow routing in `getPlatformProxy`
|
|
6
|
-
* (cloudflare/workers-sdk#13863), so `platform.env.MY_WORKFLOW` is now a
|
|
7
|
-
* real binding in both dev and production — no synthesis required.
|
|
8
|
-
*/
|
|
9
|
-
import type { Handle } from '@sveltejs/kit';
|
|
10
|
-
export declare const handle: Handle;
|
package/dist/hooks.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SvelteKit `Handle` re-exported for users.
|
|
3
|
-
*
|
|
4
|
-
* Kept as a no-op for backwards compatibility. Wrangler 4.98.0 fixed
|
|
5
|
-
* cross-worker workflow routing in `getPlatformProxy`
|
|
6
|
-
* (cloudflare/workers-sdk#13863), so `platform.env.MY_WORKFLOW` is now a
|
|
7
|
-
* real binding in both dev and production — no synthesis required.
|
|
8
|
-
*/
|
|
9
|
-
export const handle = ({ event, resolve }) => resolve(event);
|