@pluv/platform-cloudflare 0.17.3 → 0.19.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/.turbo/turbo-build.log +15 -15
- package/CHANGELOG.md +111 -0
- package/README.md +5 -4
- package/dist/index.d.mts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +12 -24
- package/dist/index.mjs +13 -27
- package/package.json +8 -8
- package/src/CloudflarePlatform.ts +6 -7
- package/src/CloudflareWebSocket.ts +3 -13
- package/src/createPluvHandler.ts +31 -80
- package/src/platformCloudflare.ts +1 -3
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
|
|
2
|
-
> @pluv/platform-cloudflare@0.
|
|
2
|
+
> @pluv/platform-cloudflare@0.19.0 build /home/runner/work/pluv/pluv/packages/platform-cloudflare
|
|
3
3
|
> tsup src/index.ts --format esm,cjs --dts
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
5
|
+
CLI Building entry: src/index.ts
|
|
6
|
+
CLI Using tsconfig: tsconfig.json
|
|
7
|
+
CLI tsup v8.1.0
|
|
8
|
+
CLI Target: es6
|
|
9
|
+
ESM Build start
|
|
10
|
+
CJS Build start
|
|
11
|
+
CJS dist/index.js 6.86 KB
|
|
12
|
+
CJS ⚡️ Build success in 91ms
|
|
13
|
+
ESM dist/index.mjs 5.73 KB
|
|
14
|
+
ESM ⚡️ Build success in 92ms
|
|
15
|
+
DTS Build start
|
|
16
|
+
DTS ⚡️ Build success in 2530ms
|
|
17
|
+
DTS dist/index.d.mts 3.02 KB
|
|
18
|
+
DTS dist/index.d.ts 3.02 KB
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,116 @@
|
|
|
1
1
|
# @pluv/platform-cloudflare
|
|
2
2
|
|
|
3
|
+
## 0.19.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @pluv/io@0.19.0
|
|
8
|
+
- @pluv/types@0.19.0
|
|
9
|
+
|
|
10
|
+
## 0.18.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- 99b5ca9: ## Breaking Changes
|
|
15
|
+
|
|
16
|
+
- `@pluv/io` has been updated to introduce `PluvProcedure`, `PluvRouter` and `PluvServer`. This change is intended to improve the ergonomics of declaring events and simplifying inferences of event types.
|
|
17
|
+
|
|
18
|
+
### Before:
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
// backend/io.ts
|
|
22
|
+
|
|
23
|
+
import { createIO } from "@pluv/io";
|
|
24
|
+
import { createPluvHandler, platformNode } from "@pluv/platform-node";
|
|
25
|
+
import { z } from "zod";
|
|
26
|
+
|
|
27
|
+
export const io = createIO({
|
|
28
|
+
platform: platformNode(),
|
|
29
|
+
})
|
|
30
|
+
.event("SEND_MESSAGE", {
|
|
31
|
+
input: z.object({ message: z.string() }),
|
|
32
|
+
resolver: ({ message }) => ({ RECEIVE_MESSAGE: { message } }),
|
|
33
|
+
})
|
|
34
|
+
.event("DOUBLE_VALUE", {
|
|
35
|
+
input: z.object({ value: z.number() }),
|
|
36
|
+
resolver: ({ value }) => ({ VALUE_DOUBLED: { value: value * 2 } }),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const Pluv = createPluvHandler({
|
|
40
|
+
io,
|
|
41
|
+
/* ... */
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// frontend/pluv.ts
|
|
47
|
+
|
|
48
|
+
import { createClient } from "@pluv/react";
|
|
49
|
+
import type { io } from "../backend/io";
|
|
50
|
+
|
|
51
|
+
const client = createClient<typeof io>({
|
|
52
|
+
/* ... */
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Now:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { createIO } from "@pluv/io";
|
|
60
|
+
import { createPluvHandler, platformNode } from "@pluv/platform-node";
|
|
61
|
+
import { z } from "zod";
|
|
62
|
+
|
|
63
|
+
const io = createIO({
|
|
64
|
+
platform: platformNode(),
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const router = io.router({
|
|
68
|
+
SEND_MESSAGE: io.procedure
|
|
69
|
+
.input(z.object({ message: z.string() }))
|
|
70
|
+
.broadcast(({ message }) => ({
|
|
71
|
+
RECEIVE_MESSAGE: { message },
|
|
72
|
+
})),
|
|
73
|
+
DOUBLE_VALUE: io.procedure
|
|
74
|
+
.input(z.object({ value: z.number() }))
|
|
75
|
+
.broadcast(({ value }) => ({
|
|
76
|
+
VALUE_DOUBLED: { value: value * 2 },
|
|
77
|
+
})),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
export const ioServer = io.server({ router });
|
|
81
|
+
|
|
82
|
+
const Pluv = createPluvHandler({
|
|
83
|
+
io: ioServer, // <- This uses the PluvServer now
|
|
84
|
+
/* ... */
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
// frontend/pluv.ts
|
|
90
|
+
|
|
91
|
+
import { createClient } from "@pluv/react";
|
|
92
|
+
import type { ioServer } from "../backend/io";
|
|
93
|
+
|
|
94
|
+
// This users the PluvServer type now
|
|
95
|
+
const client = createClient<typeof ioServer>({
|
|
96
|
+
/* ... */
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
- `PluvRouter` instances can also be merged via the `mergeRouters` method, which effectively performs an `Object.assign` of the events object and returns a new `PluvRouter` with the correct types:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const router = io.mergeRouters(router1, router2);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Patch Changes
|
|
107
|
+
|
|
108
|
+
- Updated dependencies [428c21c]
|
|
109
|
+
- Updated dependencies [329dbcd]
|
|
110
|
+
- Updated dependencies [99b5ca9]
|
|
111
|
+
- @pluv/io@0.18.0
|
|
112
|
+
- @pluv/types@0.18.0
|
|
113
|
+
|
|
3
114
|
## 0.17.3
|
|
4
115
|
|
|
5
116
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -50,14 +50,15 @@ pnpm add @pluv/platform-cloudflare
|
|
|
50
50
|
import { createIO } from "@pluv/io";
|
|
51
51
|
import { platformCloudflare } from "@pluv/platform-cloudflare";
|
|
52
52
|
|
|
53
|
-
export const io = createIO({
|
|
54
|
-
|
|
55
|
-
});
|
|
53
|
+
export const io = createIO({ platform: platformCloudflare() });
|
|
54
|
+
export const ioServer = io.server();
|
|
56
55
|
|
|
57
56
|
/* Somewhere in a Cloudflare worker durable object */
|
|
58
57
|
const { 0: client, 1: server } = new WebSocketPair();
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
const room = ioServer.getRoom(state.id.toString(), { env });
|
|
60
|
+
|
|
61
|
+
await room.register(server);
|
|
61
62
|
|
|
62
63
|
return new Response(null, { status: 101, webSocket: client });
|
|
63
64
|
```
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbstractWebSocket, AbstractEventMap, AbstractListener, AbstractWebSocketConfig, AbstractPlatform, ConvertWebSocketConfig,
|
|
1
|
+
import { AbstractWebSocket, AbstractEventMap, AbstractListener, AbstractWebSocketConfig, AbstractPlatform, ConvertWebSocketConfig, PluvServer } from '@pluv/io';
|
|
2
2
|
import { MaybePromise, Maybe, InferIOAuthorizeUser, InferIOAuthorize, InferIOAuthorizeRequired, Id } from '@pluv/types';
|
|
3
3
|
|
|
4
4
|
type CloudflareWebSocketConfig = AbstractWebSocketConfig;
|
|
@@ -27,14 +27,14 @@ interface AuthorizeFunctionContext {
|
|
|
27
27
|
request: Request<any, CfProperties<any>>;
|
|
28
28
|
roomId: string;
|
|
29
29
|
}
|
|
30
|
-
type AuthorizeFunction<
|
|
31
|
-
type CreatePluvHandlerConfig<
|
|
30
|
+
type AuthorizeFunction<TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>> = (ctx: AuthorizeFunctionContext) => MaybePromise<Maybe<InferIOAuthorizeUser<InferIOAuthorize<TPluvServer>>>>;
|
|
31
|
+
type CreatePluvHandlerConfig<TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>, TEnv extends Record<string, any>> = {
|
|
32
32
|
binding: string;
|
|
33
33
|
endpoint?: string;
|
|
34
34
|
modify?: (request: Request, response: Response, env: TEnv) => MaybePromise<Response>;
|
|
35
|
-
io:
|
|
36
|
-
} & (InferIOAuthorizeRequired<InferIOAuthorize<
|
|
37
|
-
authorize: AuthorizeFunction<
|
|
35
|
+
io: TPluvServer;
|
|
36
|
+
} & (InferIOAuthorizeRequired<InferIOAuthorize<TPluvServer>> extends true ? {
|
|
37
|
+
authorize: AuthorizeFunction<TPluvServer>;
|
|
38
38
|
} : {
|
|
39
39
|
authorize?: undefined;
|
|
40
40
|
});
|
|
@@ -46,8 +46,8 @@ interface CreatePluvHandlerResult<TEnv extends Record<string, any> = {}> {
|
|
|
46
46
|
fetch: PluvHandlerFetch<TEnv>;
|
|
47
47
|
handler: ExportedHandler<TEnv>;
|
|
48
48
|
}
|
|
49
|
-
type InferCloudflarePluvHandlerEnv<
|
|
50
|
-
declare const createPluvHandler: <
|
|
49
|
+
type InferCloudflarePluvHandlerEnv<TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>> = TPluvServer extends PluvServer<CloudflarePlatform<infer IEnv>, any, any, any> ? IEnv : {};
|
|
50
|
+
declare const createPluvHandler: <TPluvServer extends PluvServer<CloudflarePlatform<{}>, any, any, any>>(config: CreatePluvHandlerConfig<TPluvServer, Id<InferCloudflarePluvHandlerEnv<TPluvServer>>>) => CreatePluvHandlerResult<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>>;
|
|
51
51
|
|
|
52
52
|
declare const platformCloudflare: <TEnv extends Record<string, any> = {}>() => CloudflarePlatform<TEnv>;
|
|
53
53
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AbstractWebSocket, AbstractEventMap, AbstractListener, AbstractWebSocketConfig, AbstractPlatform, ConvertWebSocketConfig,
|
|
1
|
+
import { AbstractWebSocket, AbstractEventMap, AbstractListener, AbstractWebSocketConfig, AbstractPlatform, ConvertWebSocketConfig, PluvServer } from '@pluv/io';
|
|
2
2
|
import { MaybePromise, Maybe, InferIOAuthorizeUser, InferIOAuthorize, InferIOAuthorizeRequired, Id } from '@pluv/types';
|
|
3
3
|
|
|
4
4
|
type CloudflareWebSocketConfig = AbstractWebSocketConfig;
|
|
@@ -27,14 +27,14 @@ interface AuthorizeFunctionContext {
|
|
|
27
27
|
request: Request<any, CfProperties<any>>;
|
|
28
28
|
roomId: string;
|
|
29
29
|
}
|
|
30
|
-
type AuthorizeFunction<
|
|
31
|
-
type CreatePluvHandlerConfig<
|
|
30
|
+
type AuthorizeFunction<TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>> = (ctx: AuthorizeFunctionContext) => MaybePromise<Maybe<InferIOAuthorizeUser<InferIOAuthorize<TPluvServer>>>>;
|
|
31
|
+
type CreatePluvHandlerConfig<TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>, TEnv extends Record<string, any>> = {
|
|
32
32
|
binding: string;
|
|
33
33
|
endpoint?: string;
|
|
34
34
|
modify?: (request: Request, response: Response, env: TEnv) => MaybePromise<Response>;
|
|
35
|
-
io:
|
|
36
|
-
} & (InferIOAuthorizeRequired<InferIOAuthorize<
|
|
37
|
-
authorize: AuthorizeFunction<
|
|
35
|
+
io: TPluvServer;
|
|
36
|
+
} & (InferIOAuthorizeRequired<InferIOAuthorize<TPluvServer>> extends true ? {
|
|
37
|
+
authorize: AuthorizeFunction<TPluvServer>;
|
|
38
38
|
} : {
|
|
39
39
|
authorize?: undefined;
|
|
40
40
|
});
|
|
@@ -46,8 +46,8 @@ interface CreatePluvHandlerResult<TEnv extends Record<string, any> = {}> {
|
|
|
46
46
|
fetch: PluvHandlerFetch<TEnv>;
|
|
47
47
|
handler: ExportedHandler<TEnv>;
|
|
48
48
|
}
|
|
49
|
-
type InferCloudflarePluvHandlerEnv<
|
|
50
|
-
declare const createPluvHandler: <
|
|
49
|
+
type InferCloudflarePluvHandlerEnv<TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>> = TPluvServer extends PluvServer<CloudflarePlatform<infer IEnv>, any, any, any> ? IEnv : {};
|
|
50
|
+
declare const createPluvHandler: <TPluvServer extends PluvServer<CloudflarePlatform<{}>, any, any, any>>(config: CreatePluvHandlerConfig<TPluvServer, Id<InferCloudflarePluvHandlerEnv<TPluvServer>>>) => CreatePluvHandlerResult<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>>;
|
|
51
51
|
|
|
52
52
|
declare const platformCloudflare: <TEnv extends Record<string, any> = {}>() => CloudflarePlatform<TEnv>;
|
|
53
53
|
|
package/dist/index.js
CHANGED
|
@@ -85,13 +85,11 @@ var createPluvHandler = (config) => {
|
|
|
85
85
|
return namespace;
|
|
86
86
|
};
|
|
87
87
|
const authHandler = (request, env) => __async(void 0, null, function* () {
|
|
88
|
-
if (!authorize)
|
|
89
|
-
return null;
|
|
88
|
+
if (!authorize) return null;
|
|
90
89
|
const { pathname, searchParams } = new URL(request.url);
|
|
91
90
|
const matcher = (0, import_path_to_regexp.match)(`${endpoint}/authorize`);
|
|
92
91
|
const matched = matcher(pathname);
|
|
93
|
-
if (!matched)
|
|
94
|
-
return null;
|
|
92
|
+
if (!matched) return null;
|
|
95
93
|
const roomId = searchParams.get("room");
|
|
96
94
|
if (!roomId) {
|
|
97
95
|
return new Response("Not found", {
|
|
@@ -101,8 +99,7 @@ var createPluvHandler = (config) => {
|
|
|
101
99
|
}
|
|
102
100
|
try {
|
|
103
101
|
const user = yield authorize({ request, roomId });
|
|
104
|
-
if (!user)
|
|
105
|
-
throw new Error();
|
|
102
|
+
if (!user) throw new Error();
|
|
106
103
|
const namespace = getDurableObjectNamespace(env);
|
|
107
104
|
const durableObjectId = namespace.idFromName(roomId);
|
|
108
105
|
const token = yield io.createToken({
|
|
@@ -115,21 +112,17 @@ var createPluvHandler = (config) => {
|
|
|
115
112
|
status: 200
|
|
116
113
|
});
|
|
117
114
|
} catch (err) {
|
|
118
|
-
return new Response(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
status: 403
|
|
123
|
-
}
|
|
124
|
-
);
|
|
115
|
+
return new Response(err instanceof Error ? err.message : "Unauthorized", {
|
|
116
|
+
headers: { "Content-Type": "text/plain" },
|
|
117
|
+
status: 403
|
|
118
|
+
});
|
|
125
119
|
}
|
|
126
120
|
});
|
|
127
121
|
const roomHandler = (request, env) => __async(void 0, null, function* () {
|
|
128
122
|
const { pathname } = new URL(request.url);
|
|
129
123
|
const matcher = (0, import_path_to_regexp.match)(`${endpoint}/room/:roomId`);
|
|
130
124
|
const matched = matcher(pathname);
|
|
131
|
-
if (!matched)
|
|
132
|
-
return null;
|
|
125
|
+
if (!matched) return null;
|
|
133
126
|
const { roomId } = matched.params;
|
|
134
127
|
if (!roomId) {
|
|
135
128
|
return new Response("Not found", {
|
|
@@ -178,11 +171,8 @@ var CloudflareWebSocket = class extends import_io.AbstractWebSocket {
|
|
|
178
171
|
this.webSocket.addEventListener(type, handler);
|
|
179
172
|
}
|
|
180
173
|
close(code, reason) {
|
|
181
|
-
const canClose = [this.CONNECTING, this.OPEN].some(
|
|
182
|
-
|
|
183
|
-
);
|
|
184
|
-
if (!canClose)
|
|
185
|
-
return;
|
|
174
|
+
const canClose = [this.CONNECTING, this.OPEN].some((readyState) => readyState === this.readyState);
|
|
175
|
+
if (!canClose) return;
|
|
186
176
|
this.webSocket.close(code, reason);
|
|
187
177
|
}
|
|
188
178
|
initialize() {
|
|
@@ -190,8 +180,7 @@ var CloudflareWebSocket = class extends import_io.AbstractWebSocket {
|
|
|
190
180
|
return Promise.resolve(() => void 0);
|
|
191
181
|
}
|
|
192
182
|
send(message) {
|
|
193
|
-
if (this.readyState !== this.OPEN)
|
|
194
|
-
return;
|
|
183
|
+
if (this.readyState !== this.OPEN) return;
|
|
195
184
|
this.webSocket.send(message);
|
|
196
185
|
}
|
|
197
186
|
terminate() {
|
|
@@ -205,8 +194,7 @@ var CloudflarePlatform = class extends import_io2.AbstractPlatform {
|
|
|
205
194
|
return new CloudflareWebSocket(webSocket, config);
|
|
206
195
|
}
|
|
207
196
|
parseData(data) {
|
|
208
|
-
if (typeof data === "string")
|
|
209
|
-
return JSON.parse(data);
|
|
197
|
+
if (typeof data === "string") return JSON.parse(data);
|
|
210
198
|
const decoder = new TextDecoder("utf8");
|
|
211
199
|
return JSON.parse(decoder.decode(data));
|
|
212
200
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -59,13 +59,11 @@ var createPluvHandler = (config) => {
|
|
|
59
59
|
return namespace;
|
|
60
60
|
};
|
|
61
61
|
const authHandler = (request, env) => __async(void 0, null, function* () {
|
|
62
|
-
if (!authorize)
|
|
63
|
-
return null;
|
|
62
|
+
if (!authorize) return null;
|
|
64
63
|
const { pathname, searchParams } = new URL(request.url);
|
|
65
64
|
const matcher = match(`${endpoint}/authorize`);
|
|
66
65
|
const matched = matcher(pathname);
|
|
67
|
-
if (!matched)
|
|
68
|
-
return null;
|
|
66
|
+
if (!matched) return null;
|
|
69
67
|
const roomId = searchParams.get("room");
|
|
70
68
|
if (!roomId) {
|
|
71
69
|
return new Response("Not found", {
|
|
@@ -75,8 +73,7 @@ var createPluvHandler = (config) => {
|
|
|
75
73
|
}
|
|
76
74
|
try {
|
|
77
75
|
const user = yield authorize({ request, roomId });
|
|
78
|
-
if (!user)
|
|
79
|
-
throw new Error();
|
|
76
|
+
if (!user) throw new Error();
|
|
80
77
|
const namespace = getDurableObjectNamespace(env);
|
|
81
78
|
const durableObjectId = namespace.idFromName(roomId);
|
|
82
79
|
const token = yield io.createToken({
|
|
@@ -89,21 +86,17 @@ var createPluvHandler = (config) => {
|
|
|
89
86
|
status: 200
|
|
90
87
|
});
|
|
91
88
|
} catch (err) {
|
|
92
|
-
return new Response(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
status: 403
|
|
97
|
-
}
|
|
98
|
-
);
|
|
89
|
+
return new Response(err instanceof Error ? err.message : "Unauthorized", {
|
|
90
|
+
headers: { "Content-Type": "text/plain" },
|
|
91
|
+
status: 403
|
|
92
|
+
});
|
|
99
93
|
}
|
|
100
94
|
});
|
|
101
95
|
const roomHandler = (request, env) => __async(void 0, null, function* () {
|
|
102
96
|
const { pathname } = new URL(request.url);
|
|
103
97
|
const matcher = match(`${endpoint}/room/:roomId`);
|
|
104
98
|
const matched = matcher(pathname);
|
|
105
|
-
if (!matched)
|
|
106
|
-
return null;
|
|
99
|
+
if (!matched) return null;
|
|
107
100
|
const { roomId } = matched.params;
|
|
108
101
|
if (!roomId) {
|
|
109
102
|
return new Response("Not found", {
|
|
@@ -138,9 +131,7 @@ var createPluvHandler = (config) => {
|
|
|
138
131
|
import { AbstractPlatform } from "@pluv/io";
|
|
139
132
|
|
|
140
133
|
// src/CloudflareWebSocket.ts
|
|
141
|
-
import {
|
|
142
|
-
AbstractWebSocket
|
|
143
|
-
} from "@pluv/io";
|
|
134
|
+
import { AbstractWebSocket } from "@pluv/io";
|
|
144
135
|
var CloudflareWebSocket = class extends AbstractWebSocket {
|
|
145
136
|
get readyState() {
|
|
146
137
|
return this.webSocket.readyState;
|
|
@@ -154,11 +145,8 @@ var CloudflareWebSocket = class extends AbstractWebSocket {
|
|
|
154
145
|
this.webSocket.addEventListener(type, handler);
|
|
155
146
|
}
|
|
156
147
|
close(code, reason) {
|
|
157
|
-
const canClose = [this.CONNECTING, this.OPEN].some(
|
|
158
|
-
|
|
159
|
-
);
|
|
160
|
-
if (!canClose)
|
|
161
|
-
return;
|
|
148
|
+
const canClose = [this.CONNECTING, this.OPEN].some((readyState) => readyState === this.readyState);
|
|
149
|
+
if (!canClose) return;
|
|
162
150
|
this.webSocket.close(code, reason);
|
|
163
151
|
}
|
|
164
152
|
initialize() {
|
|
@@ -166,8 +154,7 @@ var CloudflareWebSocket = class extends AbstractWebSocket {
|
|
|
166
154
|
return Promise.resolve(() => void 0);
|
|
167
155
|
}
|
|
168
156
|
send(message) {
|
|
169
|
-
if (this.readyState !== this.OPEN)
|
|
170
|
-
return;
|
|
157
|
+
if (this.readyState !== this.OPEN) return;
|
|
171
158
|
this.webSocket.send(message);
|
|
172
159
|
}
|
|
173
160
|
terminate() {
|
|
@@ -181,8 +168,7 @@ var CloudflarePlatform = class extends AbstractPlatform {
|
|
|
181
168
|
return new CloudflareWebSocket(webSocket, config);
|
|
182
169
|
}
|
|
183
170
|
parseData(data) {
|
|
184
|
-
if (typeof data === "string")
|
|
185
|
-
return JSON.parse(data);
|
|
171
|
+
if (typeof data === "string") return JSON.parse(data);
|
|
186
172
|
const decoder = new TextDecoder("utf8");
|
|
187
173
|
return JSON.parse(decoder.decode(data));
|
|
188
174
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/platform-cloudflare",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"description": "@pluv/io adapter for cloudflare workers",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,17 +17,17 @@
|
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"path-to-regexp": "^
|
|
21
|
-
"@pluv/io": "^0.
|
|
22
|
-
"@pluv/types": "^0.
|
|
20
|
+
"path-to-regexp": "^7.0.0",
|
|
21
|
+
"@pluv/io": "^0.19.0",
|
|
22
|
+
"@pluv/types": "^0.19.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@cloudflare/workers-types": "^4.
|
|
25
|
+
"@cloudflare/workers-types": "^4.20240620.0",
|
|
26
26
|
"eslint": "^8.57.0",
|
|
27
|
-
"tsup": "^8.0
|
|
27
|
+
"tsup": "^8.1.0",
|
|
28
28
|
"typescript": "^5.4.5",
|
|
29
|
-
"@pluv/tsconfig": "^0.
|
|
30
|
-
"eslint-config-pluv": "^0.
|
|
29
|
+
"@pluv/tsconfig": "^0.19.0",
|
|
30
|
+
"eslint-config-pluv": "^0.19.0"
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
@@ -2,13 +2,12 @@ import type { ConvertWebSocketConfig } from "@pluv/io";
|
|
|
2
2
|
import { AbstractPlatform } from "@pluv/io";
|
|
3
3
|
import { CloudflareWebSocket } from "./CloudflareWebSocket";
|
|
4
4
|
|
|
5
|
-
export class CloudflarePlatform<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
): CloudflareWebSocket {
|
|
5
|
+
export class CloudflarePlatform<TEnv extends Record<string, any> = {}> extends AbstractPlatform<
|
|
6
|
+
WebSocket,
|
|
7
|
+
{ env: TEnv },
|
|
8
|
+
{ request: Request }
|
|
9
|
+
> {
|
|
10
|
+
public convertWebSocket(webSocket: WebSocket, config: ConvertWebSocketConfig): CloudflareWebSocket {
|
|
12
11
|
return new CloudflareWebSocket(webSocket, config);
|
|
13
12
|
}
|
|
14
13
|
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AbstractEventMap,
|
|
3
|
-
AbstractListener,
|
|
4
|
-
AbstractWebSocket,
|
|
5
|
-
AbstractWebSocketConfig,
|
|
6
|
-
} from "@pluv/io";
|
|
1
|
+
import { AbstractEventMap, AbstractListener, AbstractWebSocket, AbstractWebSocketConfig } from "@pluv/io";
|
|
7
2
|
|
|
8
3
|
export interface CloudflareWebSocketEventMap {
|
|
9
4
|
close: CloseEvent;
|
|
@@ -29,17 +24,12 @@ export class CloudflareWebSocket extends AbstractWebSocket {
|
|
|
29
24
|
this.webSocket = webSocket;
|
|
30
25
|
}
|
|
31
26
|
|
|
32
|
-
public addEventListener<TType extends keyof AbstractEventMap>(
|
|
33
|
-
type: TType,
|
|
34
|
-
handler: AbstractListener<TType>,
|
|
35
|
-
) {
|
|
27
|
+
public addEventListener<TType extends keyof AbstractEventMap>(type: TType, handler: AbstractListener<TType>) {
|
|
36
28
|
this.webSocket.addEventListener(type, handler as any);
|
|
37
29
|
}
|
|
38
30
|
|
|
39
31
|
public close(code?: number | undefined, reason?: string | undefined): void {
|
|
40
|
-
const canClose = [this.CONNECTING, this.OPEN].some(
|
|
41
|
-
(readyState) => readyState === this.readyState,
|
|
42
|
-
);
|
|
32
|
+
const canClose = [this.CONNECTING, this.OPEN].some((readyState) => readyState === this.readyState);
|
|
43
33
|
|
|
44
34
|
if (!canClose) return;
|
|
45
35
|
|
package/src/createPluvHandler.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { IORoom,
|
|
2
|
-
import {
|
|
1
|
+
import type { IORoom, PluvServer } from "@pluv/io";
|
|
2
|
+
import type {
|
|
3
3
|
Id,
|
|
4
4
|
InferIOAuthorize,
|
|
5
5
|
InferIOAuthorizeRequired,
|
|
@@ -14,24 +14,20 @@ export interface AuthorizeFunctionContext {
|
|
|
14
14
|
request: Request<any, CfProperties<any>>;
|
|
15
15
|
roomId: string;
|
|
16
16
|
}
|
|
17
|
-
export type AuthorizeFunction<
|
|
17
|
+
export type AuthorizeFunction<TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>> = (
|
|
18
18
|
ctx: AuthorizeFunctionContext,
|
|
19
|
-
) => MaybePromise<Maybe<InferIOAuthorizeUser<InferIOAuthorize<
|
|
19
|
+
) => MaybePromise<Maybe<InferIOAuthorizeUser<InferIOAuthorize<TPluvServer>>>>;
|
|
20
20
|
|
|
21
21
|
export type CreatePluvHandlerConfig<
|
|
22
|
-
|
|
22
|
+
TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>,
|
|
23
23
|
TEnv extends Record<string, any>,
|
|
24
24
|
> = {
|
|
25
25
|
binding: string;
|
|
26
26
|
endpoint?: string;
|
|
27
|
-
modify?: (
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
) => MaybePromise<Response>;
|
|
32
|
-
io: TPluv;
|
|
33
|
-
} & (InferIOAuthorizeRequired<InferIOAuthorize<TPluv>> extends true
|
|
34
|
-
? { authorize: AuthorizeFunction<TPluv> }
|
|
27
|
+
modify?: (request: Request, response: Response, env: TEnv) => MaybePromise<Response>;
|
|
28
|
+
io: TPluvServer;
|
|
29
|
+
} & (InferIOAuthorizeRequired<InferIOAuthorize<TPluvServer>> extends true
|
|
30
|
+
? { authorize: AuthorizeFunction<TPluvServer> }
|
|
35
31
|
: { authorize?: undefined });
|
|
36
32
|
|
|
37
33
|
export type PluvHandlerFetch<TEnv extends Record<string, any> = {}> = (
|
|
@@ -39,9 +35,7 @@ export type PluvHandlerFetch<TEnv extends Record<string, any> = {}> = (
|
|
|
39
35
|
env: TEnv,
|
|
40
36
|
) => Promise<Response | null>;
|
|
41
37
|
|
|
42
|
-
export interface CreatePluvHandlerResult<
|
|
43
|
-
TEnv extends Record<string, any> = {},
|
|
44
|
-
> {
|
|
38
|
+
export interface CreatePluvHandlerResult<TEnv extends Record<string, any> = {}> {
|
|
45
39
|
DurableObject: {
|
|
46
40
|
new (state: DurableObjectState, env: TEnv): DurableObject;
|
|
47
41
|
};
|
|
@@ -49,60 +43,30 @@ export interface CreatePluvHandlerResult<
|
|
|
49
43
|
handler: ExportedHandler<TEnv>;
|
|
50
44
|
}
|
|
51
45
|
|
|
52
|
-
type InferCloudflarePluvHandlerEnv<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
any,
|
|
59
|
-
any,
|
|
60
|
-
any,
|
|
61
|
-
any,
|
|
62
|
-
any
|
|
63
|
-
>
|
|
64
|
-
? IEnv
|
|
65
|
-
: {};
|
|
66
|
-
|
|
67
|
-
export const createPluvHandler = <
|
|
68
|
-
TPluv extends PluvIO<CloudflarePlatform, any, any, any, any, any, any>,
|
|
69
|
-
>(
|
|
70
|
-
config: CreatePluvHandlerConfig<
|
|
71
|
-
TPluv,
|
|
72
|
-
Id<InferCloudflarePluvHandlerEnv<TPluv>>
|
|
73
|
-
>,
|
|
74
|
-
): CreatePluvHandlerResult<Id<InferCloudflarePluvHandlerEnv<TPluv>>> => {
|
|
46
|
+
type InferCloudflarePluvHandlerEnv<TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>> =
|
|
47
|
+
TPluvServer extends PluvServer<CloudflarePlatform<infer IEnv>, any, any, any> ? IEnv : {};
|
|
48
|
+
|
|
49
|
+
export const createPluvHandler = <TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>>(
|
|
50
|
+
config: CreatePluvHandlerConfig<TPluvServer, Id<InferCloudflarePluvHandlerEnv<TPluvServer>>>,
|
|
51
|
+
): CreatePluvHandlerResult<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> => {
|
|
75
52
|
const { authorize, binding, endpoint = "/api/pluv", modify, io } = config;
|
|
76
53
|
|
|
77
54
|
const DurableObject = class implements DurableObject {
|
|
78
|
-
private _env: Id<InferCloudflarePluvHandlerEnv<
|
|
55
|
+
private _env: Id<InferCloudflarePluvHandlerEnv<TPluvServer>>;
|
|
79
56
|
private _io: IORoom<CloudflarePlatform>;
|
|
80
57
|
|
|
81
|
-
constructor(
|
|
82
|
-
state: DurableObjectState,
|
|
83
|
-
env: Id<InferCloudflarePluvHandlerEnv<TPluv>>,
|
|
84
|
-
) {
|
|
58
|
+
constructor(state: DurableObjectState, env: Id<InferCloudflarePluvHandlerEnv<TPluvServer>>) {
|
|
85
59
|
this._env = env;
|
|
86
60
|
this._io = io.getRoom(state.id.toString(), { env });
|
|
87
61
|
}
|
|
88
62
|
|
|
89
|
-
webSocketClose(
|
|
90
|
-
ws: WebSocket,
|
|
91
|
-
code: number,
|
|
92
|
-
reason: string,
|
|
93
|
-
wasClean: boolean,
|
|
94
|
-
): void | Promise<void> {}
|
|
63
|
+
webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean): void | Promise<void> {}
|
|
95
64
|
|
|
96
65
|
webSocketError(ws: WebSocket, error: unknown): void | Promise<void> {}
|
|
97
66
|
|
|
98
|
-
webSocketMessage(
|
|
99
|
-
ws: WebSocket,
|
|
100
|
-
message: string | ArrayBuffer,
|
|
101
|
-
): void | Promise<void> {}
|
|
67
|
+
webSocketMessage(ws: WebSocket, message: string | ArrayBuffer): void | Promise<void> {}
|
|
102
68
|
|
|
103
|
-
async fetch(
|
|
104
|
-
request: Request<any, CfProperties<any>>,
|
|
105
|
-
): Promise<Response> {
|
|
69
|
+
async fetch(request: Request<any, CfProperties<any>>): Promise<Response> {
|
|
106
70
|
const isWSRequest = request.headers.get("Upgrade") === "websocket";
|
|
107
71
|
|
|
108
72
|
if (!isWSRequest) {
|
|
@@ -123,12 +87,8 @@ export const createPluvHandler = <
|
|
|
123
87
|
}
|
|
124
88
|
};
|
|
125
89
|
|
|
126
|
-
const getDurableObjectNamespace = (
|
|
127
|
-
env
|
|
128
|
-
): DurableObjectNamespace => {
|
|
129
|
-
const namespace = env[
|
|
130
|
-
binding as keyof typeof env
|
|
131
|
-
] as DurableObjectNamespace;
|
|
90
|
+
const getDurableObjectNamespace = (env: Id<InferCloudflarePluvHandlerEnv<TPluvServer>>): DurableObjectNamespace => {
|
|
91
|
+
const namespace = env[binding as keyof typeof env] as DurableObjectNamespace;
|
|
132
92
|
|
|
133
93
|
if (!namespace) {
|
|
134
94
|
throw new Error(`Could not find DurableObject binding: ${binding}`);
|
|
@@ -137,9 +97,7 @@ export const createPluvHandler = <
|
|
|
137
97
|
return namespace;
|
|
138
98
|
};
|
|
139
99
|
|
|
140
|
-
const authHandler: PluvHandlerFetch<
|
|
141
|
-
Id<InferCloudflarePluvHandlerEnv<TPluv>>
|
|
142
|
-
> = async (request, env) => {
|
|
100
|
+
const authHandler: PluvHandlerFetch<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> = async (request, env) => {
|
|
143
101
|
if (!authorize) return null;
|
|
144
102
|
|
|
145
103
|
const { pathname, searchParams } = new URL(request.url);
|
|
@@ -176,19 +134,14 @@ export const createPluvHandler = <
|
|
|
176
134
|
status: 200,
|
|
177
135
|
});
|
|
178
136
|
} catch (err) {
|
|
179
|
-
return new Response(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
status: 403,
|
|
184
|
-
},
|
|
185
|
-
);
|
|
137
|
+
return new Response(err instanceof Error ? err.message : "Unauthorized", {
|
|
138
|
+
headers: { "Content-Type": "text/plain" },
|
|
139
|
+
status: 403,
|
|
140
|
+
});
|
|
186
141
|
}
|
|
187
142
|
};
|
|
188
143
|
|
|
189
|
-
const roomHandler: PluvHandlerFetch<
|
|
190
|
-
Id<InferCloudflarePluvHandlerEnv<TPluv>>
|
|
191
|
-
> = async (request, env) => {
|
|
144
|
+
const roomHandler: PluvHandlerFetch<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> = async (request, env) => {
|
|
192
145
|
const { pathname } = new URL(request.url);
|
|
193
146
|
const matcher = match<{ roomId: string }>(`${endpoint}/room/:roomId`);
|
|
194
147
|
const matched = matcher(pathname);
|
|
@@ -211,15 +164,13 @@ export const createPluvHandler = <
|
|
|
211
164
|
return room.fetch(request);
|
|
212
165
|
};
|
|
213
166
|
|
|
214
|
-
const fetch: PluvHandlerFetch<
|
|
215
|
-
Id<InferCloudflarePluvHandlerEnv<TPluv>>
|
|
216
|
-
> = async (request, env) => {
|
|
167
|
+
const fetch: PluvHandlerFetch<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> = async (request, env) => {
|
|
217
168
|
return [authHandler, roomHandler].reduce((promise, current) => {
|
|
218
169
|
return promise.then((value) => value ?? current(request, env));
|
|
219
170
|
}, Promise.resolve<Response | null>(null));
|
|
220
171
|
};
|
|
221
172
|
|
|
222
|
-
const handler: ExportedHandler<Id<InferCloudflarePluvHandlerEnv<
|
|
173
|
+
const handler: ExportedHandler<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> = {
|
|
223
174
|
fetch: async (request, env) => {
|
|
224
175
|
const response =
|
|
225
176
|
(await fetch(request, env)) ??
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { CloudflarePlatform } from "./CloudflarePlatform";
|
|
2
2
|
|
|
3
|
-
export const platformCloudflare = <
|
|
4
|
-
TEnv extends Record<string, any> = {},
|
|
5
|
-
>(): CloudflarePlatform<TEnv> => {
|
|
3
|
+
export const platformCloudflare = <TEnv extends Record<string, any> = {}>(): CloudflarePlatform<TEnv> => {
|
|
6
4
|
return new CloudflarePlatform<TEnv>();
|
|
7
5
|
};
|