@pluv/platform-pluv 0.38.3 → 0.38.5

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-pluv@0.38.3 build /home/runner/work/pluv/pluv/packages/platform-pluv
2
+ > @pluv/platform-pluv@0.38.5 build /home/runner/work/pluv/pluv/packages/platform-pluv
3
3
  > tsup src/index.ts --format esm,cjs --dts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -8,11 +8,11 @@
8
8
  CLI Target: es6
9
9
  ESM Build start
10
10
  CJS Build start
11
- ESM dist/index.mjs 9.86 KB
12
- ESM ⚡️ Build success in 80ms
13
- CJS dist/index.js 11.40 KB
14
- CJS ⚡️ Build success in 88ms
11
+ CJS dist/index.js 11.86 KB
12
+ CJS ⚡️ Build success in 84ms
13
+ ESM dist/index.mjs 10.32 KB
14
+ ESM ⚡️ Build success in 85ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 6145ms
17
- DTS dist/index.d.mts 3.56 KB
18
- DTS dist/index.d.ts 3.56 KB
16
+ DTS ⚡️ Build success in 6199ms
17
+ DTS dist/index.d.mts 3.43 KB
18
+ DTS dist/index.d.ts 3.43 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @pluv/platform-pluv
2
2
 
3
+ ## 0.38.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 77df696: Fixed platform event contexts being undefined.
8
+ - @pluv/crdt@0.38.5
9
+ - @pluv/io@0.38.5
10
+ - @pluv/types@0.38.5
11
+
12
+ ## 0.38.4
13
+
14
+ ### Patch Changes
15
+
16
+ - 15399b7: Fix webhook signature validation.
17
+ - @pluv/crdt@0.38.4
18
+ - @pluv/io@0.38.4
19
+ - @pluv/types@0.38.4
20
+
3
21
  ## 0.38.3
4
22
 
5
23
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,25 +1,11 @@
1
- import { AbstractPlatform, JWTEncodeParams, AbstractWebSocket, ConvertWebSocketConfig, WebSocketSerializedState, AbstractPlatformConfig, CreateIOParams, PluvIOAuthorize, InferInitContextType, PluvContext } from '@pluv/io';
2
- import { BaseUser, Id } from '@pluv/types';
1
+ import { BaseUser, AbstractPlatform, JWTEncodeParams, AbstractWebSocket, ConvertWebSocketConfig, WebSocketSerializedState, AbstractPlatformConfig, CreateIOParams, PluvIOAuthorize, InferInitContextType, PluvContext } from '@pluv/io';
2
+ import { BaseUser as BaseUser$1, Id } from '@pluv/types';
3
3
 
4
4
  interface PluvIOEndpoints {
5
5
  createToken: string;
6
6
  }
7
- type RoomDeletedMessageEventData = {
8
- encodedState: string | null;
9
- room: string;
10
- };
11
- type UserConnectedEventData = {
12
- encodedState: string | null;
13
- room: string;
14
- user: any;
15
- };
16
- type UserDisconnectedEventData = {
17
- encodedState: string | null;
18
- room: string;
19
- user: any;
20
- };
21
7
 
