@pluv/platform-node 0.20.0 → 0.21.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,18 @@
1
1
 
2
- > @pluv/platform-node@0.20.0 build /home/runner/work/pluv/pluv/packages/platform-node
2
+ > @pluv/platform-node@0.21.1 build /home/runner/work/pluv/pluv/packages/platform-node
3
3
  > tsup src/index.ts --format esm,cjs --dts
4
4
 
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
- ESM dist/index.mjs 6.12 KB
12
- ESM ⚡️ Build success in 127ms
13
- CJS dist/index.js 7.93 KB
14
- CJS ⚡️ Build success in 128ms
15
- DTS Build start
16
- DTS ⚡️ Build success in 4198ms
17
- DTS dist/index.d.mts 2.92 KB
18
- DTS dist/index.d.ts 2.92 KB
5
+ CLI Building entry: src/index.ts
6
+ CLI Using tsconfig: tsconfig.json
7
+ CLI tsup v8.2.4
8
+ CLI Target: es6
9
+ ESM Build start
10
+ CJS Build start
11
+ ESM dist/index.mjs 7.58 KB
12
+ ESM ⚡️ Build success in 91ms
13
+ CJS dist/index.js 9.35 KB
14
+ CJS ⚡️ Build success in 92ms
15
+ DTS Build start
16
+ DTS ⚡️ Build success in 3454ms
17
+ DTS dist/index.d.mts 3.56 KB
18
+ DTS dist/index.d.ts 3.56 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,55 @@
1
1
  # @pluv/platform-node
2
2
 
3
+ ## 0.21.1
4
+
5
+ ### Patch Changes
6
+
7
+ - @pluv/io@0.21.1
8
+ - @pluv/types@0.21.1
9
+
10
+ ## 0.21.0
11
+
12
+ ### Minor Changes
13
+
14
+ - 41b15e4: **BREAKING** - Updated `sessions` type in the procedure context from `Map<string, WebSocketSession>` to `readonly WebSocketSession[]`.
15
+ - f570c8a: **BREAKING**: The original request object is no longer available in the context of any event resolvers.
16
+
17
+ Previously, the request object that was passed into `PluvServer.getRoom` would be made available on the context object of each of the resolvers. This is no-longer a part of the event context, and therefore needs to be omitted from calls to `PluvServer.getRoom`.
18
+
19
+ ```ts
20
+ // Before
21
+
22
+ // With platform-node
23
+ ioServer.getRoom(websocket, { req, token });
24
+
25
+ // With platform-cloudflare
26
+ ioServer.getRoom(websocket, { env, req, token });
27
+ ```
28
+
29
+ ```ts
30
+ // Now
31
+
32
+ // With platform-node
33
+ ioServer.getRoom(websocket, { req });
34
+
35
+ // With platform-cloudflare
36
+ ioServer.getRoom(websocket, { env, req });
37
+ ```
38
+
39
+ - b98ab6b: Internal updates to platforms (i.e. `@pluv/platform-cloudflare` and `@pluv/platform-node`) to be able to support Cloudflare Worker Websocket Hibernation APIs.
40
+
41
+ ### Patch Changes
42
+
43
+ - cc2613e: Moved `sessionId` from being derived in `IORoom` to being derived as a getter in `AbstractWebsocket`.
44
+ - Updated dependencies [307bd44]
45
+ - Updated dependencies [41b15e4]
46
+ - Updated dependencies [f570c8a]
47
+ - Updated dependencies [b98ab6b]
48
+ - Updated dependencies [4c2228d]
49
+ - Updated dependencies [cc2613e]
50
+ - @pluv/io@0.21.0
51
+ - @pluv/types@0.21.0
52
+
3
53
  ## 0.20.0
4
54
 
5
55
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,40 +1,50 @@
1
- import { AbstractWebSocket, AbstractEventMap, AbstractListener, AbstractWebSocketConfig, AbstractPersistance, AbstractPubSub, AbstractPlatform, ConvertWebSocketConfig, PluvServer } from '@pluv/io';
2
- import { MaybePromise, Maybe, InferIOAuthorizeUser, InferIOAuthorize, InferIOAuthorizeRequired } from '@pluv/types';
3
- import { IncomingMessage as IncomingMessage$1, ServerResponse, Server } from 'node:http';
1
+ import { AbstractWebSocket, WebSocketSerializedState, AbstractEventMap, AbstractListener, AbstractWebSocketConfig, WebSocketRegistrationMode, AbstractPersistance, AbstractPubSub, AbstractPlatform, ConvertWebSocketConfig, AbstractPlatformConfig, PluvServer } from '@pluv/io';
2
+ import { JsonObject, MaybePromise, Maybe, InferIOAuthorizeUser, InferIOAuthorize, InferIOAuthorizeRequired } from '@pluv/types';
3
+ import { IncomingMessage, ServerResponse, Server } from 'node:http';
4
4
  import { WebSocket, Server as Server$1 } from 'ws';
5
5
  export { WebSocket } from 'ws';
6
- import { IncomingMessage } from 'http';
7
6
 
8
7
  type NodeWebSocketConfig = AbstractWebSocketConfig;
