@pluv/platform-pluv 3.2.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +16 -16
- package/CHANGELOG.md +91 -0
- package/dist/index.d.mts +81 -74
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +433 -435
- package/dist/index.mjs.map +1 -0
- package/package.json +21 -17
- package/src/PluvPlatform.ts +32 -6
- package/src/schemas.ts +22 -7
- package/src/shared/index.ts +0 -1
- package/src/types.ts +12 -9
- package/tsdown.config.ts +14 -0
- package/dist/index.d.ts +0 -96
- package/dist/index.js +0 -500
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/constants.ts","../src/schemas.ts","../src/shared/createErrorResponse.ts","../src/shared/getCrypto.ts","../src/shared/createHmac.ts","../src/shared/createSuccessResponse.ts","../src/shared/HttpError.ts","../src/shared/timingSafeEqual.ts","../src/shared/verifyWebhook.ts","../src/PluvPlatform.ts","../src/platformPluv.ts"],"sourcesContent":["export const SIGNATURE_ALGORITHM = \"sha256\";\nexport const SIGNATURE_HEADER = \"x-pluv-signature-256\";\n","import { z } from \"zod\";\n\nexport const ZodEventKind = z.union([\n z.literal(\"initial-storage\"),\n z.literal(\"room-destroyed\"),\n z.literal(\"storage-destroyed\"),\n z.literal(\"user-connected\"),\n z.literal(\"user-disconnected\"),\n]);\n\nexport const ZodEventInitialStorage = z.object({\n event: z.literal(\"initial-storage\"),\n data: z.object({\n room: z.string(),\n }),\n});\n\nexport const ZodEventRoomDestroyed = z.object({\n event: z.literal(\"room-destroyed\"),\n data: z.object({\n room: z.string(),\n }),\n});\n\nexport const ZodEventStorageDestroyed = z.object({\n event: z.literal(\"storage-destroyed\"),\n data: z.object({\n room: z.string(),\n storage: z.string().nullable(),\n }),\n});\n\nexport const ZodEventUserConnected = z.object({\n event: z.literal(\"user-connected\"),\n data: z.object({\n room: z.string(),\n storage: z.string().nullable(),\n user: z\n .object({\n id: z.string(),\n })\n .passthrough(),\n }),\n});\n\nexport const ZodEventUserDisconnected = z.object({\n event: z.literal(\"user-disconnected\"),\n data: z.object({\n room: z.string(),\n storage: z.string().nullable(),\n user: z\n .object({\n id: z.string(),\n })\n .passthrough(),\n }),\n});\n\nexport const ZodEvent = z.discriminatedUnion(\"event\", [\n ZodEventInitialStorage,\n ZodEventRoomDestroyed,\n ZodEventStorageDestroyed,\n ZodEventUserConnected,\n ZodEventUserDisconnected,\n]);\n\nexport const ZodInitialStorageResponse = z.object({\n event: z.literal(\"initial-storage\"),\n room: z.string(),\n storage: z.string().nullable(),\n});\n\nexport const ZodRoomDestroyedResponse = z.object({\n event: z.literal(\"room-destroyed\"),\n room: z.string(),\n});\n\nexport const ZodStorageDestroyedResponse = z.object({\n event: z.literal(\"storage-destroyed\"),\n room: z.string(),\n});\n\nexport const ZodUserConnectedResponse = z.object({\n event: z.literal(\"user-connected\"),\n room: z.string(),\n});\n\nexport const ZodUserDisconnectedResponse = z.object({\n event: z.literal(\"user-disconnected\"),\n room: z.string(),\n});\n\nexport const ZodEventResponse = z.discriminatedUnion(\"event\", [\n ZodInitialStorageResponse,\n ZodRoomDestroyedResponse,\n ZodStorageDestroyedResponse,\n ZodUserConnectedResponse,\n ZodUserDisconnectedResponse,\n]);\n","import type { Context } from \"hono\";\nimport type { BlankEnv, BlankInput } from \"hono/types\";\nimport type { ContentfulStatusCode } from \"hono/utils/http-status\";\n\nexport const createErrorResponse = <TStatus extends ContentfulStatusCode>(\n c: Context<BlankEnv, \"/\", BlankInput>,\n error: { message: string },\n status: TStatus,\n) => {\n return c.json({ ok: false, error: { message: error.message } }, status);\n};\n","import type { webcrypto } from \"crypto\";\n\nexport const getCrypto = (): webcrypto.Crypto => {\n if (typeof crypto !== \"undefined\") {\n // In a browser or Web Worker (including Cloudflare Workers)\n return crypto;\n }\n\n if (typeof require === \"function\") {\n // In Node.js\n // Node 15+ supports `crypto.webcrypto`\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require(\"node:crypto\").webcrypto as webcrypto.Crypto;\n }\n\n throw new Error(\"Missing crypto module\");\n};\n","import type { webcrypto } from \"crypto\";\nimport { getCrypto } from \"./getCrypto\";\n\nexport interface CreateHmacParams {\n payload: string;\n secret: string;\n}\n\nexport type CreateHmacResult = {\n algorithm: \"sha256\";\n hmac: string;\n};\n\nexport const createHmac = async (params: CreateHmacParams): Promise<CreateHmacResult> => {\n const { payload, secret } = params;\n\n if (!payload || !secret) throw new Error(\"Secret and payload are required to sign payload\");\n\n const encoder = new TextEncoder();\n const keyBytes = encoder.encode(secret);\n\n const crypto = getCrypto();\n\n const algorithm: webcrypto.HmacImportParams = { name: \"HMAC\", hash: { name: \"SHA-256\" } };\n const extractable = false;\n\n const key = await crypto.subtle.importKey(\"raw\", keyBytes, algorithm, extractable, [\n \"sign\",\n \"verify\",\n ]);\n const payloadBytes = encoder.encode(payload);\n\n const signature = await crypto.subtle.sign(\"HMAC\", key, payloadBytes);\n\n // Convert the signature to a hex string\n const hmac = Array.from(new Uint8Array(signature))\n .map((b) => (\"0\" + b.toString(16)).slice(-2))\n .join(\"\");\n\n return { algorithm: \"sha256\", hmac };\n};\n","import type { Context } from \"hono\";\nimport type { BlankEnv, BlankInput } from \"hono/types\";\nimport type { ContentfulStatusCode } from \"hono/utils/http-status\";\nimport { ZodEventResponse } from \"../schemas\";\nimport type { EventResponse } from \"../types\";\n\nexport interface CreateSuccessResponseParams<TStatus extends ContentfulStatusCode> {\n data: EventResponse;\n status?: TStatus;\n}\n\nexport const createSuccessResponse = <TStatus extends ContentfulStatusCode = 200>(\n c: Context<BlankEnv, \"/\", BlankInput>,\n data: EventResponse,\n status: TStatus = 200 as TStatus,\n) => {\n return c.json(\n {\n ok: true,\n data: ZodEventResponse.parse(data),\n },\n status,\n );\n};\n","import type { ContentfulStatusCode } from \"hono/utils/http-status\";\n\nexport class HttpError extends Error {\n readonly status: ContentfulStatusCode;\n\n constructor(message: string, status: ContentfulStatusCode) {\n super(message);\n\n this.status = status;\n }\n}\n","export const timingSafeEqual = (a: Uint8Array, b: Uint8Array): boolean => {\n if (a.length !== b.length) return false; // Lengths are different\n\n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a[i] ^ b[i]; // XOR each byte\n }\n\n return result === 0; // If all bytes are equal, result will be 0\n};\n","import { createHmac } from \"./createHmac\";\nimport { timingSafeEqual } from \"./timingSafeEqual\";\n\nexport interface VerifyWebhookParams {\n payload: string;\n secret: string;\n signature: string;\n}\n\nexport const verifyWebhook = async (params: VerifyWebhookParams): Promise<boolean> => {\n const { payload, secret, signature } = params;\n\n if (!secret || !payload || !signature) {\n throw new Error(\"Secret, payload and signature are required to verify payload\");\n }\n\n const { hmac } = await createHmac({ payload, secret });\n\n if (hmac.length !== signature.length) return false;\n\n const encoder = new TextEncoder();\n const verificationBytes = encoder.encode(hmac);\n const signatureBytes = encoder.encode(signature);\n\n if (verificationBytes.length !== signatureBytes.length) return false;\n\n return timingSafeEqual(verificationBytes, signatureBytes);\n};\n","import type {\n AbstractPlatformConfig,\n AbstractWebSocket,\n BaseUser,\n ConvertWebSocketConfig,\n GetInitialStorageFn,\n JWTEncodeParams,\n PluvContext,\n WebSocketSerializedState,\n} from \"@pluv/io\";\nimport { AbstractPlatform } from \"@pluv/io\";\nimport type { MaybePromise } from \"@pluv/types\";\nimport stringify from \"fast-json-stable-stringify\";\nimport type { Context } from \"hono\";\nimport { Hono } from \"hono\";\nimport type { BlankEnv, BlankInput } from \"hono/types\";\nimport { SIGNATURE_ALGORITHM, SIGNATURE_HEADER } from \"./constants\";\nimport { ZodEvent } from \"./schemas\";\nimport { createErrorResponse, createSuccessResponse, HttpError, verifyWebhook } from \"./shared\";\nimport type { PluvIOEndpoints, PluvIOListeners } from \"./types\";\n\nexport type PublicKey = string | (() => MaybePromise<string>);\nexport type SecretKey = string | (() => MaybePromise<string>);\nexport type WebhookSecret = string | (() => MaybePromise<string>);\n\nexport interface PluvPlatformConfig<TContext extends Record<string, any> = {}> {\n /**\n * @ignore\n * @readonly\n * @deprecated Internal use only. Changes to this will never be marked as breaking.\n */\n _defs?: {\n debug?: boolean;\n endpoints?: PluvIOEndpoints | (() => MaybePromise<PluvIOEndpoints>);\n };\n basePath: string;\n context?: PluvContext<any, TContext>;\n publicKey: PublicKey;\n secretKey: SecretKey;\n webhookSecret?: WebhookSecret;\n}\n\nexport class PluvPlatform<\n TContext extends Record<string, any> = {},\n TUser extends BaseUser = BaseUser,\n> extends AbstractPlatform<\n any,\n {},\n {},\n {\n authorize: {\n secret: false;\n };\n handleMode: \"fetch\";\n registrationMode: \"attached\";\n requireAuth: true;\n listeners: {\n onRoomDestroyed: true;\n onRoomMessage: false;\n onStorageDestroyed: true;\n onStorageUpdated: false;\n onUserConnected: true;\n onUserDisconnected: true;\n };\n router: false;\n }\n> {\n public readonly id = Math.random().toString();\n public readonly _config = {\n authorize: {\n secret: false as const,\n },\n handleMode: \"fetch\" as const,\n registrationMode: \"attached\" as const,\n requireAuth: true as const,\n listeners: {\n onRoomDestroyed: true as const,\n onRoomMessage: false as const,\n onStorageDestroyed: true as const,\n onStorageUpdated: false as const,\n onUserConnected: true as const,\n onUserDisconnected: true as const,\n },\n router: false as const,\n };\n public readonly _name = \"platformPluv\";\n\n private readonly _app: Hono;\n private readonly _basePath: string;\n private readonly _context: PluvContext<this, TContext>;\n private readonly _debug: boolean;\n private readonly _endpoints: PluvIOEndpoints | (() => MaybePromise<PluvIOEndpoints>);\n private _getInitialStorage?: GetInitialStorageFn<{}>;\n private _listeners?: PluvIOListeners;\n private readonly _publicKey: PublicKey;\n private readonly _secretKey: SecretKey;\n private readonly _webhookSecret?: WebhookSecret;\n\n public _createToken = async (params: JWTEncodeParams<any, any>): Promise<string> => {\n const parsed = params.authorize.user.parse(params.user);\n\n const [endpoints, publicKey, secretKey] = await Promise.all([\n typeof this._endpoints === \"object\" ? this._endpoints : this._endpoints(),\n typeof this._publicKey === \"string\" ? this._publicKey : this._publicKey(),\n typeof this._secretKey === \"string\" ? this._secretKey : this._secretKey(),\n ]);\n\n this._logDebug({ endpoints, publicKey, secretKey });\n\n const res = await fetch(endpoints.createToken, {\n headers: { \"content-type\": \"application/json\" },\n method: \"post\",\n body: JSON.stringify({\n maxAge: params.maxAge ?? null,\n publicKey,\n room: params.room,\n secretKey,\n user: parsed,\n }),\n }).catch((error) => {\n this._logDebug(error);\n\n return null;\n });\n\n this._logDebug({ response: { status: res?.status ?? null } });\n\n if (!res || !res.ok || res.status !== 200) {\n throw new Error(\"Authorization failed\");\n }\n\n const token = await res.text().catch(() => null);\n\n this._logDebug({ token });\n\n if (typeof token !== \"string\") throw new Error(\"Authorization failed\");\n\n return token;\n };\n\n constructor(params: PluvPlatformConfig) {\n super();\n\n const { _defs, basePath, context, publicKey, secretKey, webhookSecret } = params;\n\n this._basePath = basePath;\n this._context = (context ?? {}) as TContext;\n this._debug = _defs?.debug ?? false;\n this._endpoints = _defs?.endpoints ?? {\n createToken: \"https://rooms.pluv.io/api/room/token\",\n };\n this._publicKey = publicKey;\n this._secretKey = secretKey;\n this._webhookSecret = webhookSecret;\n\n this._app = new Hono().basePath(this._basePath).route(\"/\", this._webhooksRouter);\n this._fetch = this._app.fetch as (req: any) => Promise<any>;\n }\n\n public acceptWebSocket(webSocket: AbstractWebSocket): Promise<void> {\n throw new Error(\"Not implemented\");\n }\n\n public convertWebSocket(webSocket: any, config: ConvertWebSocketConfig): AbstractWebSocket {\n throw new Error(\"Not implemented\");\n }\n\n public getLastPing(webSocket: AbstractWebSocket): number | null {\n throw new Error(\"Not implemented\");\n }\n\n public getSerializedState(webSocket: any): WebSocketSerializedState | null {\n throw new Error(\"Not implemented\");\n }\n\n public getSessionId(webSocket: any): string | null {\n throw new Error(\"Not implemented\");\n }\n\n public getWebSockets(): readonly any[] {\n throw new Error(\"Not implemented\");\n }\n\n public initialize(config: AbstractPlatformConfig<{}>): this {\n throw new Error(\"Not implemented\");\n }\n\n public parseData(data: string | ArrayBuffer): Record<string, any> {\n throw new Error(\"Not implemented\");\n }\n\n public randomUUID(): string {\n throw new Error(\"Not implemented\");\n }\n\n public setSerializedState(\n webSocket: AbstractWebSocket,\n state: WebSocketSerializedState,\n ): WebSocketSerializedState {\n throw new Error(\"Not implemented\");\n }\n\n public validateConfig(config: any): void {\n this._logDebug(\"validating config with properties:\", Object.keys(config ?? {}));\n\n if (!config.authorize) {\n this._logDebug(\"Config `authorize` must be provided to `platformPluv`\");\n throw new Error(\"Config `authorize` must be provided to `platformPluv`\");\n }\n if (!!config.onRoomMessage) {\n this._logDebug(\"Config `onRoomMessage` is not supported on `platformPluv`\");\n throw new Error(\"Config `onRoomMessage` is not supported on `platformPluv`\");\n }\n if (!!config.onStorageUpdated) {\n this._logDebug(\"Config `onStorageUpdated` is not supported on `platformPluv`\");\n throw new Error(\"Config `onStorageUpdated` is not supported on `platformPluv`\");\n }\n\n this._getInitialStorage = config.getInitialStorage;\n this._listeners = {\n onRoomDestroyed: (event) => config.onRoomDestroyed?.(event),\n onStorageDestroyed: (event) => config.onStorageDestroyed?.(event),\n onUserConnected: (event) => config.onUserConnected?.(event),\n onUserDisconnected: (event) => config.onUserDisconnected?.(event),\n };\n }\n\n private _webhooksRouter = new Hono()\n .basePath(\"/\")\n .post(\"/\", async (c: Context<BlankEnv, \"/\", BlankInput>) => {\n const [algorithm, signature] = c.req.header(SIGNATURE_HEADER)?.split(\"=\") ?? [];\n\n try {\n if (!this._webhookSecret) {\n this._logDebug(\"Missing webhook secret\");\n throw new HttpError(\"Unauthorized\", 401);\n }\n if (algorithm !== SIGNATURE_ALGORITHM) {\n this._logDebug(\n `Verification algorithm is not ${SIGNATURE_ALGORITHM}. Found: `,\n algorithm,\n );\n throw new HttpError(\"Unauthorized\", 401);\n }\n if (!signature) {\n this._logDebug(\"Missing webhook signature\");\n throw new HttpError(\"Unauthorized\", 401);\n }\n\n const [payload, webhookSecret] = await Promise.all([\n c.req.json(),\n typeof this._webhookSecret === \"string\"\n ? this._webhookSecret\n : await this._webhookSecret(),\n ]).catch((error) => {\n this._logDebug(\n \"Could not derive webhook secret: \",\n error instanceof Error ? error.message : \"Unexpected error\",\n );\n throw error;\n });\n\n const verified = await verifyWebhook({\n payload: stringify(payload),\n signature,\n secret: webhookSecret,\n }).catch((error) => {\n this._logDebug(\n \"Error while verifying webhook: \",\n error instanceof Error ? error.message : \"Unexpected error\",\n );\n\n return false;\n });\n\n if (!verified) {\n this._logDebug(\"Failed to verify webhook\");\n throw new HttpError(\"Unauthorized\", 401);\n }\n\n const parsed = ZodEvent.safeParse(payload);\n\n if (!parsed.success) {\n this._logDebug(\n \"Failed to validate event payload:\",\n JSON.stringify(parsed.data ?? {}, null, 4),\n );\n throw new HttpError(\"Invalid request\", 400);\n }\n\n const { event, data } = parsed.data;\n const context = await this._getContext();\n\n switch (event) {\n case \"initial-storage\": {\n const room = data.room;\n const storage =\n typeof room === \"string\"\n ? ((await this._getInitialStorage?.({ context, room })) ?? null)\n : null;\n\n try {\n return createSuccessResponse(c, { event, room, storage });\n } catch (error) {\n this._logDebug(\"Could not create getInitialStorage response\");\n throw error;\n }\n }\n case \"room-destroyed\": {\n const room = data.room;\n\n await Promise.resolve(\n this._listeners?.onRoomDestroyed({\n context,\n platform: this,\n room,\n }),\n );\n\n try {\n return createSuccessResponse(c, { event, room });\n } catch (error) {\n this._logDebug(\"Could not create onRoomDestroyed response\");\n throw error;\n }\n }\n case \"storage-destroyed\": {\n const room = data.room;\n const encodedState = data.storage;\n\n await Promise.resolve(\n this._listeners?.onStorageDestroyed({\n context,\n encodedState,\n platform: this,\n room,\n }),\n );\n\n try {\n return createSuccessResponse(c, { event, room });\n } catch (error) {\n this._logDebug(\"Could not create onStorageDestroyed response\");\n throw error;\n }\n }\n case \"user-connected\": {\n const room = data.room;\n const encodedState = data.storage;\n const user = data.user as any;\n\n await Promise.resolve(\n this._listeners?.onUserConnected({\n context,\n encodedState,\n platform: this,\n room,\n user,\n }),\n );\n\n try {\n return createSuccessResponse(c, { event, room });\n } catch (error) {\n this._logDebug(\"Could not create onUserConnected response\");\n throw error;\n }\n }\n case \"user-disconnected\": {\n const room = data.room;\n const encodedState = data.storage;\n const user = data.user as any;\n\n await Promise.resolve(\n this._listeners?.onUserDisconnected({\n context,\n encodedState,\n platform: this,\n room,\n user,\n }),\n );\n\n try {\n return createSuccessResponse(c, { event, room });\n } catch (error) {\n this._logDebug(\"Could not create onUserDisconnected response\");\n throw error;\n }\n }\n default: {\n throw new HttpError(\"Unknown event\", 400);\n }\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Unexpected error\";\n const status = error instanceof HttpError ? error.status : 500;\n\n this._logDebug(\"Uncaught error: \", message);\n\n return createErrorResponse(c, { message }, status);\n }\n });\n\n private async _getContext(): Promise<TContext> {\n return typeof this._context === \"function\"\n ? await Promise.resolve(this._context(this._roomContext as any))\n : await Promise.resolve(this._context);\n }\n\n private _logDebug(...args: any[]): void {\n if (!this._debug) return;\n\n console.log(\"[PLATFORM PLUV]\", ...args);\n }\n}\n","import type { CrdtLibraryType, NoopCrdtDocFactory } from \"@pluv/crdt\";\nimport type { CreateIOParams, InferInitContextType, PluvContext, PluvIOAuthorize } from \"@pluv/io\";\nimport type { BaseUser, Id } from \"@pluv/types\";\nimport type { PluvPlatformConfig } from \"./PluvPlatform\";\nimport { PluvPlatform } from \"./PluvPlatform\";\n\nexport type PlatformPluvCreateIOParams<\n TContext extends Record<string, any> = {},\n TUser extends BaseUser = BaseUser,\n TCrdt extends CrdtLibraryType<any> = CrdtLibraryType<NoopCrdtDocFactory>,\n> = Id<\n PluvPlatformConfig &\n Omit<\n CreateIOParams<PluvPlatform, TContext, TUser, TCrdt>,\n \"authorize\" | \"context\" | \"limits\" | \"platform\"\n > & {\n authorize: PluvIOAuthorize<PluvPlatform, TUser, InferInitContextType<PluvPlatform>>;\n context?: PluvContext<PluvPlatform, TContext>;\n }\n>;\n\nexport const platformPluv = <\n TContext extends Record<string, any> = {},\n TUser extends BaseUser = BaseUser,\n TCrdt extends CrdtLibraryType<any> = CrdtLibraryType<NoopCrdtDocFactory>,\n>(\n config: PlatformPluvCreateIOParams<TContext, TUser, TCrdt>,\n): CreateIOParams<PluvPlatform<TContext, TUser>, TContext, TUser, TCrdt> => {\n const { authorize, context, crdt, debug } = config;\n\n return {\n authorize,\n context,\n crdt,\n debug,\n platform: () => new PluvPlatform<TContext, TUser>(config),\n };\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/platform-pluv",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "@pluv/io adapter for pluv.io",
|
|
5
5
|
"author": {
|
|
6
6
|
"email": "david@pluv.io",
|
|
@@ -14,32 +14,36 @@
|
|
|
14
14
|
"url": "git+https://github.com/pluv-io/pluv.git",
|
|
15
15
|
"directory": "packages/platform-pluv"
|
|
16
16
|
},
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"types": "./dist/index.d.ts",
|
|
17
|
+
"type": "module",
|
|
18
|
+
"types": "./dist/index.d.mts",
|
|
20
19
|
"publishConfig": {
|
|
21
20
|
"access": "public"
|
|
22
21
|
},
|
|
23
22
|
"dependencies": {
|
|
24
|
-
"@types/node": "^
|
|
23
|
+
"@types/node": "^25.0.9",
|
|
25
24
|
"fast-json-stable-stringify": "^2.1.0",
|
|
26
|
-
"hono": "^4.
|
|
27
|
-
"zod": "^3.
|
|
28
|
-
"@pluv/
|
|
29
|
-
"@pluv/
|
|
30
|
-
"@pluv/types": "^
|
|
25
|
+
"hono": "^4.11.4",
|
|
26
|
+
"zod": "^4.3.5",
|
|
27
|
+
"@pluv/crdt": "^4.0.0",
|
|
28
|
+
"@pluv/io": "^4.0.0",
|
|
29
|
+
"@pluv/types": "^4.0.0"
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
33
|
-
"eslint": "^9.
|
|
34
|
-
"
|
|
35
|
-
"typescript": "^5.
|
|
36
|
-
"@pluv/tsconfig": "^
|
|
37
|
-
"eslint-config-pluv": "^
|
|
32
|
+
"eslint": "^9.39.2",
|
|
33
|
+
"tsdown": "0.20.0-beta.4",
|
|
34
|
+
"typescript": "^5.9.3",
|
|
35
|
+
"@pluv/tsconfig": "^4.0.0",
|
|
36
|
+
"eslint-config-pluv": "^4.0.0"
|
|
37
|
+
},
|
|
38
|
+
"exports": {
|
|
39
|
+
".": "./dist/index.mjs",
|
|
40
|
+
"./*": "./*"
|
|
38
41
|
},
|
|
39
42
|
"scripts": {
|
|
40
|
-
"build": "
|
|
41
|
-
"dev": "
|
|
43
|
+
"build": "tsdown",
|
|
44
|
+
"dev": "tsdown --watch",
|
|
42
45
|
"lint": "eslint \"src/**/*.ts*\" --fix --max-warnings 0",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
43
47
|
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
|
44
48
|
}
|
|
45
49
|
}
|
package/src/PluvPlatform.ts
CHANGED
|
@@ -55,8 +55,9 @@ export class PluvPlatform<
|
|
|
55
55
|
registrationMode: "attached";
|
|
56
56
|
requireAuth: true;
|
|
57
57
|
listeners: {
|
|
58
|
-
|
|
58
|
+
onRoomDestroyed: true;
|
|
59
59
|
onRoomMessage: false;
|
|
60
|
+
onStorageDestroyed: true;
|
|
60
61
|
onStorageUpdated: false;
|
|
61
62
|
onUserConnected: true;
|
|
62
63
|
onUserDisconnected: true;
|
|
@@ -73,8 +74,9 @@ export class PluvPlatform<
|
|
|
73
74
|
registrationMode: "attached" as const,
|
|
74
75
|
requireAuth: true as const,
|
|
75
76
|
listeners: {
|
|
76
|
-
|
|
77
|
+
onRoomDestroyed: true as const,
|
|
77
78
|
onRoomMessage: false as const,
|
|
79
|
+
onStorageDestroyed: true as const,
|
|
78
80
|
onStorageUpdated: false as const,
|
|
79
81
|
onUserConnected: true as const,
|
|
80
82
|
onUserDisconnected: true as const,
|
|
@@ -216,7 +218,8 @@ export class PluvPlatform<
|
|
|
216
218
|
|
|
217
219
|
this._getInitialStorage = config.getInitialStorage;
|
|
218
220
|
this._listeners = {
|
|
219
|
-
|
|
221
|
+
onRoomDestroyed: (event) => config.onRoomDestroyed?.(event),
|
|
222
|
+
onStorageDestroyed: (event) => config.onStorageDestroyed?.(event),
|
|
220
223
|
onUserConnected: (event) => config.onUserConnected?.(event),
|
|
221
224
|
onUserDisconnected: (event) => config.onUserDisconnected?.(event),
|
|
222
225
|
};
|
|
@@ -303,18 +306,41 @@ export class PluvPlatform<
|
|
|
303
306
|
throw error;
|
|
304
307
|
}
|
|
305
308
|
}
|
|
306
|
-
case "room-
|
|
309
|
+
case "room-destroyed": {
|
|
310
|
+
const room = data.room;
|
|
311
|
+
|
|
312
|
+
await Promise.resolve(
|
|
313
|
+
this._listeners?.onRoomDestroyed({
|
|
314
|
+
context,
|
|
315
|
+
platform: this,
|
|
316
|
+
room,
|
|
317
|
+
}),
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
try {
|
|
321
|
+
return createSuccessResponse(c, { event, room });
|
|
322
|
+
} catch (error) {
|
|
323
|
+
this._logDebug("Could not create onRoomDestroyed response");
|
|
324
|
+
throw error;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
case "storage-destroyed": {
|
|
307
328
|
const room = data.room;
|
|
308
329
|
const encodedState = data.storage;
|
|
309
330
|
|
|
310
331
|
await Promise.resolve(
|
|
311
|
-
this._listeners?.
|
|
332
|
+
this._listeners?.onStorageDestroyed({
|
|
333
|
+
context,
|
|
334
|
+
encodedState,
|
|
335
|
+
platform: this,
|
|
336
|
+
room,
|
|
337
|
+
}),
|
|
312
338
|
);
|
|
313
339
|
|
|
314
340
|
try {
|
|
315
341
|
return createSuccessResponse(c, { event, room });
|
|
316
342
|
} catch (error) {
|
|
317
|
-
this._logDebug("Could not create
|
|
343
|
+
this._logDebug("Could not create onStorageDestroyed response");
|
|
318
344
|
throw error;
|
|
319
345
|
}
|
|
320
346
|
}
|
package/src/schemas.ts
CHANGED
|
@@ -2,7 +2,8 @@ import { z } from "zod";
|
|
|
2
2
|
|
|
3
3
|
export const ZodEventKind = z.union([
|
|
4
4
|
z.literal("initial-storage"),
|
|
5
|
-
z.literal("room-
|
|
5
|
+
z.literal("room-destroyed"),
|
|
6
|
+
z.literal("storage-destroyed"),
|
|
6
7
|
z.literal("user-connected"),
|
|
7
8
|
z.literal("user-disconnected"),
|
|
8
9
|
]);
|
|
@@ -14,8 +15,15 @@ export const ZodEventInitialStorage = z.object({
|
|
|
14
15
|
}),
|
|
15
16
|
});
|
|
16
17
|
|
|
17
|
-
export const
|
|
18
|
-
event: z.literal("room-
|
|
18
|
+
export const ZodEventRoomDestroyed = z.object({
|
|
19
|
+
event: z.literal("room-destroyed"),
|
|
20
|
+
data: z.object({
|
|
21
|
+
room: z.string(),
|
|
22
|
+
}),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export const ZodEventStorageDestroyed = z.object({
|
|
26
|
+
event: z.literal("storage-destroyed"),
|
|
19
27
|
data: z.object({
|
|
20
28
|
room: z.string(),
|
|
21
29
|
storage: z.string().nullable(),
|
|
@@ -50,7 +58,8 @@ export const ZodEventUserDisconnected = z.object({
|
|
|
50
58
|
|
|
51
59
|
export const ZodEvent = z.discriminatedUnion("event", [
|
|
52
60
|
ZodEventInitialStorage,
|
|
53
|
-
|
|
61
|
+
ZodEventRoomDestroyed,
|
|
62
|
+
ZodEventStorageDestroyed,
|
|
54
63
|
ZodEventUserConnected,
|
|
55
64
|
ZodEventUserDisconnected,
|
|
56
65
|
]);
|
|
@@ -61,8 +70,13 @@ export const ZodInitialStorageResponse = z.object({
|
|
|
61
70
|
storage: z.string().nullable(),
|
|
62
71
|
});
|
|
63
72
|
|
|
64
|
-
export const
|
|
65
|
-
event: z.literal("room-
|
|
73
|
+
export const ZodRoomDestroyedResponse = z.object({
|
|
74
|
+
event: z.literal("room-destroyed"),
|
|
75
|
+
room: z.string(),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
export const ZodStorageDestroyedResponse = z.object({
|
|
79
|
+
event: z.literal("storage-destroyed"),
|
|
66
80
|
room: z.string(),
|
|
67
81
|
});
|
|
68
82
|
|
|
@@ -78,7 +92,8 @@ export const ZodUserDisconnectedResponse = z.object({
|
|
|
78
92
|
|
|
79
93
|
export const ZodEventResponse = z.discriminatedUnion("event", [
|
|
80
94
|
ZodInitialStorageResponse,
|
|
81
|
-
|
|
95
|
+
ZodRoomDestroyedResponse,
|
|
96
|
+
ZodStorageDestroyedResponse,
|
|
82
97
|
ZodUserConnectedResponse,
|
|
83
98
|
ZodUserDisconnectedResponse,
|
|
84
99
|
]);
|
package/src/shared/index.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export { createErrorResponse } from "./createErrorResponse";
|
|
2
|
-
export type { CreateErrorResponseParams } from "./createErrorResponse";
|
|
3
2
|
export { createHmac } from "./createHmac";
|
|
4
3
|
export type { CreateHmacParams } from "./createHmac";
|
|
5
4
|
export { createSuccessResponse } from "./createSuccessResponse";
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
BaseUser,
|
|
3
3
|
GetInitialStorageFn,
|
|
4
|
+
IORoomDestroyedEvent,
|
|
5
|
+
IORoomListenerEvent,
|
|
4
6
|
IOUserConnectedEvent,
|
|
5
7
|
IOUserDisconnectedEvent,
|
|
6
8
|
} from "@pluv/io";
|
|
@@ -11,7 +13,8 @@ import type {
|
|
|
11
13
|
ZodEventKind,
|
|
12
14
|
ZodEventResponse,
|
|
13
15
|
ZodInitialStorageResponse,
|
|
14
|
-
|
|
16
|
+
ZodRoomDestroyedResponse,
|
|
17
|
+
ZodStorageDestroyedResponse,
|
|
15
18
|
ZodUserConnectedResponse,
|
|
16
19
|
ZodUserDisconnectedResponse,
|
|
17
20
|
} from "./schemas";
|
|
@@ -20,18 +23,17 @@ export interface PluvIOEndpoints {
|
|
|
20
23
|
createToken: string;
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
export type IORoomListenerEvent<TContext extends Record<string, any>> = {
|
|
24
|
-
context: TContext;
|
|
25
|
-
encodedState: string | null;
|
|
26
|
-
room: string;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
26
|
export type PluvIOListeners<
|
|
30
27
|
TContext extends Record<string, any> = {},
|
|
31
28
|
TUser extends BaseUser = BaseUser,
|
|
32
29
|
> = {
|
|
33
30
|
getInitialStorage?: GetInitialStorageFn<TContext>;
|
|
34
|
-
|
|
31
|
+
onRoomDestroyed: (
|
|
32
|
+
event: IORoomDestroyedEvent<PluvPlatform<TContext>, TContext>,
|
|
33
|
+
) => void;
|
|
34
|
+
onStorageDestroyed: (
|
|
35
|
+
event: IORoomListenerEvent<PluvPlatform<TContext>, TContext>,
|
|
36
|
+
) => void;
|
|
35
37
|
onUserConnected: (
|
|
36
38
|
event: IOUserConnectedEvent<
|
|
37
39
|
PluvPlatform<TContext>,
|
|
@@ -51,7 +53,8 @@ export type PluvIOListeners<
|
|
|
51
53
|
export type EventKind = z.output<typeof ZodEventKind>;
|
|
52
54
|
|
|
53
55
|
export type InitialStorageResponse = z.output<typeof ZodInitialStorageResponse>;
|
|
54
|
-
export type
|
|
56
|
+
export type RoomDestroyedResponse = z.output<typeof ZodRoomDestroyedResponse>;
|
|
57
|
+
export type StorageDestroyedResponse = z.output<typeof ZodStorageDestroyedResponse>;
|
|
55
58
|
export type UserConnectedResponse = z.output<typeof ZodUserConnectedResponse>;
|
|
56
59
|
export type UserDisconnectedResponse = z.output<typeof ZodUserDisconnectedResponse>;
|
|
57
60
|
|
package/tsdown.config.ts
ADDED
package/dist/index.d.ts
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import { CrdtLibraryType, NoopCrdtDocFactory } from '@pluv/crdt';
|
|
2
|
-
import { PluvContext, BaseUser, AbstractPlatform, JWTEncodeParams, AbstractWebSocket, ConvertWebSocketConfig, WebSocketSerializedState, AbstractPlatformConfig, CreateIOParams, PluvIOAuthorize, InferInitContextType } from '@pluv/io';
|
|
3
|
-
import { MaybePromise, BaseUser as BaseUser$1, Id } from '@pluv/types';
|
|
4
|
-
|
|
5
|
-
interface PluvIOEndpoints {
|
|
6
|
-
createToken: string;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
type PublicKey = string | (() => MaybePromise<string>);
|
|
10
|
-
type SecretKey = string | (() => MaybePromise<string>);
|
|
11
|
-
type WebhookSecret = string | (() => MaybePromise<string>);
|
|
12
|
-
interface PluvPlatformConfig<TContext extends Record<string, any> = {}> {
|
|
13
|
-
/**
|
|
14
|
-
* @ignore
|
|
15
|
-
* @readonly
|
|
16
|
-
* @deprecated Internal use only. Changes to this will never be marked as breaking.
|
|
17
|
-
*/
|
|
18
|
-
_defs?: {
|
|
19
|
-
debug?: boolean;
|
|
20
|
-
endpoints?: PluvIOEndpoints | (() => MaybePromise<PluvIOEndpoints>);
|
|
21
|
-
};
|
|
22
|
-
basePath: string;
|
|
23
|
-
context?: PluvContext<any, TContext>;
|
|
24
|
-
publicKey: PublicKey;
|
|
25
|
-
secretKey: SecretKey;
|
|
26
|
-
webhookSecret?: WebhookSecret;
|
|
27
|
-
}
|
|
28
|
-
declare class PluvPlatform<TContext extends Record<string, any> = {}, TUser extends BaseUser = BaseUser> extends AbstractPlatform<any, {}, {}, {
|
|
29
|
-
authorize: {
|
|
30
|
-
secret: false;
|
|
31
|
-
};
|
|
32
|
-
handleMode: "fetch";
|
|
33
|
-
registrationMode: "attached";
|
|
34
|
-
requireAuth: true;
|
|
35
|
-
listeners: {
|
|
36
|
-
onRoomDeleted: true;
|
|
37
|
-
onRoomMessage: false;
|
|
38
|
-
onStorageUpdated: false;
|
|
39
|
-
onUserConnected: true;
|
|
40
|
-
onUserDisconnected: true;
|
|
41
|
-
};
|
|
42
|
-
router: false;
|
|
43
|
-
}> {
|
|
44
|
-
readonly id: string;
|
|
45
|
-
readonly _config: {
|
|
46
|
-
authorize: {
|
|
47
|
-
secret: false;
|
|
48
|
-
};
|
|
49
|
-
handleMode: "fetch";
|
|
50
|
-
registrationMode: "attached";
|
|
51
|
-
requireAuth: true;
|
|
52
|
-
listeners: {
|
|
53
|
-
onRoomDeleted: true;
|
|
54
|
-
onRoomMessage: false;
|
|
55
|
-
onStorageUpdated: false;
|
|
56
|
-
onUserConnected: true;
|
|
57
|
-
onUserDisconnected: true;
|
|
58
|
-
};
|
|
59
|
-
router: false;
|
|
60
|
-
};
|
|
61
|
-
readonly _name = "platformPluv";
|
|
62
|
-
private readonly _app;
|
|
63
|
-
private readonly _basePath;
|
|
64
|
-
private readonly _context;
|
|
65
|
-
private readonly _debug;
|
|
66
|
-
private readonly _endpoints;
|
|
67
|
-
private _getInitialStorage?;
|
|
68
|
-
private _listeners?;
|
|
69
|
-
private readonly _publicKey;
|
|
70
|
-
private readonly _secretKey;
|
|
71
|
-
private readonly _webhookSecret?;
|
|
72
|
-
_createToken: (params: JWTEncodeParams<any, any>) => Promise<string>;
|
|
73
|
-
constructor(params: PluvPlatformConfig);
|
|
74
|
-
acceptWebSocket(webSocket: AbstractWebSocket): Promise<void>;
|
|
75
|
-
convertWebSocket(webSocket: any, config: ConvertWebSocketConfig): AbstractWebSocket;
|
|
76
|
-
getLastPing(webSocket: AbstractWebSocket): number | null;
|
|
77
|
-
getSerializedState(webSocket: any): WebSocketSerializedState | null;
|
|
78
|
-
getSessionId(webSocket: any): string | null;
|
|
79
|
-
getWebSockets(): readonly any[];
|
|
80
|
-
initialize(config: AbstractPlatformConfig<{}>): this;
|
|
81
|
-
parseData(data: string | ArrayBuffer): Record<string, any>;
|
|
82
|
-
randomUUID(): string;
|
|
83
|
-
setSerializedState(webSocket: AbstractWebSocket, state: WebSocketSerializedState): WebSocketSerializedState;
|
|
84
|
-
validateConfig(config: any): void;
|
|
85
|
-
private _webhooksRouter;
|
|
86
|
-
private _getContext;
|
|
87
|
-
private _logDebug;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
type PlatformPluvCreateIOParams<TContext extends Record<string, any> = {}, TUser extends BaseUser$1 = BaseUser$1, TCrdt extends CrdtLibraryType<any> = CrdtLibraryType<NoopCrdtDocFactory>> = Id<PluvPlatformConfig & Omit<CreateIOParams<PluvPlatform, TContext, TUser, TCrdt>, "authorize" | "context" | "limits" | "platform"> & {
|
|
91
|
-
authorize: PluvIOAuthorize<PluvPlatform, TUser, InferInitContextType<PluvPlatform>>;
|
|
92
|
-
context?: PluvContext<PluvPlatform, TContext>;
|
|
93
|
-
}>;
|
|
94
|
-
declare const platformPluv: <TContext extends Record<string, any> = {}, TUser extends BaseUser$1 = BaseUser$1, TCrdt extends CrdtLibraryType<any> = CrdtLibraryType<NoopCrdtDocFactory>>(config: PlatformPluvCreateIOParams<TContext, TUser, TCrdt>) => CreateIOParams<PluvPlatform<TContext, TUser>, TContext, TUser, TCrdt>;
|
|
95
|
-
|
|
96
|
-
export { type PlatformPluvCreateIOParams, type PluvIOEndpoints, PluvPlatform, type PublicKey, type SecretKey, type WebhookSecret, platformPluv };
|