@oselvar/sveltekit-add-worker-exports 0.1.2 → 0.1.3

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 (2) hide show
  1. package/README.md +88 -9
  2. package/package.json +50 -51
package/README.md CHANGED
@@ -16,26 +16,59 @@ pnpm add -D @oselvar/sveltekit-add-worker-exports
16
16
 
17
17
  ## Usage
18
18
 
19
- Create a file that exports your Durable Object and/or Workflow classes:
19
+ Create a worker entry point that exports your Durable Object classes and a default fetch handler. The fetch handler is only used by the wrangler dev server — in production, SvelteKit's route handlers handle all requests.
20
20
 
21
21
  ```typescript
22
22
  // src/lib/server/index.ts
23
23
  export { MyDurableObject } from './MyDurableObject';
24
+ export { default } from './devHandler';
25
+ ```
26
+
27
+ Both the dev handler and the production SvelteKit route need to do the same thing: validate the upgrade header and forward the request to a Durable Object. Extract that into a small helper so the two callers stay in sync:
28
+
29
+ ```typescript
30
+ // src/lib/server/forwardWebSocket.ts
31
+ export async function forwardWebSocket<T extends Rpc.DurableObjectBranded | undefined>(
32
+ request: Request,
33
+ namespace: DurableObjectNamespace<T>,
34
+ name: string
35
+ ): Promise<Response> {
36
+ if (request.headers.get('upgrade') !== 'websocket') {
37
+ return new Response('Expected WebSocket', { status: 426 });
38
+ }
39
+ const id = namespace.idFromName(name);
40
+ return namespace.get(id).fetch(request);
41
+ }
42
+ ```
43
+
44
+ The dev handler parses the URL and delegates. It's only used by the wrangler dev sidecar:
45
+
46
+ ```typescript
47
+ // src/lib/server/devHandler.ts
48
+ import { forwardWebSocket } from './forwardWebSocket';
24
49
 
25
50
  export default {
26
51
  async fetch(request: Request, env: Env): Promise<Response> {
27
- // Route WebSocket upgrades to Durable Objects (used during dev)
28
- const url = new URL(request.url);
29
- const match = url.pathname.match(/^\/ws\/(.+)$/);
30
- if (match && request.headers.get('Upgrade') === 'websocket') {
31
- const id = env.MY_DO.idFromName(match[1]);
32
- return env.MY_DO.get(id).fetch(request);
33
- }
34
- return new Response('Not found', { status: 404 });
52
+ const match = new URL(request.url).pathname.match(/^\/ws\/(.+)$/);
53
+ if (!match) return new Response('Not found', { status: 404 });
54
+ return forwardWebSocket(request, env.MY_DO, match[1]);
35
55
  }
36
56
  };
37
57
  ```
38
58
 
59
+ In production, the dev handler is *not* used — SvelteKit serves the same path through a `+server.ts` route, which delegates to the same helper:
60
+
61
+ ```typescript
62
+ // src/routes/ws/[id]/+server.ts
63
+ import { forwardWebSocket } from '$lib/server/forwardWebSocket';
64
+ import type { RequestHandler } from './$types';
65
+
66
+ export const GET: RequestHandler = ({ params, request, platform }) =>
67
+ forwardWebSocket(request, platform!.env.MY_DO, params.id);
68
+ ```
69
+
70
+ Now any change to the upgrade-and-forward logic (auth, rate-limiting, response shape) lives in one place and applies to both dev and production.
71
+
39
72
  Add the plugin to your `vite.config.ts` **after** `sveltekit()`:
40
73
 
41
74
  ```typescript
@@ -78,6 +111,29 @@ declare global {
78
111
 
79
112
  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 use your source file instead of the SvelteKit build output.
80
113
 
114
+ ### Testing the production build locally
115
+
116
+ `vite dev` exercises the dev handler via the wrangler-dev sidecar; it does *not* exercise your `+server.ts` route or the merged `_worker.js`. To verify the production wiring (named DO exports + SvelteKit routes in the same worker), run wrangler against the build output:
117
+
118
+ ```bash
119
+ pnpm build # produces .svelte-kit/cloudflare/_worker.js with merged exports
120
+ pnpm wrangler dev # uses wrangler.jsonc → main: .svelte-kit/cloudflare/_worker.js
121
+ ```
122
+
123
+ This serves the exact bundle that gets deployed, with local Durable Object storage. Connect a WebSocket client to `ws://localhost:8787/ws/<id>` and confirm you get a `101 Switching Protocols` response — that proves the request flowed through the SvelteKit `+server.ts` and into your DO.
124
+
125
+ A handy shortcut is to add a `preview` script to `package.json`:
126
+
127
+ ```json
128
+ {
129
+ "scripts": {
130
+ "preview": "wrangler dev"
131
+ }
132
+ }
133
+ ```
134
+
135
+ > 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.
136
+
81
137
  ## Options