9
- declare class NodeWebSocket extends AbstractWebSocket {
10
- webSocket: WebSocket;
8
+ declare class NodeWebSocket extends AbstractWebSocket<WebSocket> {
9
+ private _sessionId;
10
+ private _state;
11
+ set presence(presence: JsonObject | null);
11
12
  get readyState(): 0 | 1 | 2 | 3;
13
+ get sessionId(): string;
14
+ get state(): WebSocketSerializedState;
12
15
  constructor(webSocket: WebSocket, config: NodeWebSocketConfig);
13
16
  addEventListener<TType extends keyof AbstractEventMap>(type: TType, handler: AbstractListener<TType>): void;
14
17
  close(code?: number | undefined, reason?: string | undefined): void;
15
- initialize(): Promise<() => void>;
16
18
  send(message: string | ArrayBuffer | ArrayBufferView): void;
17
19
  terminate(): void;
18
20
  }
19
21
 
20
- type NodePlatformOptions = {
22
+ type NodePlatformConfig = {
23
+ mode?: WebSocketRegistrationMode;
24
+ } & ({
21
25
  persistance?: undefined;
22
26
  pubSub?: undefined;
23
27
  } | {
24
28
  persistance: AbstractPersistance;
25
29
  pubSub: AbstractPubSub;
26
- };
27
- declare class NodePlatform extends AbstractPlatform<WebSocket, {
28
- req: IncomingMessage;
29
- }> {
30
- constructor(options?: NodePlatformOptions);
30
+ });
31
+ declare class NodePlatform extends AbstractPlatform<NodeWebSocket> {
32
+ readonly _registrationMode: WebSocketRegistrationMode;
33
+ constructor(config?: NodePlatformConfig);
34
+ acceptWebSocket(webSocket: NodeWebSocket): Promise<void>;
31
35
  convertWebSocket(webSocket: WebSocket, config: ConvertWebSocketConfig): NodeWebSocket;
36
+ getLastPing(webSocket: NodeWebSocket): number | null;
37
+ getSerializedState(webSocket: NodeWebSocket): WebSocketSerializedState | null;
38
+ getSessionId(webSocket: WebSocket): string | null;
39
+ getWebSockets(): readonly WebSocket[];
40
+ initialize(config: AbstractPlatformConfig<{}, {}>): this;
32
41
  parseData(data: string | ArrayBuffer): Record<string, any>;
33
42
  randomUUID(): string;
43
+ setSerializedState(webSocket: NodeWebSocket, state: WebSocketSerializedState): void;
34
44
  }
35
45
 
36
46
  interface AuthorizeFunctionContext {
37
- req: IncomingMessage$1;
47
+ req: IncomingMessage;
38
48
  res: ServerResponse;
39
49
  roomId: string;
40
50
  }
@@ -48,11 +58,11 @@ type CreatePluvHandlerConfig<TPluvServer extends PluvServer<NodePlatform, any, a
48
58
  } : {
49
59
  authorize?: undefined;
50
60
  });
51
- type RequestHandler = (req: IncomingMessage$1, res: ServerResponse, next?: () => void) => void;
61
+ type RequestHandler = (req: IncomingMessage, res: ServerResponse, next?: () => void) => void;
52
62
  interface WebSocketHandlerResult {
53
63
  matched: boolean;
54
64
  }
