@pluv/platform-cloudflare 1.0.0 → 1.0.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @pluv/platform-cloudflare@1.0.0 build /home/runner/work/pluv/pluv/packages/platform-cloudflare
2
+ > @pluv/platform-cloudflare@1.0.2 build /home/runner/work/pluv/pluv/packages/platform-cloudflare
3
3
  > tsup src/index.ts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -8,8 +8,8 @@
8
8
  CLI Using tsup config: /home/runner/work/pluv/pluv/packages/platform-cloudflare/tsup.config.ts
9
9
  CLI Target: es6
10
10
  ESM Build start
11
- ESM dist/index.mjs 13.91 KB
12
- ESM ⚡️ Build success in 23ms
11
+ ESM dist/index.mjs 14.01 KB
12
+ ESM ⚡️ Build success in 38ms
13
13
  DTS Build start
14
- DTS ⚡️ Build success in 1088ms
14
+ DTS ⚡️ Build success in 1190ms
15
15
  DTS dist/index.d.mts 7.31 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @pluv/platform-cloudflare
2
2
 
3
+ ## 1.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - @pluv/io@1.0.2
8
+ - @pluv/persistence-cloudflare-transactional-storage@1.0.2
9
+ - @pluv/types@1.0.2
10
+
11
+ ## 1.0.1
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies [c583be9]
16
+ - @pluv/io@1.0.1
17
+ - @pluv/persistence-cloudflare-transactional-storage@1.0.1
18
+ - @pluv/types@1.0.1
19
+
3
20
  ## 1.0.0
4
21
 
5
22
  ### Major Changes
package/dist/index.mjs CHANGED
@@ -83,7 +83,8 @@ var createPluvHandler = (config) => {
83
83
  const { 0: client, 1: server } = new WebSocketPair();
84
84
  const token = new URL(request.url).searchParams.get("token");
85
85
  const alarm = yield this.ctx.storage.getAlarm();
86
- if (alarm !== null) yield this.ctx.storage.setAlarm(Date.now() + GARBAGE_COLLECT_INTERVAL_MS);
86
+ if (alarm !== null)
87
+ yield this.ctx.storage.setAlarm(Date.now() + GARBAGE_COLLECT_INTERVAL_MS);
87
88
  yield this._room.register(server, { env: this.env, request, token });
88
89
  return new Response(null, { status: 101, webSocket: client });
89
90
  });
@@ -116,7 +117,11 @@ var createPluvHandler = (config) => {
116
117
  });
117
118
  }
