@pluv/platform-cloudflare 0.39.1 → 0.40.1

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,18 +1,15 @@
1
1
 
2
- > @pluv/platform-cloudflare@0.39.1 build /home/runner/work/pluv/pluv/packages/platform-cloudflare
3
- > tsup src/index.ts --format esm,cjs --dts
2
+ > @pluv/platform-cloudflare@0.40.1 build /home/runner/work/pluv/pluv/packages/platform-cloudflare
3
+ > tsup src/index.ts
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
7
  CLI tsup v8.4.0
8
+ CLI Using tsup config: /home/runner/work/pluv/pluv/packages/platform-cloudflare/tsup.config.ts
8
9
  CLI Target: es6
9
10
  ESM Build start
10
- CJS Build start
11
- ESM dist/index.mjs 12.83 KB
12
- ESM ⚡️ Build success in 61ms
13
- CJS dist/index.js 13.96 KB
14
- CJS ⚡️ Build success in 64ms
11
+ ESM dist/index.mjs 12.93 KB
12
+ ESM ⚡️ Build success in 50ms
15
13
  DTS Build start
16
- DTS ⚡️ Build success in 1097ms
17
- DTS dist/index.d.mts 6.64 KB
18
- DTS dist/index.d.ts 6.64 KB
14
+ DTS ⚡️ Build success in 1260ms
15
+ DTS dist/index.d.mts 6.70 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @pluv/platform-cloudflare
2
2
 
3
+ ## 0.40.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 99019a3: Fix return type to return the correct DurableObject type from `createPluvHandler`.
8
+ - @pluv/io@0.40.1
9
+ - @pluv/persistence-cloudflare-transactional-storage@0.40.1
10
+ - @pluv/types@0.40.1
11
+
12
+ ## 0.40.0
13
+
14
+ ### Minor Changes
15
+
16
+ - f53c6cb: **BREAKING** The `DurableObject` from `createPluvHandler` now properly extends `DuableObject` from `cloudflare:workers`. `@pluv/platform-pluv` is also now only ESM. This may break some Cloudflare Workers if on an older compatibility date.
17
+
18
+ ### Patch Changes
19
+
20
+ - @pluv/io@0.40.0
21
+ - @pluv/persistence-cloudflare-transactional-storage@0.40.0
22
+ - @pluv/types@0.40.0
23
+
3
24
  ## 0.39.1
4
25
 
5
26
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { AbstractWebSocket, WebSocketSerializedState, AbstractWebSocketConfig, AbstractEventMap, AbstractListener, AbstractPlatform, WebSocketRegistrationMode, AbstractPlatformConfig, ConvertWebSocketConfig, PluvServer, InferInitContextType, CreateIOParams, PluvIOAuthorize, PluvContext } from '@pluv/io';
2
2
  import { JsonObject, Json, MaybePromise, InferIOAuthorizeUser, InferIOAuthorize, BaseUser, Maybe, Id } from '@pluv/types';
3
+ import { DurableObject } from 'cloudflare:workers';
3
4
 
4
5
  type CloudflareWebSocketConfig = AbstractWebSocketConfig;