22
- interface PluvPlatformConfig {
8
+ interface PluvPlatformConfig<TContext extends Record<string, any> = {}> {
23
9
  /**
24
10
  * @ignore
25
11
  * @readonly
@@ -29,11 +15,12 @@ interface PluvPlatformConfig {
29
15
  endpoints?: PluvIOEndpoints;
30
16
  };
31
17
  basePath: string;
18
+ context?: TContext;
32
19
  publicKey: string;
33
20
  secretKey: string;
34
21
  webhookSecret?: string;
35
22
  }
36
- declare class PluvPlatform extends AbstractPlatform<any, {}, {}, {
23
+ declare class PluvPlatform<TContext extends Record<string, any> = {}, TUser extends BaseUser = BaseUser> extends AbstractPlatform<any, {}, {}, {
37
24
  authorize: {
38
25
  secret: false;
39
26
  };
@@ -66,8 +53,10 @@ declare class PluvPlatform extends AbstractPlatform<any, {}, {}, {
66
53
  router: false;
67
54
  };
68
55
  readonly _name = "platformPluv";
56
+ private readonly _app;
69
57
  private _authorize;
70
58
  private readonly _basePath;
59
+ private readonly _context;
71
60
  private readonly _endpoints;
72
61
  private _getInitialStorage?;
73
62
  private _listeners?;
@@ -87,13 +76,13 @@ declare class PluvPlatform extends AbstractPlatform<any, {}, {}, {
87
76
  randomUUID(): string;
88
77
  setSerializedState(webSocket: AbstractWebSocket, state: WebSocketSerializedState): WebSocketSerializedState;
89
78
  validateConfig(config: any): void;
90
- private _webhooks;
79
+ private _webhooksRouter;
91
80
  }
92
81
 
93
- type PlatformPluvCreateIOParams<TContext extends Record<string, any> = {}, TUser extends BaseUser = BaseUser> = Id<PluvPlatformConfig & Omit<CreateIOParams<PluvPlatform, TContext, TUser>, "authorize" | "context" | "platform"> & {
82
+ type PlatformPluvCreateIOParams<TContext extends Record<string, any> = {}, TUser extends BaseUser$1 = BaseUser$1> = Id<PluvPlatformConfig & Omit<CreateIOParams<PluvPlatform, TContext, TUser>, "authorize" | "context" | "platform"> & {
94
83
  authorize: PluvIOAuthorize<PluvPlatform, TUser, InferInitContextType<PluvPlatform>>;
95
84
  context?: PluvContext<PluvPlatform, TContext>;
96
85
  }>;
97
- declare const platformPluv: <TContext extends Record<string, any> = {}, TUser extends BaseUser = BaseUser>(config: PlatformPluvCreateIOParams<TContext, TUser>) => CreateIOParams<PluvPlatform, TContext, TUser>;
86
+ declare const platformPluv: <TContext extends Record<string, any> = {}, TUser extends BaseUser$1 = BaseUser$1>(config: PlatformPluvCreateIOParams<TContext, TUser>) => CreateIOParams<PluvPlatform<TContext, TUser>, TContext, TUser>;
98
87
 
99
- export { type PlatformPluvCreateIOParams, type PluvIOEndpoints, PluvPlatform, type RoomDeletedMessageEventData, type UserConnectedEventData, type UserDisconnectedEventData, platformPluv };
88
+ export { type PlatformPluvCreateIOParams, type PluvIOEndpoints, PluvPlatform, platformPluv };
package/dist/index.d.ts CHANGED
@@ -1,25 +1,11 @@
1
- import { AbstractPlatform, JWTEncodeParams, AbstractWebSocket, ConvertWebSocketConfig, WebSocketSerializedState, AbstractPlatformConfig, CreateIOParams, PluvIOAuthorize, InferInitContextType, PluvContext } from '@pluv/io';
2
- import { BaseUser, Id } from '@pluv/types';
1
+ import { BaseUser, AbstractPlatform, JWTEncodeParams, AbstractWebSocket, ConvertWebSocketConfig, WebSocketSerializedState, AbstractPlatformConfig, CreateIOParams, PluvIOAuthorize, InferInitContextType, PluvContext } from '@pluv/io';
2
+ import { BaseUser as BaseUser$1, Id } from '@pluv/types';
3
3
 
4
4
  interface PluvIOEndpoints {
5
5
  createToken: string;
6
6
  }
7
- type RoomDeletedMessageEventData = {
8
- encodedState: string | null;
9
- room: string;
10
- };
11
- type UserConnectedEventData = {
12
- encodedState: string | null;
13
- room: string;
14
- user: any;
15
- };
16
- type UserDisconnectedEventData = {
17
- encodedState: string | null;
18
- room: string;
19
- user: any;
20
- };
21
7
 
22
- interface PluvPlatformConfig {
8
+ interface PluvPlatformConfig<TContext extends Record<string, any> = {}> {
23
9
  /**
24
10
  * @ignore
25
11
  * @readonly
@@ -29,11 +15,12 @@ interface PluvPlatformConfig {
29
15
  endpoints?: PluvIOEndpoints;
30
16
  };
31
17
  basePath: string;
18
+ context?: TContext;
32
19
  publicKey: string;
33
20
  secretKey: string;
34
21
  webhookSecret?: string;
35
22
  }
36
- declare class PluvPlatform extends AbstractPlatform<any, {}, {}, {
23
+ declare class PluvPlatform<TContext extends Record<string, any> = {}, TUser extends BaseUser = BaseUser> extends AbstractPlatform<any, {}, {}, {
37
24
  authorize: {
38
25
  secret: false;
39
26
  };
@@ -66,8 +53,10 @@ declare class PluvPlatform extends AbstractPlatform<any, {}, {}, {
66
53
  router: false;
67
54
  };
68
55
  readonly _name = "platformPluv";
56
+ private readonly _app;
69
57
  private _authorize;
70
58
  private readonly _basePath;
59
+ private readonly _context;
71
60
  private readonly _endpoints;
72
61
  private _getInitialStorage?;
73
62
  private _listeners?;
@@ -87,13 +76,13 @@ declare class PluvPlatform extends AbstractPlatform<any, {}, {}, {
87
76
  randomUUID(): string;
88
77
  setSerializedState(webSocket: AbstractWebSocket, state: WebSocketSerializedState): WebSocketSerializedState;
89
78
  validateConfig(config: any): void;
90
- private _webhooks;
79
+ private _webhooksRouter;
91
80
  }
92
81
 
93
- type PlatformPluvCreateIOParams<TContext extends Record<string, any> = {}, TUser extends BaseUser = BaseUser> = Id<PluvPlatformConfig & Omit<CreateIOParams<PluvPlatform, TContext, TUser>, "authorize" | "context" | "platform"> & {
82
+ type PlatformPluvCreateIOParams<TContext extends Record<string, any> = {}, TUser extends BaseUser$1 = BaseUser$1> = Id<PluvPlatformConfig & Omit<CreateIOParams<PluvPlatform, TContext, TUser>, "authorize" | "context" | "platform"> & {
94
83
  authorize: PluvIOAuthorize<PluvPlatform, TUser, InferInitContextType<PluvPlatform>>;
95
84
  context?: PluvContext<PluvPlatform, TContext>;
96
85
  }>;
97
- declare const platformPluv: <TContext extends Record<string, any> = {}, TUser extends BaseUser = BaseUser>(config: PlatformPluvCreateIOParams<TContext, TUser>) => CreateIOParams<PluvPlatform, TContext, TUser>;
86
+ declare const platformPluv: <TContext extends Record<string, any> = {}, TUser extends BaseUser$1 = BaseUser$1>(config: PlatformPluvCreateIOParams<TContext, TUser>) => CreateIOParams<PluvPlatform<TContext, TUser>, TContext, TUser>;
98
87
 
99
- export { type PlatformPluvCreateIOParams, type PluvIOEndpoints, PluvPlatform, type RoomDeletedMessageEventData, type UserConnectedEventData, type UserDisconnectedEventData, platformPluv };
88
+ export { type PlatformPluvCreateIOParams, type PluvIOEndpoints, PluvPlatform, platformPluv };
package/dist/index.js CHANGED
@@ -75,6 +75,7 @@ var import_fast_json_stable_stringify = __toESM(require("fast-json-stable-string
75
75
  var import_hono = require("hono");
76
76
 
77
77
  // src/constants.ts
78
+ var SIGNATURE_ALGORITHM = "sha256";
78
79
  var SIGNATURE_HEADER = "x-pluv-signature-256";
79
80
 
80
81
  // src/schemas.ts
@@ -213,10 +214,12 @@ var PluvPlatform = class extends import_io.AbstractPlatform {
213
214
  if (typeof token !== "string") throw new Error("Authorization failed");
214
215
  return token;
215
216
  });
216
- this._webhooks = new import_hono.Hono().basePath("/").post("/", (c) => __async(this, null, function* () {
217
- var _a, _b, _c, _d, _e;
218
- const signature = c.req.header(SIGNATURE_HEADER);
219
- if (!this._webhookSecret || !signature) return c.json({ error: "Unauthorized" }, 401);
217
+ this._webhooksRouter = new import_hono.Hono().basePath("/").post("/", (c) => __async(this, null, function* () {
218
+ var _a, _b, _c, _d, _e, _f, _g;
219
+ const [algorithm, signature] = (_b = (_a = c.req.header(SIGNATURE_HEADER)) == null ? void 0 : _a.split("=")) != null ? _b : [];
220
+ if (!this._webhookSecret) return c.json({ error: "Unauthorized" }, 401);
221
+ if (algorithm !== SIGNATURE_ALGORITHM) return c.json({ error: "Unauthorized" }, 401);
222
+ if (!signature) return c.json({ error: "Unauthorized" }, 401);
220
223
  const payload = yield c.req.json();
221
224
  const verified = yield verifyWebhook({
222
225
  payload: (0, import_fast_json_stable_stringify.default)(payload),
@@ -227,43 +230,46 @@ var PluvPlatform = class extends import_io.AbstractPlatform {
227
230
  const parsed = ZodEvent.safeParse(payload);
228
231
  if (!parsed.success) return c.json({ data: { ok: true } }, 200);
229
232
  const { event, data } = parsed.data;
233
+ const context = this._context;
230
234
  switch (event) {
231
235
  case "initial-storage": {
232
236
  const room = data.room;
233
- const storage = typeof room === "string" ? (_b = yield (_a = this._getInitialStorage) == null ? void 0 : _a.call(this, { context: {}, room })) != null ? _b : null : null;
237
+ const storage = typeof room === "string" ? (_d = yield (_c = this._getInitialStorage) == null ? void 0 : _c.call(this, { context, room })) != null ? _d : null : null;
234
238
  return c.json({ data: { storage } }, 200);
235
239
  }
236
240
  case "room-deleted": {
237
241
  const room = data.room;
238
242
  const encodedState = data.storage;
239
- yield Promise.resolve((_c = this._listeners) == null ? void 0 : _c.onRoomDeleted({ encodedState, room }));
243
+ yield Promise.resolve((_e = this._listeners) == null ? void 0 : _e.onRoomDeleted({ context, encodedState, room }));
240
244
  return c.json({ data: { room } }, 200);
241
245
  }
242
246
  case "user-connected": {
243
247
  const room = data.room;
244
248
  const encodedState = data.storage;
245
249
  const user = data.user;
246
- yield Promise.resolve((_d = this._listeners) == null ? void 0 : _d.onUserConnected({ encodedState, room, user }));
250
+ yield Promise.resolve((_f = this._listeners) == null ? void 0 : _f.onUserConnected({ context, encodedState, room, user }));
247
251
  }
248
252
  case "user-disconnected": {
249
253
  const room = data.room;
250
254
  const encodedState = data.storage;
251
255
  const user = data.user;
252
- yield Promise.resolve((_e = this._listeners) == null ? void 0 : _e.onUserDisconnected({ encodedState, room, user }));
256
+ yield Promise.resolve((_g = this._listeners) == null ? void 0 : _g.onUserDisconnected({ context, encodedState, room, user }));
253
257
  }
254
258
  default:
255
259
  return c.json({ data: { ok: true } }, 200);
256
260
  }
257
261
  }));
258
- const { _defs, basePath, publicKey, secretKey, webhookSecret } = params;
262
+ const { _defs, context, basePath, publicKey, secretKey, webhookSecret } = params;
259
263
  this._basePath = basePath;
264
+ this._context = typeof context === "function" ? context(this._roomContext) : context;
260
265
  this._endpoints = __spreadValues({
261
266
  createToken: "https://pluv.io/api/room/token"
262
267
  }, _defs == null ? void 0 : _defs.endpoints);
263
268
  this._publicKey = publicKey;
264
269
  this._secretKey = secretKey;
265
270
  this._webhookSecret = webhookSecret;
266
- this._fetch = new import_hono.Hono().basePath(this._basePath).route("/", this._webhooks).fetch;
271
+ this._app = new import_hono.Hono().basePath(this._basePath).route("/", this._webhooksRouter);
272
+ this._fetch = this._app.fetch;
267
273
  }
268
274
  acceptWebSocket(webSocket) {
269
275
  throw new Error("Not implemented");
package/dist/index.mjs CHANGED
@@ -47,6 +47,7 @@ import stringify from "fast-json-stable-stringify";
47
47
  import { Hono } from "hono";
48
48
 
49
49
  // src/constants.ts
50
+ var SIGNATURE_ALGORITHM = "sha256";
50
51
  var SIGNATURE_HEADER = "x-pluv-signature-256";
51
52
 
52
53
  // src/schemas.ts
@@ -185,10 +186,12 @@ var PluvPlatform = class extends AbstractPlatform {
185
186
  if (typeof token !== "string") throw new Error("Authorization failed");
186
187
  return token;
187
188
  });
188
- this._webhooks = new Hono().basePath("/").post("/", (c) => __async(this, null, function* () {
189
- var _a, _b, _c, _d, _e;
190
- const signature = c.req.header(SIGNATURE_HEADER);
191
- if (!this._webhookSecret || !signature) return c.json({ error: "Unauthorized" }, 401);
189
+ this._webhooksRouter = new Hono().basePath("/").post("/", (c) => __async(this, null, function* () {
190
+ var _a, _b, _c, _d, _e, _f, _g;
191
+ const [algorithm, signature] = (_b = (_a = c.req.header(SIGNATURE_HEADER)) == null ? void 0 : _a.split("=")) != null ? _b : [];
192
+ if (!this._webhookSecret) return c.json({ error: "Unauthorized" }, 401);
193
+ if (algorithm !== SIGNATURE_ALGORITHM) return c.json({ error: "Unauthorized" }, 401);
194
+ if (!signature) return c.json({ error: "Unauthorized" }, 401);
192
195
  const payload = yield c.req.json();
193
196
  const verified = yield verifyWebhook({
194
197
  payload: stringify(payload),
@@ -199,43 +202,46 @@ var PluvPlatform = class extends AbstractPlatform {
199
202
  const parsed = ZodEvent.safeParse(payload);
200
203
  if (!parsed.success) return c.json({ data: { ok: true } }, 200);
201
204
  const { event, data } = parsed.data;
205
+ const context = this._context;
202
206
  switch (event) {
203
207
  case "initial-storage": {
204
208
  const room = data.room;
205
- const storage = typeof room === "string" ? (_b = yield (_a = this._getInitialStorage) == null ? void 0 : _a.call(this, { context: {}, room })) != null ? _b : null : null;
209
+ const storage = typeof room === "string" ? (_d = yield (_c = this._getInitialStorage) == null ? void 0 : _c.call(this, { context, room })) != null ? _d : null : null;
206
210
  return c.json({ data: { storage } }, 200);
207
211
  }
208
212
  case "room-deleted": {
209
213
  const room = data.room;
210
214
  const encodedState = data.storage;
211
- yield Promise.resolve((_c = this._listeners) == null ? void 0 : _c.onRoomDeleted({ encodedState, room }));
215
+ yield Promise.resolve((_e = this._listeners) == null ? void 0 : _e.onRoomDeleted({ context, encodedState, room }));
212
216
  return c.json({ data: { room } }, 200);
213
217
  }
214
218
  case "user-connected": {
215
219
  const room = data.room;
216
220
  const encodedState = data.storage;
217
221
  const user = data.user;
218
- yield Promise.resolve((_d = this._listeners) == null ? void 0 : _d.onUserConnected({ encodedState, room, user }));
222
+ yield Promise.resolve((_f = this._listeners) == null ? void 0 : _f.onUserConnected({ context, encodedState, room, user }));
219
223
  }
220
224
  case "user-disconnected": {
221
225
  const room = data.room;
222
226
  const encodedState = data.storage;
223
227
  const user = data.user;
224
- yield Promise.resolve((_e = this._listeners) == null ? void 0 : _e.onUserDisconnected({ encodedState, room, user }));
228
+ yield Promise.resolve((_g = this._listeners) == null ? void 0 : _g.onUserDisconnected({ context, encodedState, room, user }));
225
229
  }
226
230
  default:
227
231
  return c.json({ data: { ok: true } }, 200);
228
232
  }
229
233
  }));
230
- const { _defs, basePath, publicKey, secretKey, webhookSecret } = params;
234
+ const { _defs, context, basePath, publicKey, secretKey, webhookSecret } = params;
231
235
  this._basePath = basePath;
236
+ this._context = typeof context === "function" ? context(this._roomContext) : context;
232
237
  this._endpoints = __spreadValues({
233
238
  createToken: "https://pluv.io/api/room/token"
234
239
  }, _defs == null ? void 0 : _defs.endpoints);
235
240
  this._publicKey = publicKey;
236
241
  this._secretKey = secretKey;
237
242
  this._webhookSecret = webhookSecret;
238
- this._fetch = new Hono().basePath(this._basePath).route("/", this._webhooks).fetch;
243
+ this._app = new Hono().basePath(this._basePath).route("/", this._webhooksRouter);
244
+ this._fetch = this._app.fetch;
239
245
  }
240
246
  acceptWebSocket(webSocket) {
241
247
  throw new Error("Not implemented");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluv/platform-pluv",
3
- "version": "0.38.3",
3
+ "version": "0.38.5",
4
4
  "description": "@pluv/io adapter for pluv.io",
5
5
  "author": "leedavidcs",
6
6
  "license": "MIT",
@@ -21,16 +21,16 @@
21
21
  "fast-json-stable-stringify": "^2.1.0",
22
22
  "hono": "^4.7.4",
23
23
  "zod": "^3.24.2",
24
- "@pluv/crdt": "^0.38.3",
25
- "@pluv/io": "^0.38.3",
26
- "@pluv/types": "^0.38.3"
24
+ "@pluv/crdt": "^0.38.5",
25
+ "@pluv/types": "^0.38.5",
26
+ "@pluv/io": "^0.38.5"
27
27
  },
28
28
  "devDependencies": {
29
29
  "eslint": "^8.57.1",
30
30
  "tsup": "^8.4.0",
31
31
  "typescript": "^5.8.2",
32
- "@pluv/tsconfig": "^0.38.3",
33
- "eslint-config-pluv": "^0.38.3"
32
+ "@pluv/tsconfig": "^0.38.5",
33
+ "eslint-config-pluv": "^0.38.5"
34
34
  },
35
35
  "scripts": {
36
36
  "build": "tsup src/index.ts --format esm,cjs --dts",
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  AbstractPlatformConfig,
3
3
  AbstractWebSocket,
4
+ BaseUser,
4
5
  ConvertWebSocketConfig,
5
6
  GetInitialStorageFn,
6
7
  JWTEncodeParams,
@@ -8,13 +9,15 @@ import type {
8
9
  } from "@pluv/io";
9
10
  import { AbstractPlatform } from "@pluv/io";
10
11
  import stringify from "fast-json-stable-stringify";
12
+ import type { Context } from "hono";
11
13
  import { Hono } from "hono";
12
- import { SIGNATURE_HEADER } from "./constants";
14
+ import type { BlankEnv, BlankInput } from "hono/types";
15
+ import { SIGNATURE_ALGORITHM, SIGNATURE_HEADER } from "./constants";
13
16
  import { ZodEvent } from "./schemas";
14
17
  import { verifyWebhook } from "./shared";
15
18
  import type { PluvIOEndpoints, PluvIOListeners } from "./types";
16
19
 
17
- export interface PluvPlatformConfig {
20
+ export interface PluvPlatformConfig<TContext extends Record<string, any> = {}> {
18
21
  /**
19
22
  * @ignore
20
23
  * @readonly
@@ -24,12 +27,16 @@ export interface PluvPlatformConfig {
24
27
  endpoints?: PluvIOEndpoints;
25
28
  };
26
29
  basePath: string;
30
+ context?: TContext;
27
31
  publicKey: string;
28
32
  secretKey: string;
29
33
  webhookSecret?: string;
30
34
  }
31
35
 
32
- export class PluvPlatform extends AbstractPlatform<
36
+ export class PluvPlatform<
37
+ TContext extends Record<string, any> = {},
38
+ TUser extends BaseUser = BaseUser,
39
+ > extends AbstractPlatform<
33
40
  any,
34
41
  {},
35
42
  {},
@@ -68,8 +75,10 @@ export class PluvPlatform extends AbstractPlatform<
68
75
  };
69
76
  public readonly _name = "platformPluv";
70
77
 
78
+ private readonly _app: Hono;
71
79
  private _authorize: any;
72
80
  private readonly _basePath: string;
81
+ private readonly _context: any;
73
82
  private readonly _endpoints: PluvIOEndpoints;
74
83
  private _getInitialStorage?: GetInitialStorageFn<{}>;
75
84
  private _listeners?: PluvIOListeners;
@@ -106,9 +115,10 @@ export class PluvPlatform extends AbstractPlatform<
106
115
  constructor(params: PluvPlatformConfig) {
107
116
  super();
108
117
 
109
- const { _defs, basePath, publicKey, secretKey, webhookSecret } = params;
118
+ const { _defs, context, basePath, publicKey, secretKey, webhookSecret } = params;
110
119
 
111
120
  this._basePath = basePath;
121
+ this._context = typeof context === "function" ? context(this._roomContext) : context;
112
122
  this._endpoints = {
113
123
  createToken: "https://pluv.io/api/room/token",
114
124
  ..._defs?.endpoints,
@@ -117,9 +127,8 @@ export class PluvPlatform extends AbstractPlatform<
117
127
  this._secretKey = secretKey;
118
128
  this._webhookSecret = webhookSecret;
119
129
 
120
- this._fetch = new Hono().basePath(this._basePath).route("/", this._webhooks).fetch as (
121
- req: any,
122
- ) => Promise<any>;
130
+ this._app = new Hono().basePath(this._basePath).route("/", this._webhooksRouter);
131
+ this._fetch = this._app.fetch as (req: any) => Promise<any>;
123
132
  }
124
133
 
125
134
  public acceptWebSocket(webSocket: AbstractWebSocket): Promise<void> {
@@ -182,10 +191,12 @@ export class PluvPlatform extends AbstractPlatform<
182
191
  };
183
192
  }
184
193
 
185
- private _webhooks = new Hono().basePath("/").post("/", async (c) => {
186
- const signature = c.req.header(SIGNATURE_HEADER);
194
+ private _webhooksRouter = new Hono().basePath("/").post("/", async (c: Context<BlankEnv, "/", BlankInput>) => {
195
+ const [algorithm, signature] = c.req.header(SIGNATURE_HEADER)?.split("=") ?? [];
187
196
 
188
- if (!this._webhookSecret || !signature) return c.json({ error: "Unauthorized" }, 401);
197
+ if (!this._webhookSecret) return c.json({ error: "Unauthorized" }, 401);
198
+ if (algorithm !== SIGNATURE_ALGORITHM) return c.json({ error: "Unauthorized" }, 401);
199
+ if (!signature) return c.json({ error: "Unauthorized" }, 401);
189
200
 
190
201
  const payload = await c.req.json();
191
202
 
@@ -203,13 +214,13 @@ export class PluvPlatform extends AbstractPlatform<
203
214
 
204
215
  const { event, data } = parsed.data;
205
216
 
217
+ const context = this._context;
218
+
206
219
  switch (event) {
207
220
  case "initial-storage": {
208
221
  const room = data.room;
209
222
  const storage =
210
- typeof room === "string"
211
- ? ((await this._getInitialStorage?.({ context: {}, room })) ?? null)
212
- : null;
223
+ typeof room === "string" ? ((await this._getInitialStorage?.({ context, room })) ?? null) : null;
213
224
 
214
225
  return c.json({ data: { storage } }, 200);
215
226
  }
@@ -217,7 +228,7 @@ export class PluvPlatform extends AbstractPlatform<
217
228
  const room = data.room;
218
229
  const encodedState = data.storage;
219
230
 
220
- await Promise.resolve(this._listeners?.onRoomDeleted({ encodedState, room }));
231
+ await Promise.resolve(this._listeners?.onRoomDeleted({ context, encodedState, room }));
221
232
 
222
233
  return c.json({ data: { room } }, 200);
223
234
  }
@@ -226,14 +237,14 @@ export class PluvPlatform extends AbstractPlatform<
226
237
  const encodedState = data.storage;
227
238
  const user = data.user as any;
228
239
 
229
- await Promise.resolve(this._listeners?.onUserConnected({ encodedState, room, user }));
240
+ await Promise.resolve(this._listeners?.onUserConnected({ context, encodedState, room, user }));
230
241
  }
231
242
  case "user-disconnected": {
232
243
  const room = data.room;
233
244
  const encodedState = data.storage;
234
245
  const user = data.user as any;
235
246
 
236
- await Promise.resolve(this._listeners?.onUserDisconnected({ encodedState, room, user }));
247
+ await Promise.resolve(this._listeners?.onUserDisconnected({ context, encodedState, room, user }));
237
248
  }
238
249
  default:
239
250
  return c.json({ data: { ok: true } }, 200);
package/src/constants.ts CHANGED
@@ -1 +1,2 @@
1
+ export const SIGNATURE_ALGORITHM = "sha256";
1
2
  export const SIGNATURE_HEADER = "x-pluv-signature-256";
package/src/index.ts CHANGED
@@ -1,9 +1,4 @@
1
1
  export { platformPluv } from "./platformPluv";
2
2
  export type { PlatformPluvCreateIOParams } from "./platformPluv";
3
3
  export { PluvPlatform } from "./PluvPlatform";
4
- export type {
5
- PluvIOEndpoints,
6
- RoomDeletedMessageEventData,
7
- UserConnectedEventData,
8
- UserDisconnectedEventData,
9
- } from "./types";
4
+ export type { PluvIOEndpoints } from "./types";
@@ -16,7 +16,7 @@ export type PlatformPluvCreateIOParams<
16
16
 
17
17
  export const platformPluv = <TContext extends Record<string, any> = {}, TUser extends BaseUser = BaseUser>(
18
18
  config: PlatformPluvCreateIOParams<TContext, TUser>,
19
- ): CreateIOParams<PluvPlatform, TContext, TUser> => {
19
+ ): CreateIOParams<PluvPlatform<TContext, TUser>, TContext, TUser> => {
20
20
  const { authorize, context, crdt, debug } = config;
21
21
 
22
22
  return {
@@ -24,6 +24,6 @@ export const platformPluv = <TContext extends Record<string, any> = {}, TUser ex
24
24
  context,
25
25
  crdt,
26
26
  debug,
27
- platform: new PluvPlatform(config),
27
+ platform: new PluvPlatform<TContext, TUser>(config),
28
28
  };
29
29
  };
package/src/types.ts CHANGED
@@ -1,29 +1,24 @@
1
- import type { GetInitialStorageFn } from "@pluv/io";
1
+ import type {
2
+ BaseUser,
3
+ GetInitialStorageFn,
4
+ IORoomListenerEvent,
5
+ IOUserConnectedEvent,
6
+ IOUserDisconnectedEvent,
7
+ } from "@pluv/io";
8
+ import type { InputZodLike } from "@pluv/types";
9
+ import type { PluvPlatform } from "./PluvPlatform";
2
10
 
3
11
  export interface PluvIOEndpoints {
4
12
  createToken: string;
5
13
  }
6
14
 
7
- export type RoomDeletedMessageEventData = {
8
- encodedState: string | null;
9
- room: string;
10
- };
11
-
12
- export type UserConnectedEventData = {
13
- encodedState: string | null;
14
- room: string;
15
- user: any;
16
- };
17
-
18
- export type UserDisconnectedEventData = {
19
- encodedState: string | null;
20
- room: string;
21
- user: any;
22
- };
23
-
24
- export type PluvIOListeners = {
25
- getInitialStorage?: GetInitialStorageFn<{}>;
26
- onRoomDeleted: (event: RoomDeletedMessageEventData) => void;
27
- onUserConnected: (event: UserConnectedEventData) => void;
28
- onUserDisconnected: (event: UserDisconnectedEventData) => void;
15
+ export type PluvIOListeners<TContext extends Record<string, any> = {}, TUser extends BaseUser = BaseUser> = {
16
+ getInitialStorage?: GetInitialStorageFn<TContext>;
17
+ onRoomDeleted: (event: IORoomListenerEvent<TContext>) => void;
18
+ onUserConnected: (
19
+ event: IOUserConnectedEvent<PluvPlatform<TContext>, { user: InputZodLike<TUser> }, TContext>,
20
+ ) => void;
21
+ onUserDisconnected: (
22
+ event: IOUserDisconnectedEvent<PluvPlatform<TContext>, { user: InputZodLike<TUser> }, TContext>,
23
+ ) => void;
29
24
  };