82
138
 
83
139
  | Option | Type | Required | Default | Description |
@@ -111,6 +167,29 @@ The plugin reads your wrangler config, creates a temporary config with `main` po
111
167
  - Real workerd runtime (not emulated)
112
168
  - Hot-reload when you change DO code
113
169
  - Same WebSocket protocol as production
170
+ - Fully typed Durable Object bindings (see below)
171
+
172
+ ### Generating typed bindings
173
+
174
+ The dev plugin creates a temporary `.dev-worker-wrangler.jsonc` with `main` pointing to your source entry point. You can use this to generate fully generic Cloudflare types:
175
+
176
+ ```bash
177
+ wrangler types --config .dev-worker-wrangler.jsonc
178
+ ```
179
+
180
+ 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).
181
+
182
+ Add this to your `package.json` scripts for convenience:
183
+
184
+ ```json
185
+ {
186
+ "scripts": {
187
+ "types": "wrangler types --config .dev-worker-wrangler.jsonc"
188
+ }
189
+ }
190
+ ```
191
+
192
+ Note: the `.dev-worker-wrangler.jsonc` file is generated when the dev server starts. Run `pnpm dev` at least once before running `wrangler types`.
114
193
 
115
194
  ## Why this exists
116
195
 
package/package.json CHANGED
@@ -1,52 +1,51 @@
1
1
  {
2
- "name": "@oselvar/sveltekit-add-worker-exports",
3
- "version": "0.1.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
- },
15
- "files": [
16
- "dist"
17
- ],
18
- "license": "MIT",
19
- "repository": {
20
- "type": "git",
21
- "url": "https://github.com/oselvar/sveltekit-add-worker-exports"
22
- },
23
- "keywords": [
24
- "sveltekit",
25
- "cloudflare",
26
- "workers",
27
- "durable-objects",
28
- "workflows",
29
- "vite-plugin"
30
- ],
31
- "peerDependencies": {
32
- "esbuild": ">=0.17",
33
- "vite": ">=5",
34
- "wrangler": ">=4"
35
- },
36
- "devDependencies": {
37
- "@types/node": "^22.0.0",
38
- "esbuild": "^0.25.0",
39
- "np": "^11.2.0",
40
- "typescript": "^5.0.0",
41
- "vite": "^6.0.0",
42
- "wrangler": "^4.84.0"
43
- },
44
- "scripts": {
45
- "build": "tsc",
46
- "test": "tsc --noEmit",
47
- "prepublishOnly": "tsc"
48
- },
49
- "dependencies": {
50
- "jsonc-parser": "^3.3.1"
51
- }
52
- }
2
+ "name": "@oselvar/sveltekit-add-worker-exports",
3
+ "version": "0.1.3",
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
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "license": "MIT",
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "git+https://github.com/oselvar/sveltekit-add-worker-exports.git"
22
+ },
23
+ "keywords": [
24
+ "sveltekit",
25
+ "cloudflare",
26
+ "workers",
27
+ "durable-objects",
28
+ "workflows",
29
+ "vite-plugin"
30
+ ],
31
+ "peerDependencies": {
32
+ "esbuild": ">=0.17",
33
+ "vite": ">=5",
34
+ "wrangler": ">=4"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^22.0.0",
38
+ "esbuild": "^0.25.0",
39
+ "np": "^11.2.0",
40
+ "typescript": "^5.0.0",
41
+ "vite": "^6.0.0",
42
+ "wrangler": "^4.84.0"
43
+ },
44
+ "dependencies": {
45
+ "jsonc-parser": "^3.3.1"
46
+ },
47
+ "scripts": {
48
+ "build": "tsc",
49
+ "test": "tsc --noEmit"
50
+ }
51
+ }