55
- type WebSocketHandler = (ws: WebSocket, req: IncomingMessage$1) => Promise<WebSocketHandlerResult>;
65
+ type WebSocketHandler = (ws: WebSocket, req: IncomingMessage) => Promise<WebSocketHandlerResult>;
56
66
  interface CreatePluvHandlerResult {
57
67
  createWsServer: () => Server$1;
58
68
  handler: RequestHandler;
@@ -60,6 +70,6 @@ interface CreatePluvHandlerResult {
60
70
  }
61
71
  declare const createPluvHandler: <TPluvServer extends PluvServer<NodePlatform, any, any, any>>(config: CreatePluvHandlerConfig<TPluvServer>) => CreatePluvHandlerResult;
62
72
 
63
- declare const platformNode: (options?: NodePlatformOptions) => NodePlatform;
73
+ declare const platformNode: (config?: NodePlatformConfig) => NodePlatform;
64
74
 
65
- export { type AuthorizeFunction, type AuthorizeFunctionContext, type CreatePluvHandlerConfig, type NodePlatformOptions, createPluvHandler, platformNode };
75
+ export { type AuthorizeFunction, type AuthorizeFunctionContext, type CreatePluvHandlerConfig, type NodePlatformConfig, createPluvHandler, platformNode };
package/dist/index.d.ts CHANGED
@@ -1,40 +1,50 @@
1
- import { AbstractWebSocket, AbstractEventMap, AbstractListener, AbstractWebSocketConfig, AbstractPersistance, AbstractPubSub, AbstractPlatform, ConvertWebSocketConfig, PluvServer } from '@pluv/io';
2
- import { MaybePromise, Maybe, InferIOAuthorizeUser, InferIOAuthorize, InferIOAuthorizeRequired } from '@pluv/types';
3
- import { IncomingMessage as IncomingMessage$1, ServerResponse, Server } from 'node:http';
1
+ import { AbstractWebSocket, WebSocketSerializedState, AbstractEventMap, AbstractListener, AbstractWebSocketConfig, WebSocketRegistrationMode, AbstractPersistance, AbstractPubSub, AbstractPlatform, ConvertWebSocketConfig, AbstractPlatformConfig, PluvServer } from '@pluv/io';
2
+ import { JsonObject, MaybePromise, Maybe, InferIOAuthorizeUser, InferIOAuthorize, InferIOAuthorizeRequired } from '@pluv/types';
3
+ import { IncomingMessage, ServerResponse, Server } from 'node:http';
4
4
  import { WebSocket, Server as Server$1 } from 'ws';
5
5
  export { WebSocket } from 'ws';
6
- import { IncomingMessage } from 'http';
7
6
 
8
7
  type NodeWebSocketConfig = AbstractWebSocketConfig;
9
- declare class NodeWebSocket extends AbstractWebSocket {
10
- webSocket: WebSocket;
8
+ declare class NodeWebSocket extends AbstractWebSocket<WebSocket> {
9
+ private _sessionId;
10
+ private _state;
11
+ set presence(presence: JsonObject | null);
11
12
  get readyState(): 0 | 1 | 2 | 3;
13
+ get sessionId(): string;
14
+ get state(): WebSocketSerializedState;
12
15
  constructor(webSocket: WebSocket, config: NodeWebSocketConfig);
13
16
  addEventListener<TType extends keyof AbstractEventMap>(type: TType, handler: AbstractListener<TType>): void;
14
17
  close(code?: number | undefined, reason?: string | undefined): void;
15
- initialize(): Promise<() => void>;
16
18
  send(message: string | ArrayBuffer | ArrayBufferView): void;
17
19
  terminate(): void;
18
20
  }
19
21
 
20
- type NodePlatformOptions = {
22
+ type NodePlatformConfig = {
23
+ mode?: WebSocketRegistrationMode;
24
+ } & ({
21
25
  persistance?: undefined;
22
26
  pubSub?: undefined;
23
27
  } | {
24
28
  persistance: AbstractPersistance;
25
29
  pubSub: AbstractPubSub;
26
- };
27
- declare class NodePlatform extends AbstractPlatform<WebSocket, {
28
- req: IncomingMessage;
29
- }> {
30
- constructor(options?: NodePlatformOptions);
30
+ });
31
+ declare class NodePlatform extends AbstractPlatform<NodeWebSocket> {
32
+ readonly _registrationMode: WebSocketRegistrationMode;
33
+ constructor(config?: NodePlatformConfig);
34
+ acceptWebSocket(webSocket: NodeWebSocket): Promise<void>;
31
35
  convertWebSocket(webSocket: WebSocket, config: ConvertWebSocketConfig): NodeWebSocket;
36
+ getLastPing(webSocket: NodeWebSocket): number | null;
37
+ getSerializedState(webSocket: NodeWebSocket): WebSocketSerializedState | null;
38
+ getSessionId(webSocket: WebSocket): string | null;
39
+ getWebSockets(): readonly WebSocket[];
40
+ initialize(config: AbstractPlatformConfig<{}, {}>): this;
32
41
  parseData(data: string | ArrayBuffer): Record<string, any>;
33
42
  randomUUID(): string;
43
+ setSerializedState(webSocket: NodeWebSocket, state: WebSocketSerializedState): void;
34
44
  }
35
45
 
36
46
  interface AuthorizeFunctionContext {
37
- req: IncomingMessage$1;
47
+ req: IncomingMessage;
38
48
  res: ServerResponse;
39
49
  roomId: string;
40
50
  }
@@ -48,11 +58,11 @@ type CreatePluvHandlerConfig<TPluvServer extends PluvServer<NodePlatform, any, a
48
58
  } : {
49
59
  authorize?: undefined;
50
60
  });
51
- type RequestHandler = (req: IncomingMessage$1, res: ServerResponse, next?: () => void) => void;
61
+ type RequestHandler = (req: IncomingMessage, res: ServerResponse, next?: () => void) => void;
52
62
  interface WebSocketHandlerResult {
53
63
  matched: boolean;
54
64
  }
55
- type WebSocketHandler = (ws: WebSocket, req: IncomingMessage$1) => Promise<WebSocketHandlerResult>;
65
+ type WebSocketHandler = (ws: WebSocket, req: IncomingMessage) => Promise<WebSocketHandlerResult>;
56
66
  interface CreatePluvHandlerResult {
57
67
  createWsServer: () => Server$1;
58
68
  handler: RequestHandler;
@@ -60,6 +70,6 @@ interface CreatePluvHandlerResult {
60
70
  }
61
71
  declare const createPluvHandler: <TPluvServer extends PluvServer<NodePlatform, any, any, any>>(config: CreatePluvHandlerConfig<TPluvServer>) => CreatePluvHandlerResult;
62
72
 
63
- declare const platformNode: (options?: NodePlatformOptions) => NodePlatform;
73
+ declare const platformNode: (config?: NodePlatformConfig) => NodePlatform;
64
74
 
65
- export { type AuthorizeFunction, type AuthorizeFunctionContext, type CreatePluvHandlerConfig, type NodePlatformOptions, createPluvHandler, platformNode };
75
+ export { type AuthorizeFunction, type AuthorizeFunctionContext, type CreatePluvHandlerConfig, type NodePlatformConfig, createPluvHandler, platformNode };
package/dist/index.js CHANGED
@@ -3,8 +3,22 @@ var __create = Object.create;
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
7
  var __getProtoOf = Object.getPrototypeOf;
7
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
+ };
8
22
  var __export = (target, all) => {
9
23
  for (var name in all)
10
24
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -75,6 +89,9 @@ var handle = (ws) => ({
75
89
  });
76
90
  var createPluvHandler = (config) => {
77
91
  const { authorize, endpoint = "/api/pluv", io, server } = config;
92
+ if (io._registrationMode === "detached") {
93
+ throw new Error("Cannot use createPluvHandler in detached mode for Node.js");
94
+ }
78
95
  const wsServer = new import_ws.Server({ server });
79
96
  const wsHandler = (ws, req) => __async(void 0, null, function* () {
80
97
  var _a;
@@ -94,8 +111,8 @@ var createPluvHandler = (config) => {
94
111
  if (!roomId) return onError.invalidRoom();
95
112
  const token = ((_a = parsed.query) == null ? void 0 : _a.token) || void 0;
96
113
  if (Array.isArray(token)) return onError.invalidToken();
97
- const room = io.getRoom(roomId, { req });
98
- yield room.register(ws, { req, token });
114
+ const room = io.getRoom(roomId);
115
+ yield room.register(ws, { token });
99
116
  return { matched: true };
100
117
  });
101
118
  const createWsServer = () => {
@@ -123,11 +140,7 @@ var createPluvHandler = (config) => {
123
140
  try {
124
141
  const user = yield authorize({ res, req, roomId });
125
142
  if (!user) throw new Error();
126
- const token = yield io.createToken({
127
- req,
128
- room: roomId,
129
- user
130
- });
143
+ const token = yield io.createToken({ room: roomId, user });
131
144
  res.writeHead(200, { "Content-Type": "text/plain" });
132
145
  return res.end(token);
133
146
  } catch (err) {
@@ -144,49 +157,53 @@ var createPluvHandler = (config) => {
144
157
 
145
158
  // src/NodePlatform.ts
146
159
  var import_io2 = require("@pluv/io");
147
- var import_crypto = __toESM(require("crypto"));
148
- var import_util = require("util");
160
+ var import_node_crypto2 = __toESM(require("crypto"));
161
+ var import_node_util = require("util");
149
162
 
150
163
  // src/NodeWebSocket.ts
151
164
  var import_io = require("@pluv/io");
165
+ var import_node_crypto = __toESM(require("crypto"));
152
166
  var NodeWebSocket = class extends import_io.AbstractWebSocket {
167
+ set presence(presence) {
168
+ this._state.presence = presence;
169
+ }
153
170
  get readyState() {
154
171
  return this.webSocket.readyState;
155
172
  }
173
+ get sessionId() {
174
+ return this._sessionId;
175
+ }
176
+ get state() {
177
+ return this._state;
178
+ }
156
179
  constructor(webSocket, config) {
157
- const { room, sessionId, userId } = config;
158
- super({ room, sessionId, userId });
159
- this.webSocket = webSocket;
180
+ const { room } = config;
181
+ super(webSocket, config);
182
+ this._sessionId = import_node_crypto.default.randomUUID();
183
+ this._state = {
184
+ presence: null,
185
+ quit: false,
186
+ room,
187
+ timers: { ping: (/* @__PURE__ */ new Date()).getTime() }
188
+ };
160
189
  }
161
190
  addEventListener(type, handler) {
162
191
  switch (type) {
163
192
  case "close":
164
- this.webSocket.on("close", (code, reason) => __async(this, null, function* () {
165
- yield Promise.resolve(
166
- handler({
167
- code,
168
- reason: reason.toString("utf-8")
169
- })
170
- );
193
+ this.webSocket.on("close", (code, buffer) => __async(this, null, function* () {
194
+ const reason = buffer.toString("utf-8");
195
+ yield Promise.resolve(handler({ code, reason }));
171
196
  }));
172
197
  return;
173
198
  case "error":
174
199
  this.webSocket.on("error", (error) => __async(this, null, function* () {
175
- yield Promise.resolve(
176
- handler({
177
- error,
178
- message: error.message
179
- })
180
- );
200
+ const message = error.message;
201
+ yield Promise.resolve(handler({ error, message }));
181
202
  }));
182
203
  return;
183
204
  case "message":
184
205
  this.webSocket.on("message", (data) => __async(this, null, function* () {
185
- yield Promise.resolve(
186
- handler({
187
- data
188
- })
189
- );
206
+ yield Promise.resolve(handler({ data }));
190
207
  }));
191
208
  return;
192
209
  default:
@@ -197,11 +214,6 @@ var NodeWebSocket = class extends import_io.AbstractWebSocket {
197
214
  if (!canClose) return;
198
215
  this.webSocket.close(code, reason);
199
216
  }
200
- initialize() {
201
- return __async(this, null, function* () {
202
- return Promise.resolve(() => void 0);
203
- });
204
- }
205
217
  send(message) {
206
218
  if (this.readyState !== this.OPEN) return;
207
219
  this.webSocket.send(message, (error) => {
@@ -214,27 +226,54 @@ var NodeWebSocket = class extends import_io.AbstractWebSocket {
214
226
  };
215
227
 
216
228
  // src/NodePlatform.ts
217
- var NodePlatform = class extends import_io2.AbstractPlatform {
218
- constructor(options = {}) {
219
- const { persistance, pubSub } = options;
229
+ var NodePlatform = class _NodePlatform extends import_io2.AbstractPlatform {
230
+ constructor(config = {}) {
231
+ const { mode = "attached", persistance, pubSub } = config;
220
232
  super(persistance && pubSub ? { persistance, pubSub } : {});
233
+ this._registrationMode = mode;
234
+ }
235
+ acceptWebSocket(webSocket) {
236
+ return Promise.resolve(void 0);
221
237
  }
222
238
  convertWebSocket(webSocket, config) {
223
- return new NodeWebSocket(webSocket, config);
239
+ const { room } = config;
240
+ return new NodeWebSocket(webSocket, { persistance: this.persistance, room });
241
+ }
242
+ getLastPing(webSocket) {
243
+ return null;
244
+ }
245
+ getSerializedState(webSocket) {
246
+ return null;
247
+ }
248
+ getSessionId(webSocket) {
249
+ return null;
250
+ }
251
+ getWebSockets() {
252
+ return [];
253
+ }
254
+ initialize(config) {
255
+ return new _NodePlatform(__spreadValues({
256
+ mode: this._registrationMode,
257
+ persistance: this.persistance,
258
+ pubSub: this.pubSub
259
+ }, config))._initialize();
224
260
  }
225
261
  parseData(data) {
226
262
  if (typeof data === "string") return JSON.parse(data);
227
- const decoder = new import_util.TextDecoder("utf8");
263
+ const decoder = new import_node_util.TextDecoder("utf8");
228
264
  return JSON.parse(decoder.decode(data));
229
265
  }
230
266
  randomUUID() {
231
- return import_crypto.default.randomUUID();
267
+ return import_node_crypto2.default.randomUUID();
268
+ }
269
+ setSerializedState(webSocket, state) {
270
+ return;
232
271
  }
233
272
  };
234
273
 
235
274
  // src/platformNode.ts
236
- var platformNode = (options = {}) => {
237
- return new NodePlatform(options);
275
+ var platformNode = (config = {}) => {
276
+ return new NodePlatform(config);
238
277
  };
239
278
  // Annotate the CommonJS export names for ESM import in node:
240
279
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -1,3 +1,19 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __spreadValues = (a, b) => {
7
+ for (var prop in b || (b = {}))
8
+ if (__hasOwnProp.call(b, prop))
9
+ __defNormalProp(a, prop, b[prop]);
10
+ if (__getOwnPropSymbols)
11
+ for (var prop of __getOwnPropSymbols(b)) {
12
+ if (__propIsEnum.call(b, prop))
13
+ __defNormalProp(a, prop, b[prop]);
14
+ }
15
+ return a;
16
+ };
1
17
  var __async = (__this, __arguments, generator) => {
2
18
  return new Promise((resolve, reject) => {
3
19
  var fulfilled = (value) => {
@@ -39,6 +55,9 @@ var handle = (ws) => ({
39
55
  });
40
56
  var createPluvHandler = (config) => {
41
57
  const { authorize, endpoint = "/api/pluv", io, server } = config;
58
+ if (io._registrationMode === "detached") {
59
+ throw new Error("Cannot use createPluvHandler in detached mode for Node.js");
60
+ }
42
61
  const wsServer = new WsServer({ server });
43
62
  const wsHandler = (ws, req) => __async(void 0, null, function* () {
44
63
  var _a;
@@ -58,8 +77,8 @@ var createPluvHandler = (config) => {
58
77
  if (!roomId) return onError.invalidRoom();
59
78
  const token = ((_a = parsed.query) == null ? void 0 : _a.token) || void 0;
60
79
  if (Array.isArray(token)) return onError.invalidToken();
61
- const room = io.getRoom(roomId, { req });
62
- yield room.register(ws, { req, token });
80
+ const room = io.getRoom(roomId);
81
+ yield room.register(ws, { token });
63
82
  return { matched: true };
64
83
  });
65
84
  const createWsServer = () => {
@@ -87,11 +106,7 @@ var createPluvHandler = (config) => {
87
106
  try {
88
107
  const user = yield authorize({ res, req, roomId });
89
108
  if (!user) throw new Error();
90
- const token = yield io.createToken({
91
- req,
92
- room: roomId,
93
- user
94
- });
109
+ const token = yield io.createToken({ room: roomId, user });
95
110
  res.writeHead(200, { "Content-Type": "text/plain" });
96
111
  return res.end(token);
97
112
  } catch (err) {
@@ -108,49 +123,53 @@ var createPluvHandler = (config) => {
108
123
 
109
124
  // src/NodePlatform.ts
110
125
  import { AbstractPlatform } from "@pluv/io";
111
- import crypto from "crypto";
126
+ import crypto2 from "crypto";
112
127
  import { TextDecoder } from "util";
113
128
 
114
129
  // src/NodeWebSocket.ts
115
130
  import { AbstractWebSocket } from "@pluv/io";
131
+ import crypto from "crypto";
116
132
  var NodeWebSocket = class extends AbstractWebSocket {
133
+ set presence(presence) {
134
+ this._state.presence = presence;
135
+ }
117
136
  get readyState() {
118
137
  return this.webSocket.readyState;
119
138
  }
139
+ get sessionId() {
140
+ return this._sessionId;
141
+ }
142
+ get state() {
143
+ return this._state;
144
+ }
120
145
  constructor(webSocket, config) {
121
- const { room, sessionId, userId } = config;
122
- super({ room, sessionId, userId });
123
- this.webSocket = webSocket;
146
+ const { room } = config;
147
+ super(webSocket, config);
148
+ this._sessionId = crypto.randomUUID();
149
+ this._state = {
150
+ presence: null,
151
+ quit: false,
152
+ room,
153
+ timers: { ping: (/* @__PURE__ */ new Date()).getTime() }
154
+ };
124
155
  }
125
156
  addEventListener(type, handler) {
126
157
  switch (type) {
127
158
  case "close":
128
- this.webSocket.on("close", (code, reason) => __async(this, null, function* () {
129
- yield Promise.resolve(
130
- handler({
131
- code,
132
- reason: reason.toString("utf-8")
133
- })
134
- );
159
+ this.webSocket.on("close", (code, buffer) => __async(this, null, function* () {
160
+ const reason = buffer.toString("utf-8");
161
+ yield Promise.resolve(handler({ code, reason }));
135
162
  }));
136
163
  return;
137
164
  case "error":
138
165
  this.webSocket.on("error", (error) => __async(this, null, function* () {
139
- yield Promise.resolve(
140
- handler({
141
- error,
142
- message: error.message
143
- })
144
- );
166
+ const message = error.message;
167
+ yield Promise.resolve(handler({ error, message }));
145
168
  }));
146
169
  return;
147
170
  case "message":
148
171
  this.webSocket.on("message", (data) => __async(this, null, function* () {
149
- yield Promise.resolve(
150
- handler({
151
- data
152
- })
153
- );
172
+ yield Promise.resolve(handler({ data }));
154
173
  }));
155
174
  return;
156
175
  default:
@@ -161,11 +180,6 @@ var NodeWebSocket = class extends AbstractWebSocket {
161
180
  if (!canClose) return;
162
181
  this.webSocket.close(code, reason);
163
182
  }
164
- initialize() {
165
- return __async(this, null, function* () {
166
- return Promise.resolve(() => void 0);
167
- });
168
- }
169
183
  send(message) {
170
184
  if (this.readyState !== this.OPEN) return;
171
185
  this.webSocket.send(message, (error) => {
@@ -178,13 +192,37 @@ var NodeWebSocket = class extends AbstractWebSocket {
178
192
  };
179
193
 
180
194
  // src/NodePlatform.ts
181
- var NodePlatform = class extends AbstractPlatform {
182
- constructor(options = {}) {
183
- const { persistance, pubSub } = options;
195
+ var NodePlatform = class _NodePlatform extends AbstractPlatform {
196
+ constructor(config = {}) {
197
+ const { mode = "attached", persistance, pubSub } = config;
184
198
  super(persistance && pubSub ? { persistance, pubSub } : {});
199
+ this._registrationMode = mode;
200
+ }
201
+ acceptWebSocket(webSocket) {
202
+ return Promise.resolve(void 0);
185
203
  }
186
204
  convertWebSocket(webSocket, config) {
187
- return new NodeWebSocket(webSocket, config);
205
+ const { room } = config;
206
+ return new NodeWebSocket(webSocket, { persistance: this.persistance, room });
207
+ }
208
+ getLastPing(webSocket) {
209
+ return null;
210
+ }
211
+ getSerializedState(webSocket) {
212
+ return null;
213
+ }
214
+ getSessionId(webSocket) {
215
+ return null;
216
+ }
217
+ getWebSockets() {
218
+ return [];
219
+ }
220
+ initialize(config) {
221
+ return new _NodePlatform(__spreadValues({
222
+ mode: this._registrationMode,
223
+ persistance: this.persistance,
224
+ pubSub: this.pubSub
225
+ }, config))._initialize();
188
226
  }
189
227
  parseData(data) {
190
228
  if (typeof data === "string") return JSON.parse(data);
@@ -192,13 +230,16 @@ var NodePlatform = class extends AbstractPlatform {
192
230
  return JSON.parse(decoder.decode(data));
193
231
  }
194
232
  randomUUID() {
195
- return crypto.randomUUID();
233
+ return crypto2.randomUUID();
234
+ }
235
+ setSerializedState(webSocket, state) {
236
+ return;
196
237
  }
197
238
  };
198
239
 
199
240
  // src/platformNode.ts
200
- var platformNode = (options = {}) => {
201
- return new NodePlatform(options);
241
+ var platformNode = (config = {}) => {
242
+ return new NodePlatform(config);
202
243
  };
203
244
  export {
204
245
  createPluvHandler,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluv/platform-node",
3
- "version": "0.20.0",
3
+ "version": "0.21.1",
4
4
  "description": "@pluv/io adapter for node.js",
5
5
  "author": "leedavidcs",
6
6
  "license": "MIT",
@@ -17,19 +17,19 @@
17
17
  "access": "public"
18
18
  },
19
19
  "dependencies": {
20
- "@types/node": "^20.14.9",
21
- "@types/ws": "^8.5.10",
22
- "path-to-regexp": "^7.0.0",
23
- "@pluv/io": "^0.20.0",
24
- "@pluv/types": "^0.20.0"
20
+ "@types/node": "^22.2.0",
21
+ "@types/ws": "^8.5.12",
22
+ "path-to-regexp": "^7.1.0",
23
+ "@pluv/io": "^0.21.1",
24
+ "@pluv/types": "^0.21.1"
25
25
  },
26
26
  "devDependencies": {
27
27
  "eslint": "^8.57.0",
28
- "tsup": "^8.1.0",
29
- "typescript": "^5.4.5",
28
+ "tsup": "^8.2.4",
29
+ "typescript": "^5.5.4",
30
30
  "ws": "^8.18.0",
31
- "@pluv/tsconfig": "^0.20.0",
32
- "eslint-config-pluv": "^0.20.0"
31
+ "@pluv/tsconfig": "^0.21.1",
32
+ "eslint-config-pluv": "^0.21.1"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "ws": "^8.0.0"
@@ -1,27 +1,66 @@
1
- import type { AbstractPersistance, ConvertWebSocketConfig } from "@pluv/io";
2
- import { AbstractPlatform, AbstractPubSub } from "@pluv/io";
3
- import crypto from "crypto";
4
- import { IncomingMessage } from "http";
5
- import { TextDecoder } from "util";
1
+ import type {
2
+ AbstractPersistance,
3
+ AbstractPlatformConfig,
4
+ AbstractPubSub,
5
+ ConvertWebSocketConfig,
6
+ WebSocketRegistrationMode,
7
+ WebSocketSerializedState,
8
+ } from "@pluv/io";
9
+ import { AbstractPlatform } from "@pluv/io";
10
+ import crypto from "node:crypto";
11
+ import { TextDecoder } from "node:util";
6
12
  import type { WebSocket } from "ws";
7
13
  import { NodeWebSocket } from "./NodeWebSocket";
8
14
 
9
- export type NodePlatformOptions =
15
+ export type NodePlatformConfig = { mode?: WebSocketRegistrationMode } & (
10
16
  | { persistance?: undefined; pubSub?: undefined }
11
- | {
12
- persistance: AbstractPersistance;
13
- pubSub: AbstractPubSub;
14
- };
17
+ | { persistance: AbstractPersistance; pubSub: AbstractPubSub }
18
+ );
15
19
 
16
- export class NodePlatform extends AbstractPlatform<WebSocket, { req: IncomingMessage }> {
17
- constructor(options: NodePlatformOptions = {}) {
18
- const { persistance, pubSub } = options;
20
+ export class NodePlatform extends AbstractPlatform<NodeWebSocket> {
21
+ readonly _registrationMode: WebSocketRegistrationMode;
22
+
23
+ constructor(config: NodePlatformConfig = {}) {
24
+ const { mode = "attached", persistance, pubSub } = config;
19
25
 
20
26
  super(persistance && pubSub ? { persistance, pubSub } : {});
27
+
28
+ this._registrationMode = mode;
29
+ }
30
+
31
+ public acceptWebSocket(webSocket: NodeWebSocket): Promise<void> {
32
+ return Promise.resolve(undefined);
21
33
  }
22
34
 
23
35
  public convertWebSocket(webSocket: WebSocket, config: ConvertWebSocketConfig): NodeWebSocket {
24
- return new NodeWebSocket(webSocket, config);
36
+ const { room } = config;
37
+
38
+ return new NodeWebSocket(webSocket, { persistance: this.persistance, room });
39
+ }
40
+
41
+ public getLastPing(webSocket: NodeWebSocket): number | null {
42
+ return null;
43
+ }
44
+
45
+ public getSerializedState(webSocket: NodeWebSocket): WebSocketSerializedState | null {
46
+ return null;
47
+ }
48
+
49
+ public getSessionId(webSocket: WebSocket): string | null {
50
+ return null;
51
+ }
52
+
53
+ public getWebSockets(): readonly WebSocket[] {
54
+ return [];
55
+ }
56
+
57
+ public initialize(config: AbstractPlatformConfig<{}, {}>): this {
58
+ return new NodePlatform({
59
+ mode: this._registrationMode,
60
+ persistance: this.persistance,
61
+ pubSub: this.pubSub,
62
+ ...config,
63
+ } as NodePlatformConfig)._initialize() as this;
25
64
  }
26
65
 
27
66
  public parseData(data: string | ArrayBuffer): Record<string, any> {
@@ -35,4 +74,8 @@ export class NodePlatform extends AbstractPlatform<WebSocket, { req: IncomingMes
35
74
  public randomUUID(): string {
36
75
  return crypto.randomUUID();
37
76
  }
77
+
78
+ public setSerializedState(webSocket: NodeWebSocket, state: WebSocketSerializedState): void {
79
+ return;
80
+ }
38
81
  }
@@ -5,8 +5,11 @@ import type {
5
5
  AbstractListener,
6
6
  AbstractMessageEvent,
7
7
  AbstractWebSocketConfig,
8
+ WebSocketSerializedState,
8
9
  } from "@pluv/io";
9
10
  import { AbstractWebSocket } from "@pluv/io";
11
+ import type { JsonObject } from "@pluv/types";
12
+ import crypto from "node:crypto";
10
13
  import type { WebSocket } from "ws";
11
14
 
12
15
  export interface NodeWebSocketEventMap {
@@ -17,52 +20,61 @@ export interface NodeWebSocketEventMap {
17
20
 
18
21
  export type NodeWebSocketConfig = AbstractWebSocketConfig;
19
22
 
20
- export class NodeWebSocket extends AbstractWebSocket {
21
- public webSocket: WebSocket;
23
+ export class NodeWebSocket extends AbstractWebSocket<WebSocket> {
24
+ private _sessionId: string;
25
+ private _state: WebSocketSerializedState;
26
+
27
+ public set presence(presence: JsonObject | null) {
28
+ this._state.presence = presence;
29
+ }
22
30
 
23
31
  public get readyState(): 0 | 1 | 2 | 3 {
24
32
  return this.webSocket.readyState;
25
33
  }
26
34
 
35
+ public get sessionId(): string {
36
+ return this._sessionId;
37
+ }
38
+
39
+ public get state(): WebSocketSerializedState {
40
+ return this._state;
41
+ }
42
+
27
43
  constructor(webSocket: WebSocket, config: NodeWebSocketConfig) {
28
- const { room, sessionId, userId } = config;
44
+ const { room } = config;
29
45
 
30
- super({ room, sessionId, userId });
46
+ super(webSocket, config);
31
47
 
32
- this.webSocket = webSocket;
48
+ this._sessionId = crypto.randomUUID();
49
+ this._state = {
50
+ presence: null,
51
+ quit: false,
52
+ room,
53
+ timers: { ping: new Date().getTime() },
54
+ };
33
55
  }
34
56
 
35
57
  public addEventListener<TType extends keyof AbstractEventMap>(type: TType, handler: AbstractListener<TType>): void {
36
58
  switch (type) {
37
59
  case "close":
38
- this.webSocket.on("close", async (code, reason) => {
39
- await Promise.resolve(
40
- (handler as AbstractListener<"close">)({
41
- code,
42
- reason: reason.toString("utf-8"),
43
- }),
44
- );
60
+ this.webSocket.on("close", async (code, buffer) => {
61
+ const reason = buffer.toString("utf-8");
62
+
63
+ await Promise.resolve((handler as AbstractListener<"close">)({ code, reason }));
45
64
  });
46
65
 
47
66
  return;
48
67
  case "error":
49
68
  this.webSocket.on("error", async (error) => {
50
- await Promise.resolve(
51
- (handler as AbstractListener<"error">)({
52
- error,
53
- message: error.message,
54
- }),
55
- );
69
+ const message = error.message;
70
+
71
+ await Promise.resolve((handler as AbstractListener<"error">)({ error, message }));
56
72
  });
57
73
 
58
74
  return;
59
75
  case "message":
60
76
  this.webSocket.on("message", async (data) => {
61
- await Promise.resolve(
62
- (handler as AbstractListener<"message">)({
63
- data,
64
- }),
65
- );
77
+ await Promise.resolve((handler as AbstractListener<"message">)({ data }));
66
78
  });
67
79
 
68
80
  return;
@@ -78,10 +90,6 @@ export class NodeWebSocket extends AbstractWebSocket {
78
90
  this.webSocket.close(code, reason);
79
91
  }
80
92
 
81
- public async initialize(): Promise<() => void> {
82
- return Promise.resolve(() => undefined);
83
- }
84
-
85
93
  public send(message: string | ArrayBuffer | ArrayBufferView): void {
86
94
  if (this.readyState !== this.OPEN) return;
87
95
 
@@ -67,6 +67,10 @@ export const createPluvHandler = <TPluvServer extends PluvServer<NodePlatform, a
67
67
  ): CreatePluvHandlerResult => {
68
68
  const { authorize, endpoint = "/api/pluv", io, server } = config;
69
69
 
70
+ if (io._registrationMode === "detached") {
71
+ throw new Error("Cannot use createPluvHandler in detached mode for Node.js");
72
+ }
73
+
70
74
  const wsServer = new WsServer({ server });
71
75
 
72
76
  const wsHandler = async (ws: WebSocket, req: IncomingMessage): Promise<WebSocketHandlerResult> => {
@@ -97,9 +101,9 @@ export const createPluvHandler = <TPluvServer extends PluvServer<NodePlatform, a
97
101
 
98
102
  if (Array.isArray(token)) return onError.invalidToken();
99
103
 
100
- const room = io.getRoom(roomId, { req });
104
+ const room = io.getRoom(roomId);
101
105
 
102
- await room.register(ws, { req, token });
106
+ await room.register(ws, { token });
103
107
 
104
108
  return { matched: true };
105
109
  };
@@ -144,11 +148,7 @@ export const createPluvHandler = <TPluvServer extends PluvServer<NodePlatform, a
144
148
 
145
149
  if (!user) throw new Error();
146
150
 
147
- const token = await io.createToken({
148
- req,
149
- room: roomId,
150
- user,
151
- });
151
+ const token = await io.createToken({ room: roomId, user });
152
152
 
153
153
  res.writeHead(200, { "Content-Type": "text/plain" });
154
154
  return res.end(token);
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export type { AuthorizeFunction, AuthorizeFunctionContext, CreatePluvHandlerConfig } from "./createPluvHandler";
2
2
  export { createPluvHandler } from "./createPluvHandler";
3
3
  export type { WebSocket } from "ws";
4
- export type { NodePlatformOptions } from "./NodePlatform";
4
+ export type { NodePlatformConfig } from "./NodePlatform";
5
5
  export { platformNode } from "./platformNode";
@@ -1,6 +1,6 @@
1
- import type { NodePlatformOptions } from "./NodePlatform";
1
+ import type { NodePlatformConfig } from "./NodePlatform";
2
2
  import { NodePlatform } from "./NodePlatform";
3
3
 
4
- export const platformNode = (options: NodePlatformOptions = {}): NodePlatform => {
5
- return new NodePlatform(options);
4
+ export const platformNode = (config: NodePlatformConfig = {}): NodePlatform => {
5
+ return new NodePlatform(config);
6
6
  };