118
119
  try {
119
- const user = yield authorize({ env, request, room });
120
+ const user = yield authorize({
121
+ env,
122
+ request,
123
+ room
124
+ });
120
125
  if (!user) throw new Error();
121
126
  const namespace = getDurableObjectNamespace(env);
122
127
  const durableObjectId = namespace.idFromName(room);
@@ -257,7 +262,9 @@ var CloudflareWebSocket = class extends AbstractWebSocket {
257
262
  this.webSocket.addEventListener(type, handler);
258
263
  }
259
264
  close(code, reason) {
260
- const canClose = [this.CONNECTING, this.OPEN].some((readyState) => readyState === this.readyState);
265
+ const canClose = [this.CONNECTING, this.OPEN].some(
266
+ (readyState) => readyState === this.readyState
267
+ );
261
268
  if (!canClose) return;
262
269
  this.webSocket.close(code, reason);
263
270
  }
@@ -295,7 +302,10 @@ var CloudflarePlatform = class _CloudflarePlatform extends AbstractPlatform {
295
302
  const detachedState = this._getDetachedState();
296
303
  if (!detachedState) return;
297
304
  detachedState.setWebSocketAutoResponse(
298
- new WebSocketRequestResponsePair('{"type":"$ping","data":{}}', JSON.stringify({ type: "$pong", data: {} }))
305
+ new WebSocketRequestResponsePair(
306
+ '{"type":"$ping","data":{}}',
307
+ JSON.stringify({ type: "$pong", data: {} })
308
+ )
299
309
  );
300
310
  }
301
311
  acceptWebSocket(webSocket) {
@@ -310,7 +320,11 @@ var CloudflarePlatform = class _CloudflarePlatform extends AbstractPlatform {
310
320
  }
311
321
  convertWebSocket(webSocket, config) {
312
322
  const { room } = config;
313
- return new CloudflareWebSocket(webSocket, { persistence: this.persistence, platform: this, room });
323
+ return new CloudflareWebSocket(webSocket, {
324
+ persistence: this.persistence,
325
+ platform: this,
326
+ room
327
+ });
314
328
  }
315
329
  getLastPing(webSocket) {
316
330
  var _a;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluv/platform-cloudflare",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "@pluv/io adapter for cloudflare workers",
5
5
  "author": "leedavidcs",
6
6
  "license": "MIT",
@@ -17,17 +17,17 @@
17
17
  },
18
18
  "dependencies": {
19
19
  "path-to-regexp": "^8.2.0",
20
- "@pluv/io": "^1.0.0",
21
- "@pluv/persistence-cloudflare-transactional-storage": "^1.0.0",
22
- "@pluv/types": "^1.0.0"
20
+ "@pluv/io": "^1.0.2",
21
+ "@pluv/persistence-cloudflare-transactional-storage": "^1.0.2",
22
+ "@pluv/types": "^1.0.2"
23
23
  },
24
24
  "devDependencies": {
25
25
  "@cloudflare/workers-types": "^4.20250430.0",
26
26
  "eslint": "^9.25.1",
27
27
  "tsup": "^8.4.0",
28
28
  "typescript": "^5.8.3",
29
- "@pluv/tsconfig": "^1.0.0",
30
- "eslint-config-pluv": "^1.0.0"
29
+ "@pluv/tsconfig": "^1.0.2",
30
+ "eslint-config-pluv": "^1.0.2"
31
31
  },
32
32
  "scripts": {
33
33
  "build": "tsup src/index.ts",
@@ -10,7 +10,10 @@ import type { IOAuthorize, Json } from "@pluv/types";
10
10
  import { CloudflareWebSocket } from "./CloudflareWebSocket";
11
11
  import { DEFAULT_REGISTRATION_MODE } from "./constants";
12
12
 
13
- export type CloudflarePlatformRoomContext<TEnv extends Record<string, any>, TMeta extends Record<string, Json>> = {
13
+ export type CloudflarePlatformRoomContext<
14
+ TEnv extends Record<string, any>,
15
+ TMeta extends Record<string, Json>,
16
+ > = {
14
17
  env: TEnv;
15
18
  state: DurableObjectState;
16
19
  } & (keyof TMeta extends never ? { meta?: undefined } : { meta: TMeta });
@@ -18,7 +21,9 @@ export type CloudflarePlatformRoomContext<TEnv extends Record<string, any>, TMet
18
21
  export type CloudflarePlatformConfig<
19
22
  TEnv extends Record<string, any> = {},
20
23
  TMeta extends Record<string, Json> = {},
21
- > = AbstractPlatformConfig<CloudflarePlatformRoomContext<TEnv, TMeta>> & { mode?: WebSocketRegistrationMode };
24
+ > = AbstractPlatformConfig<CloudflarePlatformRoomContext<TEnv, TMeta>> & {
25
+ mode?: WebSocketRegistrationMode;
26
+ };
22
27
 
23
28
  export class CloudflarePlatform<
24
29
  TAuthorize extends IOAuthorize<any, any> | null = null,
@@ -78,7 +83,10 @@ export class CloudflarePlatform<
78
83
  if (!detachedState) return;
79
84
 
80
85
  detachedState.setWebSocketAutoResponse(
81
- new WebSocketRequestResponsePair('{"type":"$ping","data":{}}', JSON.stringify({ type: "$pong", data: {} })),
86
+ new WebSocketRequestResponsePair(
87
+ '{"type":"$ping","data":{}}',
88
+ JSON.stringify({ type: "$pong", data: {} }),
89
+ ),
82
90
  );
83
91
  }
84
92
 
@@ -94,10 +102,17 @@ export class CloudflarePlatform<
94
102
  detachedState.acceptWebSocket(webSocket.webSocket);
95
103
  }
96
104
 
97
- public convertWebSocket(webSocket: WebSocket, config: ConvertWebSocketConfig): CloudflareWebSocket<TAuthorize> {
105
+ public convertWebSocket(
106
+ webSocket: WebSocket,
107
+ config: ConvertWebSocketConfig,
108
+ ): CloudflareWebSocket<TAuthorize> {
98
109
  const { room } = config;
99
110
 
100
- return new CloudflareWebSocket<TAuthorize>(webSocket, { persistence: this.persistence, platform: this, room });
111
+ return new CloudflareWebSocket<TAuthorize>(webSocket, {
112
+ persistence: this.persistence,
113
+ platform: this,
114
+ room,
115
+ });
101
116
  }
102
117
 
103
118
  public getLastPing(webSocket: CloudflareWebSocket<TAuthorize>): number | null {
@@ -135,7 +150,9 @@ export class CloudflarePlatform<
135
150
  return webSockets;
136
151
  }
137
152
 
138
- public initialize(config: AbstractPlatformConfig<CloudflarePlatformRoomContext<TEnv, TMeta>>): this {
153
+ public initialize(
154
+ config: AbstractPlatformConfig<CloudflarePlatformRoomContext<TEnv, TMeta>>,
155
+ ): this {
139
156
  const ctx = config.roomContext ?? { ...this._roomContext };
140
157
 
141
158
  if (!ctx.env || !ctx.state) throw new Error("Could not derive platform roomContext");
@@ -17,10 +17,9 @@ export interface CloudflareWebSocketEventMap {
17
17
 
18
18
  export type CloudflareWebSocketConfig = AbstractWebSocketConfig;
19
19
 
20
- export class CloudflareWebSocket<TAuthorize extends IOAuthorize<any, any> | null = null> extends AbstractWebSocket<
21
- WebSocket,
22
- TAuthorize
23
- > {
20
+ export class CloudflareWebSocket<
21
+ TAuthorize extends IOAuthorize<any, any> | null = null,
22
+ > extends AbstractWebSocket<WebSocket, TAuthorize> {
24
23
  public set presence(presence: JsonObject | null) {
25
24
  const deserialized = this.webSocket.deserializeAttachment();
26
25
  const state = deserialized.state;
@@ -113,12 +112,17 @@ export class CloudflareWebSocket<TAuthorize extends IOAuthorize<any, any> | null
113
112
  });
114
113
  }
115
114
 
116
- public addEventListener<TType extends keyof AbstractEventMap>(type: TType, handler: AbstractListener<TType>) {
115
+ public addEventListener<TType extends keyof AbstractEventMap>(
116
+ type: TType,
117
+ handler: AbstractListener<TType>,
118
+ ) {
117
119
  this.webSocket.addEventListener(type, handler as any);
118
120
  }
119
121
 
120
122
  public close(code?: number | undefined, reason?: string | undefined): void {
121
- const canClose = [this.CONNECTING, this.OPEN].some((readyState) => readyState === this.readyState);
123
+ const canClose = [this.CONNECTING, this.OPEN].some(
124
+ (readyState) => readyState === this.readyState,
125
+ );
122
126
 
123
127
  if (!canClose) return;
124
128
 
@@ -1,5 +1,12 @@
1
1
  import type { InferInitContextType, IORoom, PluvServer } from "@pluv/io";
2
- import type { BaseUser, Id, InferIOAuthorize, InferIOAuthorizeUser, Maybe, MaybePromise } from "@pluv/types";
2
+ import type {
3
+ BaseUser,
4
+ Id,
5
+ InferIOAuthorize,
6
+ InferIOAuthorizeUser,
7
+ Maybe,
8
+ MaybePromise,
9
+ } from "@pluv/types";
3
10
  import { DurableObject as BaseDurableObject } from "cloudflare:workers";
4
11
  import { match } from "path-to-regexp";
5
12
  import { CloudflarePlatform } from "./CloudflarePlatform";
@@ -7,7 +14,9 @@ import { GARBAGE_COLLECT_INTERVAL_MS } from "./constants";
7
14
 
8
15
  export type AuthorizeFunctionContext<TPluvServer extends PluvServer<any, any, any, any>> = {
9
16
  room: string;
10
- } & InferInitContextType<TPluvServer extends PluvServer<infer IPlatform, any, any, any> ? IPlatform : never>;
17
+ } & InferInitContextType<
18
+ TPluvServer extends PluvServer<infer IPlatform, any, any, any> ? IPlatform : never
19
+ >;
11
20
  export type AuthorizeFunction<TPluvServer extends PluvServer<any, any, any, any>> = (
12
21
  ctx: AuthorizeFunctionContext<TPluvServer>,
13
22
  ) => MaybePromise<Maybe<InferIOAuthorizeUser<InferIOAuthorize<TPluvServer>>>>;
@@ -37,28 +46,41 @@ export interface CreatePluvHandlerResult<TEnv extends Record<string, any> = {}>
37
46
  handler: ExportedHandler<TEnv>;
38
47
  }
39
48
 
40
- type InferCloudflarePluvHandlerEnv<TPluvServer extends PluvServer<CloudflarePlatform<any, any>, any, any, any>> =
41
- TPluvServer extends PluvServer<CloudflarePlatform<any, infer IEnv>, any, any, any> ? IEnv : {};
49
+ type InferCloudflarePluvHandlerEnv<
50
+ TPluvServer extends PluvServer<CloudflarePlatform<any, any>, any, any, any>,
51
+ > = TPluvServer extends PluvServer<CloudflarePlatform<any, infer IEnv>, any, any, any> ? IEnv : {};
42
52
 
43
53
  /**
44
54
  * @deprecated Instructions will be provided on https://pluv.io on how to host this yourself instead.
45
55
  * @date April 27, 2025
46
56
  */
47
- export const createPluvHandler = <TPluvServer extends PluvServer<CloudflarePlatform<any, any>, any, any, any>>(
57
+ export const createPluvHandler = <
58
+ TPluvServer extends PluvServer<CloudflarePlatform<any, any>, any, any, any>,
59
+ >(
48
60
  config: CreatePluvHandlerConfig<TPluvServer, Id<InferCloudflarePluvHandlerEnv<TPluvServer>>>,
49
61
  ): CreatePluvHandlerResult<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> => {
50
62
  const { authorize, binding, endpoint = "/api/pluv", modify, io } = config;
51
63
 
52
- const DurableObject = class extends BaseDurableObject<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> {
64
+ const DurableObject = class extends BaseDurableObject<
65
+ Id<InferCloudflarePluvHandlerEnv<TPluvServer>>
66
+ > {
53
67
  private _room: IORoom<CloudflarePlatform<any, any>>;
54
68
 
55
- constructor(state: DurableObjectState, env: Id<InferCloudflarePluvHandlerEnv<TPluvServer>>) {
69
+ constructor(
70
+ state: DurableObjectState,
71
+ env: Id<InferCloudflarePluvHandlerEnv<TPluvServer>>,
72
+ ) {
56
73
  super(state, env);
57
74
 
58
75
  this._room = io.createRoom(state.id.toString(), { env, state });
59
76
  }
60
77
 
61
- public async webSocketClose(ws: WebSocket, code: number, reason: string, wasClean: boolean): Promise<void> {
78
+ public async webSocketClose(
79
+ ws: WebSocket,
80
+ code: number,
81
+ reason: string,
82
+ wasClean: boolean,
83
+ ): Promise<void> {
62
84
  if (io._defs.platform._config.registrationMode !== "detached") return;
63
85
 
64
86
  const onCloseHandler = this._room.onClose(ws);
@@ -92,7 +114,8 @@ export const createPluvHandler = <TPluvServer extends PluvServer<CloudflarePlatf
92
114
  const token = new URL(request.url).searchParams.get("token");
93
115
 
94
116
  const alarm = await this.ctx.storage.getAlarm();
95
- if (alarm !== null) await this.ctx.storage.setAlarm(Date.now() + GARBAGE_COLLECT_INTERVAL_MS);
117
+ if (alarm !== null)
118
+ await this.ctx.storage.setAlarm(Date.now() + GARBAGE_COLLECT_INTERVAL_MS);
96
119
 
97
120
  await this._room.register(server, { env: this.env, request, token });
98
121
 
@@ -105,7 +128,9 @@ export const createPluvHandler = <TPluvServer extends PluvServer<CloudflarePlatf
105
128
  }
106
129
  };
107
130
 
108
- const getDurableObjectNamespace = (env: Id<InferCloudflarePluvHandlerEnv<TPluvServer>>): DurableObjectNamespace => {
131
+ const getDurableObjectNamespace = (
132
+ env: Id<InferCloudflarePluvHandlerEnv<TPluvServer>>,
133
+ ): DurableObjectNamespace => {
109
134
  const namespace = env[binding as keyof typeof env] as DurableObjectNamespace;
110
135
 
111
136
  if (!namespace) {
@@ -115,7 +140,10 @@ export const createPluvHandler = <TPluvServer extends PluvServer<CloudflarePlatf
115
140
  return namespace;
116
141
  };
117
142
 
118
- const authHandler: PluvHandlerFetch<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> = async (request, env) => {
143
+ const authHandler: PluvHandlerFetch<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> = async (
144
+ request,
145
+ env,
146
+ ) => {
119
147
  if (!authorize) return null;
120
148
 
121
149
  const { pathname, searchParams } = new URL(request.url);
@@ -134,7 +162,11 @@ export const createPluvHandler = <TPluvServer extends PluvServer<CloudflarePlatf
134
162
  }
135
163
 
136
164
  try {
137
- const user = await authorize({ env, request, room } as AuthorizeFunctionContext<TPluvServer>);
165
+ const user = await authorize({
166
+ env,
167
+ request,
168
+ room,
169
+ } as AuthorizeFunctionContext<TPluvServer>);
138
170
 
139
171
  if (!user) throw new Error();
140
172
 
@@ -160,7 +192,10 @@ export const createPluvHandler = <TPluvServer extends PluvServer<CloudflarePlatf
160
192
  }
161
193
  };
162
194
 
163
- const roomHandler: PluvHandlerFetch<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> = async (request, env) => {
195
+ const roomHandler: PluvHandlerFetch<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> = async (
196
+ request,
197
+ env,
198
+ ) => {
164
199
  const { pathname } = new URL(request.url);
165
200
  const matcher = match<{ roomId: string }>(`${endpoint}/room/:roomId`);
166
201
  const matched = matcher(pathname);
@@ -183,7 +218,10 @@ export const createPluvHandler = <TPluvServer extends PluvServer<CloudflarePlatf
183
218
  return room.fetch(request);
184
219
  };
185
220
 
186
- const handlerFetch: PluvHandlerFetch<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> = async (request, env) => {
221
+ const handlerFetch: PluvHandlerFetch<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> = async (
222
+ request,
223
+ env,
224
+ ) => {
187
225
  return [authHandler, roomHandler].reduce(async (promise, current) => {
188
226
  return await promise.then(async (value) => value ?? (await current(request, env)));
189
227
  }, Promise.resolve<Response | null>(null));
package/src/infer.ts CHANGED
@@ -1,13 +1,17 @@
1
1
  import type { Json } from "@pluv/types";
2
2
  import type { identity } from "./utils";
3
3
 
4
- export type InferCallback<TEnv extends Record<string, any> = {}, TMeta extends Record<string, Json> = {}> = (
5
- i: typeof identity,
6
- ) => {
4
+ export type InferCallback<
5
+ TEnv extends Record<string, any> = {},
6
+ TMeta extends Record<string, Json> = {},
7
+ > = (i: typeof identity) => {
7
8
  env?: (io: TEnv) => TEnv;
8
9
  meta?: (io: TMeta) => TMeta;
9
10
  };
10
11
 
11
- export const infer = <TEnv extends Record<string, any> = {}, TMeta extends Record<string, Json> = {}>(
12
+ export const infer = <
13
+ TEnv extends Record<string, any> = {},
14
+ TMeta extends Record<string, Json> = {},
15
+ >(
12
16
  callback: InferCallback<TEnv, TMeta>,
13
17
  ) => callback;
@@ -12,7 +12,11 @@ export type PlatformCloudflareCreateIOParams<
12
12
  > = Id<
13
13
  CloudflarePlatformConfig<TEnv, TMeta> &
14
14
  Omit<
15
- CreateIOParams<CloudflarePlatform<IOAuthorize<TUser, TContext>, TEnv, TMeta>, TContext, TUser>,
15
+ CreateIOParams<
16
+ CloudflarePlatform<IOAuthorize<TUser, TContext>, TEnv, TMeta>,
17
+ TContext,
18
+ TUser
19
+ >,
16
20
  "authorize" | "context" | "platform"
17
21
  > & {
18
22
  authorize?: PluvIOAuthorize<
@@ -20,7 +24,10 @@ export type PlatformCloudflareCreateIOParams<
20
24
  TUser,
21
25
  InferInitContextType<CloudflarePlatform<IOAuthorize<TUser, TContext>, TEnv, TMeta>>
22
26
  >;
23
- context?: PluvContext<CloudflarePlatform<IOAuthorize<TUser, any>, TEnv, TMeta>, TContext>;
27
+ context?: PluvContext<
28
+ CloudflarePlatform<IOAuthorize<TUser, any>, TEnv, TMeta>,
29
+ TContext
30
+ >;
24
31
  types?: InferCallback<TEnv, TMeta>;
25
32
  }
26
33
  >;
@@ -32,7 +39,11 @@ export const platformCloudflare = <
32
39
  TUser extends BaseUser | null = null,
33
40
  >(
34
41
  config: PlatformCloudflareCreateIOParams<TEnv, TMeta, TContext, TUser> = {},
35
- ): CreateIOParams<CloudflarePlatform<IOAuthorize<TUser, TContext>, TEnv, TMeta>, TContext, TUser> => {
42
+ ): CreateIOParams<
43
+ CloudflarePlatform<IOAuthorize<TUser, TContext>, TEnv, TMeta>,
44
+ TContext,
45
+ TUser
46
+ > => {
36
47
  const { authorize, context, crdt, debug, limits } = config;
37
48
 
38
49
  return {