@oselvar/sveltekit-add-worker-exports 0.3.0 → 0.3.2
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 +22 -6
- package/dist/hooks.d.ts +10 -0
- package/dist/hooks.js +9 -0
- package/dist/index.d.ts +7 -3
- package/dist/index.js +93 -18
- package/package.json +61 -50
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ export default defineConfig({
|
|
|
87
87
|
});
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
Point `adapter-cloudflare`'s platform proxy at the generated `.platform-proxy-wrangler.jsonc`. The plugin writes this file with internal Durable Object bindings rewritten to cross-worker form (each gets a `script_name` pointing at the sidecar).
|
|
90
|
+
Point `adapter-cloudflare`'s platform proxy at the generated `.platform-proxy-wrangler.jsonc`. The plugin writes this file with internal Durable Object and Workflow bindings rewritten to cross-worker form (each gets a `script_name` pointing at the sidecar), so `platform.env.MY_DO` and `platform.env.MY_WORKFLOW` calls in `+server.ts` reach the sidecar via the wrangler dev registry. Without this config path, `getPlatformProxy` would try to run the DO/Workflow classes itself and warn that it can't:
|
|
91
91
|
|
|
92
92
|
```javascript
|
|
93
93
|
// svelte.config.js
|
|
@@ -129,7 +129,23 @@ declare global {
|
|
|
129
129
|
}
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
-
The plugin auto-discovers your `wrangler.jsonc` (or `wrangler.toml`) and reads DO bindings, migrations, and compatibility settings from it. It overrides only the `main` entry point to
|
|
132
|
+
The plugin auto-discovers your `wrangler.jsonc` (or `wrangler.toml`) and reads DO bindings, workflows, migrations, and compatibility settings from it. It overrides only the `main` entry point to point at your source entry.
|
|
133
|
+
|
|
134
|
+
### Dev mode: calling Workflows
|
|
135
|
+
|
|
136
|
+
`+server.ts` calls workflows the same way it does in production:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
export const POST: RequestHandler = async ({ params, request, platform }) => {
|
|
140
|
+
const userMessage = await request.text();
|
|
141
|
+
const instance = await platform!.env.MY_WORKFLOW.create({
|
|
142
|
+
params: { ... }
|
|
143
|
+
});
|
|
144
|
+
return new Response(instance.id);
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
The sidecar runs the real `WorkflowEntrypoint` class; calls reach it via the `script_name` rewrite in the platform-proxy config. This requires `wrangler >= 4.98.0` ([cloudflare/workers-sdk#13863](https://github.com/cloudflare/workers-sdk/pull/13863)).
|
|
133
149
|
|
|
134
150
|
### Testing the production build locally
|
|
135
151
|
|
|
@@ -191,10 +207,10 @@ The plugin reads your wrangler config, creates a temporary config with `main` po
|
|
|
191
207
|
|
|
192
208
|
### Generating typed bindings
|
|
193
209
|
|
|
194
|
-
The dev plugin creates a temporary `.
|
|
210
|
+
The dev plugin creates a temporary `.types-worker-wrangler.jsonc` with `main` pointing to your source entry point. Use it to generate fully generic Cloudflare types:
|
|
195
211
|
|
|
196
212
|
```bash
|
|
197
|
-
wrangler types --config .
|
|
213
|
+
wrangler types --config .types-worker-wrangler.jsonc
|
|
198
214
|
```
|
|
199
215
|
|
|
200
216
|
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).
|
|
@@ -204,12 +220,12 @@ Add this to your `package.json` scripts for convenience:
|
|
|
204
220
|
```json
|
|
205
221
|
{
|
|
206
222
|
"scripts": {
|
|
207
|
-
"types": "wrangler types --config .
|
|
223
|
+
"types": "wrangler types --config .types-worker-wrangler.jsonc"
|
|
208
224
|
}
|
|
209
225
|
}
|
|
210
226
|
```
|
|
211
227
|
|
|
212
|
-
Note: the `.
|
|
228
|
+
Note: the `.types-worker-wrangler.jsonc` file is generated when the dev server starts. Run `pnpm dev` at least once before running `wrangler types`.
|
|
213
229
|
|
|
214
230
|
## Why this exists
|
|
215
231
|
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
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
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
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);
|
package/dist/index.d.ts
CHANGED
|
@@ -7,9 +7,13 @@
|
|
|
7
7
|
* exports. This plugin post-processes the build output to merge them.
|
|
8
8
|
*
|
|
9
9
|
* **Dev mode:** `getPlatformProxy` (used by adapter-cloudflare in dev) can't
|
|
10
|
-
* run internal Durable Objects. This plugin starts a separate
|
|
11
|
-
* server via `unstable_startWorker` that runs the real
|
|
12
|
-
*
|
|
10
|
+
* run internal Durable Objects or Workflows. This plugin starts a separate
|
|
11
|
+
* wrangler dev server via `unstable_startWorker` that runs the real
|
|
12
|
+
* DO/Workflow worker. Internal DO and Workflow bindings in the platform-proxy
|
|
13
|
+
* config get a `script_name` pointing at that sidecar; miniflare routes calls
|
|
14
|
+
* across the dev registry (cloudflare/workers-sdk#7459, fixed in wrangler
|
|
15
|
+
* 4.98.0). Clients connect directly to the sidecar via WebSocket on a
|
|
16
|
+
* separate port.
|
|
13
17
|
*
|
|
14
18
|
* Usage in vite.config.ts:
|
|
15
19
|
* addWorkerExports({ entryPoint: 'src/lib/server/index.ts' })
|
package/dist/index.js
CHANGED
|
@@ -7,9 +7,13 @@
|
|
|
7
7
|
* exports. This plugin post-processes the build output to merge them.
|
|
8
8
|
*
|
|
9
9
|
* **Dev mode:** `getPlatformProxy` (used by adapter-cloudflare in dev) can't
|
|
10
|
-
* run internal Durable Objects. This plugin starts a separate
|
|
11
|
-
* server via `unstable_startWorker` that runs the real
|
|
12
|
-
*
|
|
10
|
+
* run internal Durable Objects or Workflows. This plugin starts a separate
|
|
11
|
+
* wrangler dev server via `unstable_startWorker` that runs the real
|
|
12
|
+
* DO/Workflow worker. Internal DO and Workflow bindings in the platform-proxy
|
|
13
|
+
* config get a `script_name` pointing at that sidecar; miniflare routes calls
|
|
14
|
+
* across the dev registry (cloudflare/workers-sdk#7459, fixed in wrangler
|
|
15
|
+
* 4.98.0). Clients connect directly to the sidecar via WebSocket on a
|
|
16
|
+
* separate port.
|
|
13
17
|
*
|
|
14
18
|
* Usage in vite.config.ts:
|
|
15
19
|
* addWorkerExports({ entryPoint: 'src/lib/server/index.ts' })
|
|
@@ -23,6 +27,16 @@ import { homedir } from 'node:os';
|
|
|
23
27
|
import { join, resolve } from 'node:path';
|
|
24
28
|
import { parse as parseJsonc } from 'jsonc-parser';
|
|
25
29
|
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
|
+
];
|
|
26
40
|
/**
|
|
27
41
|
* Mirrors wrangler's internal getRegistryPath() — wrangler doesn't export it.
|
|
28
42
|
* Workers register themselves under this path so cross-worker `script_name`
|
|
@@ -77,14 +91,30 @@ function buildPlugin(options) {
|
|
|
77
91
|
if (!(await exists(workerPath))) {
|
|
78
92
|
return;
|
|
79
93
|
}
|
|
80
|
-
// Bundle the named exports
|
|
94
|
+
// Bundle the named exports.
|
|
95
|
+
//
|
|
96
|
+
// `conditions: ['workerd', 'worker', 'browser']` is the Cloudflare-
|
|
97
|
+
// recommended set for bundlers targeting Workers — it picks the
|
|
98
|
+
// workerd-specific or browser-shimmed variants of packages over
|
|
99
|
+
// their Node variants (e.g. nanoid's webcrypto-via-`globalThis.crypto`
|
|
100
|
+
// browser build instead of the `node:crypto`-importing main build).
|
|
101
|
+
//
|
|
102
|
+
// Node built-ins are externalised so transitive deps that do
|
|
103
|
+
// `require('path')` or `import 'node:async_hooks'` survive bundling;
|
|
104
|
+
// the Workers runtime resolves them when `nodejs_compat` is enabled
|
|
105
|
+
// in wrangler.jsonc.
|
|
81
106
|
await build({
|
|
82
107
|
entryPoints: [options.entryPoint],
|
|
83
108
|
bundle: true,
|
|
84
109
|
format: 'esm',
|
|
85
110
|
sourcemap: true,
|
|
86
111
|
target: 'esnext',
|
|
87
|
-
|
|
112
|
+
conditions: ['workerd', 'worker', 'browser'],
|
|
113
|
+
external: [
|
|
114
|
+
'cloudflare:*',
|
|
115
|
+
...NODE_BUILTINS,
|
|
116
|
+
...NODE_BUILTINS.map((m) => `node:${m}`)
|
|
117
|
+
],
|
|
88
118
|
outfile: exportsPath
|
|
89
119
|
});
|
|
90
120
|
// Rename original worker and create merged entry point
|
|
@@ -98,6 +128,12 @@ function devPlugin(options) {
|
|
|
98
128
|
let worker = null;
|
|
99
129
|
let tempConfigPath = null;
|
|
100
130
|
let proxyConfigPath = null;
|
|
131
|
+
let typesConfigPath = null;
|
|
132
|
+
async function readRawConfig() {
|
|
133
|
+
const { unstable_readConfig } = await import('wrangler');
|
|
134
|
+
const parsed = unstable_readConfig(options.wranglerConfig ? { config: options.wranglerConfig } : {});
|
|
135
|
+
return readFile(parsed.configPath, 'utf-8');
|
|
136
|
+
}
|
|
101
137
|
return {
|
|
102
138
|
name: 'add-worker-exports-dev',
|
|
103
139
|
apply: 'serve',
|
|
@@ -109,36 +145,51 @@ function devPlugin(options) {
|
|
|
109
145
|
};
|
|
110
146
|
},
|
|
111
147
|
async configureServer(server) {
|
|
112
|
-
const {
|
|
113
|
-
|
|
114
|
-
const
|
|
148
|
+
const { unstable_startWorker } = await import('wrangler');
|
|
149
|
+
const rawJson = await readRawConfig();
|
|
150
|
+
const sidecarName = `${parseJsonc(rawJson).name ?? 'sveltekit'}-dev-worker`;
|
|
115
151
|
// Copy the raw config and override main, name, and dev port
|
|
116
|
-
const rawJson = await readFile(wranglerConfig.configPath, 'utf-8');
|
|
117
152
|
const devConfig = parseJsonc(rawJson);
|
|
118
|
-
devConfig.name =
|
|
153
|
+
devConfig.name = sidecarName;
|
|
119
154
|
devConfig.main = options.entryPoint;
|
|
120
155
|
devConfig.dev = { ...devConfig.dev, port: devPort };
|
|
121
156
|
delete devConfig.assets;
|
|
122
157
|
tempConfigPath = resolve('.dev-worker-wrangler.jsonc');
|
|
123
158
|
await writeFile(tempConfigPath, JSON.stringify(devConfig, null, '\t'));
|
|
124
|
-
//
|
|
159
|
+
// Write a wrangler config for adapter-cloudflare's getPlatformProxy
|
|
125
160
|
// (used by vite dev for platform.env). It can't run internal DOs or
|
|
126
161
|
// Workflows itself -- those are served by the sidecar above. Rewrite
|
|
127
|
-
// internal DO bindings as cross-worker bindings
|
|
128
|
-
// at the sidecar) so platform.env.MY_DO
|
|
129
|
-
//
|
|
130
|
-
//
|
|
162
|
+
// internal DO and Workflow bindings as cross-worker bindings
|
|
163
|
+
// (script_name pointing at the sidecar) so platform.env.MY_DO and
|
|
164
|
+
// platform.env.MY_WORKFLOW calls in +server.ts reach the sidecar via
|
|
165
|
+
// the wrangler dev registry.
|
|
131
166
|
const proxyConfig = parseJsonc(rawJson);
|
|
132
167
|
if (proxyConfig.durable_objects?.bindings) {
|
|
133
|
-
proxyConfig.durable_objects.bindings = proxyConfig.durable_objects.bindings.map((b) => b.script_name ? b : { ...b, script_name:
|
|
168
|
+
proxyConfig.durable_objects.bindings = proxyConfig.durable_objects.bindings.map((b) => b.script_name ? b : { ...b, script_name: sidecarName });
|
|
169
|
+
}
|
|
170
|
+
if (Array.isArray(proxyConfig.workflows)) {
|
|
171
|
+
proxyConfig.workflows = proxyConfig.workflows.map((w) => w.script_name ? w : { ...w, script_name: sidecarName });
|
|
134
172
|
}
|
|
135
|
-
delete proxyConfig.workflows;
|
|
136
173
|
delete proxyConfig.migrations;
|
|
137
174
|
proxyConfigPath = resolve('.platform-proxy-wrangler.jsonc');
|
|
138
175
|
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'));
|
|
139
187
|
worker = await unstable_startWorker({
|
|
140
188
|
config: tempConfigPath,
|
|
141
|
-
dev: { registry: getWranglerRegistryPath() }
|
|
189
|
+
dev: { registry: getWranglerRegistryPath() },
|
|
190
|
+
build: {
|
|
191
|
+
nodejsCompatMode: (parsedConfig) => getNodejsCompatMode(parsedConfig.compatibility_date, parsedConfig.compatibility_flags)
|
|
192
|
+
}
|
|
142
193
|
});
|
|
143
194
|
server.httpServer?.on('close', async () => {
|
|
144
195
|
if (worker) {
|
|
@@ -151,6 +202,9 @@ function devPlugin(options) {
|
|
|
151
202
|
if (proxyConfigPath) {
|
|
152
203
|
await unlink(proxyConfigPath).catch(() => { });
|
|
153
204
|
}
|
|
205
|
+
if (typesConfigPath) {
|
|
206
|
+
await unlink(typesConfigPath).catch(() => { });
|
|
207
|
+
}
|
|
154
208
|
});
|
|
155
209
|
}
|
|
156
210
|
};
|
|
@@ -164,3 +218,24 @@ async function exists(path) {
|
|
|
164
218
|
return false;
|
|
165
219
|
}
|
|
166
220
|
}
|
|
221
|
+
/**
|
|
222
|
+
* Mirrors miniflare's `getNodeCompat` mode resolution. wrangler's
|
|
223
|
+
* `unstable_startWorker` does not derive this from the config flags
|
|
224
|
+
* automatically — without it, wrangler falls back to the legacy nodejs
|
|
225
|
+
* compat plugin and warns about `node:*` imports even when
|
|
226
|
+
* `nodejs_compat` is enabled.
|
|
227
|
+
*/
|
|
228
|
+
function getNodejsCompatMode(compatibilityDate, compatibilityFlags = []) {
|
|
229
|
+
const hasCompat = compatibilityFlags.includes('nodejs_compat');
|
|
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;
|
|
241
|
+
}
|
package/package.json
CHANGED
|
@@ -1,51 +1,62 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
2
|
+
"name": "@oselvar/sveltekit-add-worker-exports",
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"description": "Vite plugin that adds Durable Object and Workflow exports to SvelteKit Cloudflare workers",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./hooks": {
|
|
15
|
+
"types": "./dist/hooks.d.ts",
|
|
16
|
+
"import": "./dist/hooks.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/oselvar/sveltekit-add-worker-exports.git"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"sveltekit",
|
|
29
|
+
"cloudflare",
|
|
30
|
+
"workers",
|
|
31
|
+
"durable-objects",
|
|
32
|
+
"workflows",
|
|
33
|
+
"vite-plugin"
|
|
34
|
+
],
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@sveltejs/kit": ">=2",
|
|
37
|
+
"esbuild": ">=0.17",
|
|
38
|
+
"miniflare": ">=4",
|
|
39
|
+
"vite": ">=5",
|
|
40
|
+
"wrangler": ">=4"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@release-it/conventional-changelog": "^11.0.1",
|
|
44
|
+
"@sveltejs/kit": "^2.62.0",
|
|
45
|
+
"@types/node": "^25.9.1",
|
|
46
|
+
"esbuild": "^0.28.0",
|
|
47
|
+
"miniflare": "^4.20260601.0",
|
|
48
|
+
"release-it": "^20.2.0",
|
|
49
|
+
"typescript": "^6.0.3",
|
|
50
|
+
"vite": "^8.0.16",
|
|
51
|
+
"wrangler": "^4.98.0"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsc",
|
|
55
|
+
"test": "tsc --noEmit",
|
|
56
|
+
"prepublishOnly": "tsc",
|
|
57
|
+
"release": "release-it"
|
|
58
|
+
},
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"jsonc-parser": "^3.3.1"
|
|
61
|
+
}
|
|
62
|
+
}
|