5
6
  declare class CloudflareWebSocket extends AbstractWebSocket<WebSocket> {
@@ -93,7 +94,7 @@ type CreatePluvHandlerConfig<TPluvServer extends PluvServer<any, any, any, any>,
93
94
  type PluvHandlerFetch<TEnv extends Record<string, any> = {}> = (request: Request, env: TEnv) => Promise<Response | null>;
94
95
  interface CreatePluvHandlerResult<TEnv extends Record<string, any> = {}> {
95
96
  DurableObject: {
96
- new (state: DurableObjectState, env: TEnv): DurableObject;
97
+ new (state: DurableObjectState, env: TEnv): DurableObject<TEnv>;
97
98
  };
98
99
  fetch: PluvHandlerFetch<TEnv>;
99
100
  handler: ExportedHandler<TEnv>;
package/dist/index.mjs CHANGED
@@ -39,12 +39,13 @@ var __async = (__this, __arguments, generator) => {
39
39
  };
40
40
 
41
41
  // src/createPluvHandler.ts
42
+ import { DurableObject as BaseDurableObject } from "cloudflare:workers";
42
43
  import { match } from "path-to-regexp";
43
44
  var createPluvHandler = (config) => {
44
45
  const { authorize, binding, endpoint = "/api/pluv", modify, io } = config;
45
- const DurableObject = class {
46
+ const DurableObject = class extends BaseDurableObject {
46
47
  constructor(state, env) {
47
- this._env = env;
48
+ super(state, env);
48
49
  this._room = io.createRoom(state.id.toString(), { env, state });
49
50
  }
50
51
  webSocketClose(ws, code, reason, wasClean) {
@@ -75,7 +76,7 @@ var createPluvHandler = (config) => {
75
76
  if (!isWSRequest) return new Response("Expected websocket", { status: 400 });
76
77
  const { 0: client, 1: server } = new WebSocketPair();
77
78
  const token = new URL(request.url).searchParams.get("token");
78
- yield this._room.register(server, { env: this._env, request, token });
79
+ yield this._room.register(server, { env: this.env, request, token });
79
80
  return new Response(null, { status: 101, webSocket: client });
80
81
  });
81
82
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluv/platform-cloudflare",
3
- "version": "0.39.1",
3
+ "version": "0.40.1",
4
4
  "description": "@pluv/io adapter for cloudflare workers",
5
5
  "author": "leedavidcs",
6
6
  "license": "MIT",
@@ -10,28 +10,27 @@
10
10
  "url": "git+https://github.com/pluv-io/pluv.git",
11
11
  "directory": "packages/platform-cloudflare"
12
12
  },
13
- "main": "./dist/index.js",
14
13
  "module": "./dist/index.mjs",
15
- "types": "./dist/index.d.ts",
14
+ "types": "./dist/index.d.mts",
16
15
  "publishConfig": {
17
16
  "access": "public"
18
17
  },
19
18
  "dependencies": {
20
19
  "path-to-regexp": "^8.2.0",
21
- "@pluv/io": "^0.39.1",
22
- "@pluv/types": "^0.39.1",
23
- "@pluv/persistence-cloudflare-transactional-storage": "^0.39.1"
20
+ "@pluv/io": "^0.40.1",
21
+ "@pluv/persistence-cloudflare-transactional-storage": "^0.40.1",
22
+ "@pluv/types": "^0.40.1"
24
23
  },
25
24
  "devDependencies": {
26
25
  "@cloudflare/workers-types": "^4.20250414.0",
27
26
  "eslint": "^9.24.0",
28
27
  "tsup": "^8.4.0",
29
28
  "typescript": "^5.8.3",
30
- "@pluv/tsconfig": "^0.39.1",
31
- "eslint-config-pluv": "^0.39.1"
29
+ "@pluv/tsconfig": "^0.40.1",
30
+ "eslint-config-pluv": "^0.40.1"
32
31
  },
33
32
  "scripts": {
34
- "build": "tsup src/index.ts --format esm,cjs --dts",
33
+ "build": "tsup src/index.ts",
35
34
  "dev": "tsup src/index.ts --format esm,cjs --watch --dts",
36
35
  "lint": "eslint src/**/*.ts* --fix --max-warnings 0",
37
36
  "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
@@ -1,5 +1,6 @@
1
1
  import type { InferInitContextType, IORoom, PluvServer } from "@pluv/io";
2
2
  import type { BaseUser, Id, InferIOAuthorize, InferIOAuthorizeUser, Maybe, MaybePromise } from "@pluv/types";
3
+ import { DurableObject as BaseDurableObject } from "cloudflare:workers";
3
4
  import { match } from "path-to-regexp";
4
5
  import { CloudflarePlatform } from "./CloudflarePlatform";
5
6
 
@@ -29,7 +30,7 @@ export type PluvHandlerFetch<TEnv extends Record<string, any> = {}> = (
29
30
 
30
31
  export interface CreatePluvHandlerResult<TEnv extends Record<string, any> = {}> {
31
32
  DurableObject: {
32
- new (state: DurableObjectState, env: TEnv): DurableObject;
33
+ new (state: DurableObjectState, env: TEnv): BaseDurableObject<TEnv>;
33
34
  };
34
35
  fetch: PluvHandlerFetch<TEnv>;
35
36
  handler: ExportedHandler<TEnv>;
@@ -43,12 +44,12 @@ export const createPluvHandler = <TPluvServer extends PluvServer<CloudflarePlatf
43
44
  ): CreatePluvHandlerResult<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> => {
44
45
  const { authorize, binding, endpoint = "/api/pluv", modify, io } = config;
45
46
 
46
- const DurableObject = class implements DurableObject {
47
- private _env: Id<InferCloudflarePluvHandlerEnv<TPluvServer>>;
47
+ const DurableObject = class extends BaseDurableObject<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>> {
48
48
  private _room: IORoom<CloudflarePlatform>;
49
49
 
50
50
  constructor(state: DurableObjectState, env: Id<InferCloudflarePluvHandlerEnv<TPluvServer>>) {
51
- this._env = env;
51
+ super(state, env);
52
+
52
53
  this._room = io.createRoom(state.id.toString(), { env, state });
53
54
  }
54
55
 
@@ -85,7 +86,7 @@ export const createPluvHandler = <TPluvServer extends PluvServer<CloudflarePlatf
85
86
  const { 0: client, 1: server } = new WebSocketPair();
86
87
  const token = new URL(request.url).searchParams.get("token");
87
88
 
88
- await this._room.register(server, { env: this._env, request, token });
89
+ await this._room.register(server, { env: this.env, request, token });
89
90
 
90
91
  return new Response(null, { status: 101, webSocket: client });
91
92
  }
package/tsup.config.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from "tsup";
2
+
3
+ export default defineConfig({
4
+ dts: true,
5
+ entry: ["src/index.ts"],
6
+ external: ["cloudflare:workers"],
7
+ format: ["esm"],
8
+ });
package/dist/index.d.ts DELETED
@@ -1,119 +0,0 @@
1
- import { AbstractWebSocket, WebSocketSerializedState, AbstractWebSocketConfig, AbstractEventMap, AbstractListener, AbstractPlatform, WebSocketRegistrationMode, AbstractPlatformConfig, ConvertWebSocketConfig, PluvServer, InferInitContextType, CreateIOParams, PluvIOAuthorize, PluvContext } from '@pluv/io';
2
- import { JsonObject, Json, MaybePromise, InferIOAuthorizeUser, InferIOAuthorize, BaseUser, Maybe, Id } from '@pluv/types';
3
-
4
- type CloudflareWebSocketConfig = AbstractWebSocketConfig;
5
- declare class CloudflareWebSocket extends AbstractWebSocket<WebSocket> {
6
- set presence(presence: JsonObject | null);
7
- get readyState(): 0 | 1 | 2 | 3;
8
- get sessionId(): string;
9
- get state(): WebSocketSerializedState;
10
- set state(state: WebSocketSerializedState);
11
- constructor(webSocket: WebSocket, config: CloudflareWebSocketConfig);
12
- addEventListener<TType extends keyof AbstractEventMap>(type: TType, handler: AbstractListener<TType>): void;
13
- close(code?: number | undefined, reason?: string | undefined): void;
14
- send(message: string | ArrayBuffer | ArrayBufferView): void;
15
- terminate(code?: number): void;
16
- }
17
-
18
- type CloudflarePlatformRoomContext<TEnv extends Record<string, any>, TMeta extends Record<string, Json>> = {
19
- env: TEnv;
20
- state: DurableObjectState;
21
- } & (keyof TMeta extends never ? {
22
- meta?: undefined;
23
- } : {
24
- meta: TMeta;
25
- });
26
- type CloudflarePlatformConfig<TEnv extends Record<string, any> = {}, TMeta extends Record<string, Json> = {}> = AbstractPlatformConfig<CloudflarePlatformRoomContext<TEnv, TMeta>> & {
27
- mode?: WebSocketRegistrationMode;
28
- };
29
- declare class CloudflarePlatform<TEnv extends Record<string, any> = {}, TMeta extends Record<string, Json> = {}> extends AbstractPlatform<CloudflareWebSocket, {
30
- env: TEnv;
31
- request: Request;
32
- }, CloudflarePlatformRoomContext<TEnv, TMeta>, {
33
- authorize: {
34
- secret: true;
35
- };
36
- handleMode: "io";
37
- requireAuth: false;
38
- registrationMode: WebSocketRegistrationMode;
39
- listeners: {
40
- onRoomDeleted: true;
41
- onRoomMessage: true;
42
- onStorageUpdated: true;
43
- onUserConnected: true;
44
- onUserDisconnected: true;
45
- };
46
- router: true;
47
- }> {
48
- readonly _config: {
49
- authorize: {
50
- secret: true;
51
- };
52
- handleMode: "io";
53
- registrationMode: WebSocketRegistrationMode;
54
- requireAuth: false;
55
- listeners: {
56
- onRoomDeleted: true;
57
- onRoomMessage: true;
58
- onStorageUpdated: true;
59
- onUserConnected: true;
60
- onUserDisconnected: true;
61
- };
62
- router: true;
63
- };
64
- readonly _name = "platformCloudflare";
65
- constructor(config: CloudflarePlatformConfig<TEnv, TMeta>);
66
- acceptWebSocket(webSocket: CloudflareWebSocket): Promise<void>;
67
- convertWebSocket(webSocket: WebSocket, config: ConvertWebSocketConfig): CloudflareWebSocket;
68
- getLastPing(webSocket: CloudflareWebSocket): number | null;
69
- getSerializedState(webSocket: WebSocket): WebSocketSerializedState | null;
70
- getSessionId(webSocket: WebSocket): string | null;
71
- getWebSockets(): readonly WebSocket[];
72
- initialize(config: AbstractPlatformConfig<CloudflarePlatformRoomContext<TEnv, TMeta>>): this;
73
- parseData(data: string | ArrayBuffer): Record<string, any>;
74
- randomUUID(): string;
75
- setSerializedState(webSocket: CloudflareWebSocket, state: WebSocketSerializedState): WebSocketSerializedState;
76
- private _getDetachedState;
77
- }
78
-
79
- type AuthorizeFunctionContext<TPluvServer extends PluvServer<any, any, any, any>> = {
80
- room: string;
81
- } & InferInitContextType<TPluvServer extends PluvServer<infer IPlatform, any, any, any> ? IPlatform : never>;
82
- type AuthorizeFunction<TPluvServer extends PluvServer<any, any, any, any>> = (ctx: AuthorizeFunctionContext<TPluvServer>) => MaybePromise<Maybe<InferIOAuthorizeUser<InferIOAuthorize<TPluvServer>>>>;
83
- type CreatePluvHandlerConfig<TPluvServer extends PluvServer<any, any, any, any>, TEnv extends Record<string, any>> = {
84
- binding: string;
85
- endpoint?: string;
86
- modify?: (request: Request, response: Response, env: TEnv) => MaybePromise<Response>;
87
- io: TPluvServer;
88
- } & (InferIOAuthorizeUser<InferIOAuthorize<TPluvServer>> extends BaseUser ? {
89
- authorize: AuthorizeFunction<TPluvServer>;
90
- } : {
91
- authorize?: undefined;
92
- });
93
- type PluvHandlerFetch<TEnv extends Record<string, any> = {}> = (request: Request, env: TEnv) => Promise<Response | null>;
94
- interface CreatePluvHandlerResult<TEnv extends Record<string, any> = {}> {
95
- DurableObject: {
96
- new (state: DurableObjectState, env: TEnv): DurableObject;
97
- };
98
- fetch: PluvHandlerFetch<TEnv>;
99
- handler: ExportedHandler<TEnv>;
100
- }
101
- type InferCloudflarePluvHandlerEnv<TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>> = TPluvServer extends PluvServer<CloudflarePlatform<infer IEnv>, any, any, any> ? IEnv : {};
102
- declare const createPluvHandler: <TPluvServer extends PluvServer<CloudflarePlatform, any, any, any>>(config: CreatePluvHandlerConfig<TPluvServer, Id<InferCloudflarePluvHandlerEnv<TPluvServer>>>) => CreatePluvHandlerResult<Id<InferCloudflarePluvHandlerEnv<TPluvServer>>>;
103
-
104
- declare const identity: <T extends unknown>(x: T) => T;
105
-
106
- type InferCallback<TEnv extends Record<string, any> = {}, TMeta extends Record<string, Json> = {}> = (i: typeof identity) => {
107
- env?: (io: TEnv) => TEnv;
108
- meta?: (io: TMeta) => TMeta;
109
- };
110
- declare const infer: <TEnv extends Record<string, any> = {}, TMeta extends Record<string, Json> = {}>(callback: InferCallback<TEnv, TMeta>) => InferCallback<TEnv, TMeta>;
111
-
112
- type PlatformCloudflareCreateIOParams<TEnv extends Record<string, any> = {}, TMeta extends Record<string, Json> = {}, TContext extends Record<string, any> = {}, TUser extends BaseUser | null = null> = Id<CloudflarePlatformConfig<TEnv, TMeta> & Omit<CreateIOParams<CloudflarePlatform<TEnv, TMeta>, TContext, TUser>, "authorize" | "context" | "platform"> & {
113
- authorize?: PluvIOAuthorize<CloudflarePlatform<TEnv, TMeta>, TUser, InferInitContextType<CloudflarePlatform<TEnv, TMeta>>>;
114
- context?: PluvContext<CloudflarePlatform<TEnv, TMeta>, TContext>;
115
- types?: InferCallback<TEnv, TMeta>;
116
- }>;
117
- declare const platformCloudflare: <TEnv extends Record<string, any> = {}, TMeta extends Record<string, Json> = {}, TContext extends Record<string, any> = {}, TUser extends BaseUser | null = null>(config?: PlatformCloudflareCreateIOParams<TEnv, TMeta, TContext, TUser>) => CreateIOParams<CloudflarePlatform<TEnv, TMeta>, TContext, TUser>;
118
-
119
- export { type AuthorizeFunction, type AuthorizeFunctionContext, CloudflarePlatform, type CloudflarePlatformConfig, type CreatePluvHandlerConfig, type CreatePluvHandlerResult, type InferCallback, type PlatformCloudflareCreateIOParams, type PluvHandlerFetch, createPluvHandler, infer, platformCloudflare };
package/dist/index.js DELETED
@@ -1,389 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __defProps = Object.defineProperties;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
8
- var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
10
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
11
- var __spreadValues = (a, b) => {
12
- for (var prop in b || (b = {}))
13
- if (__hasOwnProp.call(b, prop))
14
- __defNormalProp(a, prop, b[prop]);
15
- if (__getOwnPropSymbols)
16
- for (var prop of __getOwnPropSymbols(b)) {
17
- if (__propIsEnum.call(b, prop))
18
- __defNormalProp(a, prop, b[prop]);
19
- }
20
- return a;
21
- };
22
- var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
23
- var __export = (target, all) => {
24
- for (var name in all)
25
- __defProp(target, name, { get: all[name], enumerable: true });
26
- };
27
- var __copyProps = (to, from, except, desc) => {
28
- if (from && typeof from === "object" || typeof from === "function") {
29
- for (let key of __getOwnPropNames(from))
30
- if (!__hasOwnProp.call(to, key) && key !== except)
31
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
32
- }
33
- return to;
34
- };
35
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
36
- var __async = (__this, __arguments, generator) => {
37
- return new Promise((resolve, reject) => {
38
- var fulfilled = (value) => {
39
- try {
40
- step(generator.next(value));
41
- } catch (e) {
42
- reject(e);
43
- }
44
- };
45
- var rejected = (value) => {
46
- try {
47
- step(generator.throw(value));
48
- } catch (e) {
49
- reject(e);
50
- }
51
- };
52
- var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
53
- step((generator = generator.apply(__this, __arguments)).next());
54
- });
55
- };
56
-
57
- // src/index.ts
58
- var index_exports = {};
59
- __export(index_exports, {
60
- createPluvHandler: () => createPluvHandler,
61
- infer: () => infer,
62
- platformCloudflare: () => platformCloudflare
63
- });
64
- module.exports = __toCommonJS(index_exports);
65
-
66
- // src/createPluvHandler.ts
67
- var import_path_to_regexp = require("path-to-regexp");
68
- var createPluvHandler = (config) => {
69
- const { authorize, binding, endpoint = "/api/pluv", modify, io } = config;
70
- const DurableObject = class {
71
- constructor(state, env) {
72
- this._env = env;
73
- this._room = io.createRoom(state.id.toString(), { env, state });
74
- }
75
- webSocketClose(ws, code, reason, wasClean) {
76
- return __async(this, null, function* () {
77
- if (io._defs.platform._config.registrationMode !== "detached") return;
78
- const onCloseHandler = this._room.onClose(ws);
79
- yield onCloseHandler({ code, reason });
80
- });
81
- }
82
- webSocketError(ws, error) {
83
- return __async(this, null, function* () {
84
- if (io._defs.platform._config.registrationMode !== "detached") return;
85
- const onErrorHandler = this._room.onError(ws);
86
- const eventError = error instanceof Error ? error : new Error("Internal Error");
87
- yield onErrorHandler({ error: eventError, message: eventError.message });
88
- });
89
- }
90
- webSocketMessage(ws, message) {
91
- return __async(this, null, function* () {
92
- if (io._defs.platform._config.registrationMode !== "detached") return;
93
- const onMessageHandler = this._room.onMessage(ws);
94
- yield onMessageHandler({ data: message });
95
- });
96
- }
97
- fetch(request) {
98
- return __async(this, null, function* () {
99
- const isWSRequest = request.headers.get("Upgrade") === "websocket";
100
- if (!isWSRequest) return new Response("Expected websocket", { status: 400 });
101
- const { 0: client, 1: server } = new WebSocketPair();
102
- const token = new URL(request.url).searchParams.get("token");
103
- yield this._room.register(server, { env: this._env, request, token });
104
- return new Response(null, { status: 101, webSocket: client });
105
- });
106
- }
107
- };
108
- const getDurableObjectNamespace = (env) => {
109
- const namespace = env[binding];
110
- if (!namespace) {
111
- throw new Error(`Could not find DurableObject binding: ${binding}`);
112
- }
113
- return namespace;
114
- };
115
- const authHandler = (request, env) => __async(void 0, null, function* () {
116
- if (!authorize) return null;
117
- const { pathname, searchParams } = new URL(request.url);
118
- const matcher = (0, import_path_to_regexp.match)(`${endpoint}/authorize`);
119
- const matched = matcher(pathname);
120
- if (!matched) return null;
121
- const room = searchParams.get("room");
122
- if (!room) {
123
- return new Response("Not found", {
124
- headers: { "Content-Type": "text/plain" },
125
- status: 404
126
- });
127
- }
128
- try {
129
- const user = yield authorize({ env, request, room });
130
- if (!user) throw new Error();
131
- const namespace = getDurableObjectNamespace(env);
132
- const durableObjectId = namespace.idFromName(room);
133
- const token = yield io.createToken({
134
- env,
135
- room: durableObjectId.toString(),
136
- user,
137
- request
138
- });
139
- return new Response(token, {
140
- headers: { "Content-Type": "text/plain" },
141
- status: 200
142
- });
143
- } catch (err) {
144
- return new Response(err instanceof Error ? err.message : "Unauthorized", {
145
- headers: { "Content-Type": "text/plain" },
146
- status: 403
147
- });
148
- }
149
- });
150
- const roomHandler = (request, env) => __async(void 0, null, function* () {
151
- const { pathname } = new URL(request.url);
152
- const matcher = (0, import_path_to_regexp.match)(`${endpoint}/room/:roomId`);
153
- const matched = matcher(pathname);
154
- if (!matched) return null;
155
- const { roomId } = matched.params;
156
- if (!roomId) {
157
- return new Response("Not found", {
158
- headers: { "Content-Type": "text/plain" },
159
- status: 404
160
- });
161
- }
162
- const namespace = getDurableObjectNamespace(env);
163
- const durableObjectId = namespace.idFromName(roomId);
164
- const room = namespace.get(durableObjectId);
165
- return room.fetch(request);
166
- });
167
- const handlerFetch = (request, env) => __async(void 0, null, function* () {
168
- return [authHandler, roomHandler].reduce((promise, current) => __async(void 0, null, function* () {
169
- return yield promise.then((value) => __async(void 0, null, function* () {
170
- return value != null ? value : yield current(request, env);
171
- }));
172
- }), Promise.resolve(null));
173
- });
174
- const handler = {
175
- fetch: (request, env) => __async(void 0, null, function* () {
176
- var _a, _b;
177
- const response = (_a = yield handlerFetch(request, env)) != null ? _a : new Response("Not Found", {
178
- headers: { "Content-Type": "text/plain" },
179
- status: 404
180
- });
181
- return (_b = modify == null ? void 0 : modify(request, response, env)) != null ? _b : response;
182
- })
183
- };
184
- return { fetch: handlerFetch, DurableObject, handler };
185
- };
186
-
187
- // src/infer.ts
188
- var infer = (callback) => callback;
189
-
190
- // src/CloudflarePlatform.ts
191
- var import_io2 = require("@pluv/io");
192
- var import_persistence_cloudflare_transactional_storage = require("@pluv/persistence-cloudflare-transactional-storage");
193
-
194
- // src/CloudflareWebSocket.ts
195
- var import_io = require("@pluv/io");
196
- var CloudflareWebSocket = class extends import_io.AbstractWebSocket {
197
- set presence(presence) {
198
- const deserialized = this.webSocket.deserializeAttachment();
199
- const state = deserialized.state;
200
- this.webSocket.serializeAttachment(__spreadProps(__spreadValues({}, this.webSocket.deserializeAttachment()), {
201
- state: __spreadProps(__spreadValues({}, state), { presence })
202
- }));
203
- }
204
- get readyState() {
205
- return this.webSocket.readyState;
206
- }
207
- get sessionId() {
208
- var _a, _b;
209
- const deserialized = (_a = this.webSocket.deserializeAttachment()) != null ? _a : {};
210
- const sessionId = (_b = deserialized.sessionId) != null ? _b : crypto.randomUUID();
211
- if (typeof deserialized.sessionId !== "string") {
212
- this.webSocket.serializeAttachment(__spreadProps(__spreadValues({}, deserialized), { sessionId }));
213
- }
214
- return sessionId;
215
- }
216
- get state() {
217
- var _a;
218
- const deserialized = this.webSocket.deserializeAttachment();
219
- const state = (_a = deserialized == null ? void 0 : deserialized.state) != null ? _a : null;
220
- if (!state) throw new Error("Could not get websocket state");
221
- const currentPing = state.timers.ping;
222
- const lastPing = this._platform.getLastPing(this);
223
- if (!lastPing) return state;
224
- if (currentPing >= lastPing) return state;
225
- const newState = __spreadProps(__spreadValues({}, state), {
226
- timers: __spreadProps(__spreadValues({}, state.timers), { ping: lastPing })
227
- });
228
- return this._platform.setSerializedState(this, newState);
229
- }
230
- set state(state) {
231
- const deserialized = this.webSocket.deserializeAttachment();
232
- this.webSocket.serializeAttachment(__spreadProps(__spreadValues({}, deserialized), { state }));
233
- }
234
- constructor(webSocket, config) {
235
- const { room } = config;
236
- super(webSocket, config);
237
- const state = {
238
- presence: null,
239
- quit: false,
240
- room,
241
- timers: { ping: (/* @__PURE__ */ new Date()).getTime() }
242
- };
243
- webSocket.serializeAttachment(__spreadValues({
244
- sessionId: this.sessionId,
245
- state
246
- }, webSocket.deserializeAttachment()));
247
- }
248
- addEventListener(type, handler) {
249
- this.webSocket.addEventListener(type, handler);
250
- }
251
- close(code, reason) {
252
- const canClose = [this.CONNECTING, this.OPEN].some((readyState) => readyState === this.readyState);
253
- if (!canClose) return;
254
- this.webSocket.close(code, reason);
255
- }
256
- send(message) {
257
- if (this.readyState !== this.OPEN) return;
258
- this.webSocket.send(message);
259
- }
260
- terminate(code = 1011) {
261
- return this.webSocket.close(code, "Terminated");
262
- }
263
- };
264
-
265
- // src/constants.ts
266
- var DEFAULT_REGISTRATION_MODE = "detached";
267
-
268
- // src/CloudflarePlatform.ts
269
- var CloudflarePlatform = class _CloudflarePlatform extends import_io2.AbstractPlatform {
270
- constructor(config) {
271
- var _a;
272
- super(__spreadValues(__spreadValues({}, config), config.roomContext && config.mode === "detached" ? { persistence: new import_persistence_cloudflare_transactional_storage.PersistenceCloudflareTransactionalStorage(config.roomContext) } : {}));
273
- this._name = "platformCloudflare";
274
- this._config = {
275
- authorize: {
276
- secret: true
277
- },
278
- handleMode: "io",
279
- registrationMode: (_a = config.mode) != null ? _a : DEFAULT_REGISTRATION_MODE,
280
- requireAuth: false,
281
- listeners: {
282
- onRoomDeleted: true,
283
- onRoomMessage: true,
284
- onStorageUpdated: true,
285
- onUserConnected: true,
286
- onUserDisconnected: true
287
- },
288
- router: true
289
- };
290
- const detachedState = this._getDetachedState();
291
- if (!detachedState) return;
292
- detachedState.setWebSocketAutoResponse(
293
- new WebSocketRequestResponsePair('{"type":"$ping","data":{}}', JSON.stringify({ type: "$pong", data: {} }))
294
- );
295
- }
296
- acceptWebSocket(webSocket) {
297
- return __async(this, null, function* () {
298
- const detachedState = this._getDetachedState();
299
- if (!detachedState) {
300
- webSocket.webSocket.accept();
301
- return;
302
- }
303
- detachedState.acceptWebSocket(webSocket.webSocket);
304
- });
305
- }
306
- convertWebSocket(webSocket, config) {
307
- const { room } = config;
308
- return new CloudflareWebSocket(webSocket, { persistence: this.persistence, platform: this, room });
309
- }
310
- getLastPing(webSocket) {
311
- var _a;
312
- const detachedState = this._getDetachedState();
313
- if (!detachedState) return null;
314
- const timestamp = detachedState.getWebSocketAutoResponseTimestamp(webSocket.webSocket);
315
- return (_a = timestamp == null ? void 0 : timestamp.getTime()) != null ? _a : null;
316
- }
317
- getSerializedState(webSocket) {
318
- var _a;
319
- const deserialized = webSocket.deserializeAttachment();
320
- return (_a = deserialized == null ? void 0 : deserialized.state) != null ? _a : null;
321
- }
322
- getSessionId(webSocket) {
323
- var _a;
324
- const deserialized = (_a = webSocket.deserializeAttachment()) != null ? _a : {};
325
- const sessionId = deserialized.sessionId;
326
- if (typeof sessionId !== "string") return null;
327
- return sessionId;
328
- }
329
- getWebSockets() {
330
- var _a;
331
- const detachedState = this._getDetachedState();
332
- if (!detachedState) return [];
333
- const webSockets = (_a = detachedState.getWebSockets()) != null ? _a : [];
334
- return webSockets;
335
- }
336
- initialize(config) {
337
- var _a;
338
- const roomContext = (_a = config.roomContext) != null ? _a : __spreadValues({}, this._roomContext);
339
- if (!roomContext.env || !roomContext.state) throw new Error("Could not derive platform roomContext");
340
- return new _CloudflarePlatform({
341
- roomContext: {
342
- env: roomContext.env,
343
- meta: roomContext.meta,
344
- state: roomContext.state
345
- },
346
- mode: this._config.registrationMode,
347
- persistence: this.persistence,
348
- pubSub: this.pubSub
349
- })._initialize();
350
- }
351
- parseData(data) {
352
- if (typeof data === "string") return JSON.parse(data);
353
- const decoder = new TextDecoder("utf8");
354
- return JSON.parse(decoder.decode(data));
355
- }
356
- randomUUID() {
357
- return crypto.randomUUID();
358
- }
359
- setSerializedState(webSocket, state) {
360
- var _a;
361
- const deserialized = (_a = webSocket.webSocket.deserializeAttachment()) != null ? _a : {};
362
- webSocket.webSocket.serializeAttachment(__spreadProps(__spreadValues({}, deserialized), { state }));
363
- return state;
364
- }
365
- _getDetachedState() {
366
- var _a, _b;
367
- if (this._config.registrationMode !== "detached") return null;
368
- const detachedState = (_b = (_a = this._roomContext) == null ? void 0 : _a.state) != null ? _b : null;
369
- return detachedState;
370
- }
371
- };
372
-
373
- // src/platformCloudflare.ts
374
- var platformCloudflare = (config = {}) => {
375
- const { authorize, context, crdt, debug } = config;
376
- return {
377
- authorize,
378
- context,
379
- crdt,
380
- debug,
381
- platform: new CloudflarePlatform(config)
382
- };
383
- };
384
- // Annotate the CommonJS export names for ESM import in node:
385
- 0 && (module.exports = {
386
- createPluvHandler,
387
- infer,
388
- platformCloudflare
389
- });