@pluv/io 0.0.0-canary-20261027014949
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/LICENSE +21 -0
- package/README.md +18 -0
- package/dist/index.d.mts +952 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +3591 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["baseProcedureFactory","__PLUV_VERSION","__PLUV_VERSION"],"sources":["../src/utils/ArmedWait.ts","../src/utils/assertExhaustive.ts","../src/constants.ts","../src/utils/oneLine.ts","../src/utils/assertPresenceFanoutBudget.ts","../src/PluvRouter.ts","../src/utils/assertEventNames.ts","../src/utils/createInternalPluvRouter.ts","../src/utils/getLiveSessions.ts","../src/utils/sessionKind.ts","../src/utils/getMyConnectionIds.ts","../src/utils/getRoomStatsFromSessions.ts","../src/utils/groupLiveUsers.ts","../src/utils/invokeProcedureResolvers.ts","../src/utils/isThenable.ts","../src/utils/listLiveUsers.ts","../src/utils/resolveListUsersLimit.ts","../src/utils/pageLiveUsers.ts","../src/utils/parseOperatorUser.ts","../src/utils/parsePluvSchema.ts","../src/utils/pickBy.ts","../src/utils/resolveIOSecret.ts","../src/utils/throttle.ts","../src/AbstractPersistence.ts","../src/Persistence.ts","../src/AbstractPubSub.ts","../src/PubSub.ts","../src/AbstractPlatform.ts","../src/roomEffects.ts","../src/AbstractWebSocket.ts","../src/CommitGate.ts","../src/authorize.ts","../src/PluvProcedure.ts","../src/createSessionRouter.ts","../src/createStorageRouter.ts","../src/createBaseRouter.ts","../src/RoomStorage.ts","../src/StorageChangeLog.ts","../src/StorageReservations.ts","../src/StorageEdits.ts","../src/StorageSnapshot.ts","../src/IORoom.ts","../src/version.generated.ts","../src/PluvServer.ts","../src/PluvIO.ts","../src/createIO.ts","../src/internal.ts","../src/ExclusiveUntil.ts","../src/JoinQueue.ts","../src/RoomSessions.ts","../src/RoomSessionManager/createHostTreatyProcedureProxy.ts","../src/RoomSessionManager/readTreatySchema.ts","../src/RoomSessionManager/resolveHostTreatyProcedureSenderId.ts","../src/RoomSessionManager/RoomSessionManager.ts","../src/manageSessions.ts"],"sourcesContent":["/**\n * The first `arm` starts one wait. Another `arm` during that wait does nothing.\n * When the wait ends, `work` runs. `keepAlive` covers the wait and that work.\n * `clear` cancels a pending wait and settles `keepAlive` without running `work`.\n */\nexport class ArmedWait {\n private _done: (() => void) | null = null;\n private _timer: ReturnType<typeof setTimeout> | null = null;\n\n public constructor(\n private readonly _intervalMs: number,\n private readonly _keepAlive: (promise: Promise<unknown>) => void,\n ) {}\n\n public arm(work: () => Promise<void>): void {\n if (this._timer) return;\n\n const pending = new Promise<void>((resolve) => {\n this._done = resolve;\n this._timer = setTimeout(() => {\n this._timer = null;\n this._done = null;\n void work().finally(resolve);\n }, this._intervalMs);\n });\n\n this._keepAlive(pending);\n }\n\n public clear(): void {\n if (!this._timer) return;\n\n clearTimeout(this._timer);\n this._timer = null;\n const done = this._done;\n\n this._done = null;\n done?.();\n }\n}\n","export const assertExhaustive = (value: never): never => {\n // oxlint-disable-next-line typescript/restrict-template-expressions\n throw new Error(`Unhandled value: ${value}`);\n};\n","import type { ServerOriginEvent } from \"@pluv/types\";\n\nexport const GARBAGE_COLLECT_INTERVAL_MS = 60_000;\nexport const JS_IDENTIFIER = /^[a-z_$][a-z0-9_$]*$/i;\nexport const MAX_PRESENCE_SIZE_BYTES = 512;\nexport const MAX_STORAGE_SIZE_BYTES = 31_457_280;\nexport const MAX_USER_ID_LENGTH = 128;\nexport const MAX_USER_SIZE_BYTES = 512;\nexport const PING_TIMEOUT_MS = 30_000;\n\nexport const PRESENCE_FANOUT_BUDGET = 100_000;\nexport const DEFAULT_MAX_CONNECTIONS = 256;\nexport const ROOM_STATS_THROTTLE_MS = 150;\nexport const STORAGE_EDITS_INTERVAL_MS = 1_000;\nexport const STORAGE_SNAPSHOT_INTERVAL_MS = 1_000;\nexport const LIST_USERS_DEFAULT_LIMIT = 50;\nexport const LIST_USERS_MAX_LIMIT = 100;\n\nexport const SERVER_ORIGIN_EVENTS = [\n \"$error\",\n \"$roomStats\",\n \"$syncStateReceived\",\n] as const satisfies readonly ServerOriginEvent[];\n\nexport const isServerOriginEvent = (type: string): type is ServerOriginEvent => {\n return (SERVER_ORIGIN_EVENTS as readonly string[]).includes(type);\n};\n","export const oneLine = (strings: TemplateStringsArray, ...values: unknown[]): string => {\n return strings\n .map((str) => str.replace(/\\s+/g, \" \"))\n .reduce((acc, str, i) => acc + str + (i < values.length ? values[i] : \"\"), \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n};\n","import { DEFAULT_MAX_CONNECTIONS, PRESENCE_FANOUT_BUDGET } from \"../constants\";\nimport type { PluvIOLimits } from \"../types\";\nimport { oneLine } from \"./oneLine\";\n\nexport const resolveMaxConnections = (limits: Pick<PluvIOLimits, \"maxConnections\">): number => {\n const maxConnections = limits.maxConnections ?? DEFAULT_MAX_CONNECTIONS;\n\n if (!Number.isInteger(maxConnections) || maxConnections < 1) {\n throw new Error(\n `limits.maxConnections must be a positive integer. Received: ${String(limits.maxConnections)}.`,\n );\n }\n\n return maxConnections;\n};\n\nexport const assertPresenceFanoutBudget = (limits: PluvIOLimits): void => {\n const maxConnections = resolveMaxConnections(limits);\n const slots = maxConnections * maxConnections;\n\n if (slots <= PRESENCE_FANOUT_BUDGET) return;\n if (limits.dangerouslyAllowHighPresenceFanout) return;\n\n throw new Error(oneLine`\n maxConnections (${maxConnections.toLocaleString()}) is too high.\n Set dangerouslyAllowHighPresenceFanout: true to allow this.\n `);\n};\n","import type { IORouterLike, SetKey } from \"@pluv/types\";\nimport type { IODefs } from \"./IODefs\";\nimport type { PluvProcedure } from \"./PluvProcedure\";\nimport { assertEventNames, createInternalPluvRouter } from \"./utils\";\n\nexport type PluvRouterEventConfig<T extends IODefs = IODefs> = {\n [P: string]: Pick<PluvProcedure<T, any, any>, \"config\">;\n};\n\nexport type MergedRouter<\n TRouters extends PluvRouter<any>[] = [],\n T extends IODefs = IODefs,\n TRoot extends Record<string, any> = {},\n> = TRouters extends [infer IHead extends PluvRouter<any>, ...infer ITail extends PluvRouter<any>[]]\n ? MergedRouter<ITail, T, TRoot & IHead[\"_defs\"][\"events\"]>\n : PluvRouter<SetKey<T, \"events\", TRoot>>;\n\nexport class PluvRouter<T extends IODefs = IODefs> implements IORouterLike<T[\"events\"]> {\n readonly _defs: { events: T[\"events\"] } = { events: {} as T[\"events\"] };\n /** Event names this router defines. */\n readonly eventNames: ReadonlySet<string> = new Set();\n\n constructor(events: T[\"events\"]) {\n const names = Object.keys(events as Record<string, unknown>);\n\n assertEventNames(names, { allowDollar: false });\n this._defs = { events };\n this.eventNames = new Set(names);\n }\n\n public static merge<TRouters extends PluvRouter<any>[]>(\n ...routers: TRouters\n ): MergedRouter<TRouters> {\n const seen = new Set<string>();\n\n for (const router of routers) {\n for (const name of Object.keys(router._defs.events as Record<string, unknown>)) {\n if (seen.has(name)) {\n throw new Error(`Duplicate event name \"${name}\" when merging routers`);\n }\n\n seen.add(name);\n }\n }\n\n const events = Object.assign(\n Object.create(null),\n ...routers.map((router) => router._defs.events),\n );\n\n return createInternalPluvRouter(events) as MergedRouter<TRouters>;\n }\n}\n","import { JS_IDENTIFIER } from \"../constants\";\nimport { oneLine } from \"./oneLine\";\n\nexport type AssertEventNamesOptions = {\n allowDollar?: boolean;\n};\n\nexport const assertEventNames = (\n names: readonly string[],\n options: AssertEventNamesOptions = {},\n): void => {\n const allowDollar = options.allowDollar ?? false;\n\n for (const name of names) {\n if (!allowDollar && name.includes(\"$\")) {\n throw new Error(oneLine`\n Invalid event name. Event names must not contain $: \"${name}\"\n `);\n }\n\n if (!JS_IDENTIFIER.test(name)) {\n throw new Error(\n `Invalid event name. Event names must be formatted as valid JavaScript variable names: \"${name}\"`,\n );\n }\n }\n};\n","import type { IODefs } from \"../IODefs\";\nimport { PluvRouter } from \"../PluvRouter\";\nimport { assertEventNames } from \"./assertEventNames\";\n\n/**\n * Build a router that may include `$` protocol events. Not part of the public\n * package API — import via `__internal` or sibling modules under `@pluv/io`.\n */\nexport const createInternalPluvRouter = <T extends IODefs = IODefs>(\n events: T[\"events\"],\n): PluvRouter<T> => {\n const names = Object.keys(events as Record<string, unknown>);\n\n assertEventNames(names, { allowDollar: true });\n\n const router = Object.create(PluvRouter.prototype) as PluvRouter<T>;\n (router as { _defs: PluvRouter<T>[\"_defs\"] })._defs = { events };\n (router as { eventNames: PluvRouter<T>[\"eventNames\"] }).eventNames = new Set(names);\n\n return router;\n};\n","import type { WebSocketSession } from \"../types\";\n\nexport const getLiveSessions = (\n sessions: readonly WebSocketSession<any>[],\n): readonly WebSocketSession<any>[] => {\n return sessions.filter((session) => !session.quit);\n};\n","import type { OperatorUser, ParticipantKind } from \"@pluv/types\";\nimport { assertExhaustive } from \"./assertExhaustive\";\n\nexport const getSessionKind = (session: { kind: ParticipantKind }): ParticipantKind => {\n switch (session.kind) {\n case \"operator\":\n case \"user\":\n return session.kind;\n default:\n return assertExhaustive(session.kind);\n }\n};\n\nexport const getSessionOperator = (session: {\n kind: ParticipantKind;\n operator?: OperatorUser | null;\n}): OperatorUser | null => {\n const kind = getSessionKind(session);\n\n switch (kind) {\n case \"operator\":\n return session.operator ?? null;\n case \"user\":\n return null;\n default:\n return assertExhaustive(kind);\n }\n};\n","import type { WebSocketSession } from \"../types\";\nimport { getLiveSessions } from \"./getLiveSessions\";\nimport { getSessionKind } from \"./sessionKind\";\n\nexport const getMyConnectionIds = (\n sessions: readonly WebSocketSession<any>[],\n requester: WebSocketSession<any> | null,\n): string[] => {\n if (!requester) return [];\n\n const live = getLiveSessions(sessions);\n const kind = getSessionKind(requester);\n const userId = requester.user?.id;\n\n if (typeof userId !== \"string\") return [requester.id];\n\n return live\n .filter((session) => getSessionKind(session) === kind && session.user?.id === userId)\n .map((session) => session.id);\n};\n","import type { RoomStatsByKind } from \"@pluv/types\";\nimport type { WebSocketSession } from \"../types\";\nimport { assertExhaustive } from \"./assertExhaustive\";\nimport { getLiveSessions } from \"./getLiveSessions\";\nimport { getSessionKind } from \"./sessionKind\";\n\nexport const getRoomStatsFromSessions = (\n sessions: readonly WebSocketSession<any>[],\n): RoomStatsByKind => {\n const live = getLiveSessions(sessions);\n const occupantIds = new Set<string>();\n const operatorIds = new Set<string>();\n let occupantConnections = 0;\n let operatorConnections = 0;\n\n for (const session of live) {\n const kind = getSessionKind(session);\n const userId = session.user?.id;\n\n switch (kind) {\n case \"operator\": {\n operatorConnections += 1;\n if (typeof userId === \"string\") operatorIds.add(userId);\n break;\n }\n case \"user\": {\n occupantConnections += 1;\n if (typeof userId === \"string\") occupantIds.add(userId);\n break;\n }\n default:\n assertExhaustive(kind);\n }\n }\n\n return {\n user: {\n connectionCount: occupantConnections,\n userCount: occupantIds.size,\n },\n operator: {\n connectionCount: operatorConnections,\n userCount: operatorIds.size,\n },\n };\n};\n","import type { JsonObject, OperatorUser, ParticipantKind } from \"@pluv/types\";\nimport type { WebSocketSession } from \"../types\";\nimport { assertExhaustive } from \"./assertExhaustive\";\nimport { getLiveSessions } from \"./getLiveSessions\";\nimport { getSessionKind, getSessionOperator } from \"./sessionKind\";\n\nexport type GroupedRoomUser = {\n connectionIds: string[];\n data: JsonObject;\n key: string;\n kind: ParticipantKind;\n operator: OperatorUser | null;\n presence: JsonObject | null;\n};\n\ntype LiveUserKey = {\n id: string;\n kind: ParticipantKind;\n};\n\n/**\n * Group live sockets by `(kind, user id)`. Extra tabs of the same kind share\n * one row. The socket with the newest `seq.presence` supplies `presence`,\n * `data`, and `operator`. `excludeSessionId` drops that person's whole row.\n * `key` is `user.id`.\n */\nexport const groupLiveUsers = (\n sessions: readonly WebSocketSession<any>[],\n options: { excludeSessionId?: string; kinds?: readonly ParticipantKind[] } = {},\n): GroupedRoomUser[] => {\n const live = getLiveSessions(sessions);\n const excluded = options.excludeSessionId\n ? live.find((session) => session.id === options.excludeSessionId)\n : null;\n const excludedRef = excluded ? liveUserKey(excluded) : null;\n const kinds = options.kinds ? new Set(options.kinds) : null;\n const grouped = {\n operator: new Map<string, GroupedRoomUser>(),\n user: new Map<string, GroupedRoomUser>(),\n };\n const presenceSeqs = {\n operator: new Map<string, number | null>(),\n user: new Map<string, number | null>(),\n };\n\n for (const session of live) {\n const ref = liveUserKey(session);\n if (!ref) continue;\n if (kinds && !kinds.has(ref.kind)) continue;\n if (sameParticipant(ref, excludedRef)) continue;\n\n const rows = rowsForKind(grouped, ref.kind);\n const seqs = seqsForKind(presenceSeqs, ref.kind);\n const row = rows.get(ref.id);\n const presenceSeq = session.seq.presence;\n const operator = getSessionOperator(session);\n\n if (!row) {\n rows.set(ref.id, {\n connectionIds: [session.id],\n data: session.user as JsonObject,\n key: ref.id,\n kind: ref.kind,\n operator,\n presence: session.presence,\n });\n seqs.set(ref.id, presenceSeq);\n continue;\n }\n\n row.connectionIds.push(session.id);\n\n const previousSeq = seqs.get(ref.id) ?? null;\n\n if (typeof presenceSeq !== \"number\") continue;\n if (typeof previousSeq === \"number\" && presenceSeq <= previousSeq) continue;\n\n row.data = session.user as JsonObject;\n row.operator = operator;\n row.presence = session.presence;\n seqs.set(ref.id, presenceSeq);\n }\n\n return [...grouped.user.values(), ...grouped.operator.values()];\n};\n\nconst liveUserKey = (session: WebSocketSession<any>): LiveUserKey | null => {\n const kind = getSessionKind(session);\n const id = session.user?.id;\n\n if (typeof id !== \"string\") return null;\n\n return { kind, id };\n};\n\nconst sameParticipant = (a: LiveUserKey | null, b: LiveUserKey | null): boolean => {\n return !!a && !!b && a.kind === b.kind && a.id === b.id;\n};\n\nconst rowsForKind = (\n grouped: {\n operator: Map<string, GroupedRoomUser>;\n user: Map<string, GroupedRoomUser>;\n },\n kind: ParticipantKind,\n): Map<string, GroupedRoomUser> => {\n switch (kind) {\n case \"operator\":\n return grouped.operator;\n case \"user\":\n return grouped.user;\n default:\n return assertExhaustive(kind);\n }\n};\n\nconst seqsForKind = (\n seqs: {\n operator: Map<string, number | null>;\n user: Map<string, number | null>;\n },\n kind: ParticipantKind,\n): Map<string, number | null> => {\n switch (kind) {\n case \"operator\":\n return seqs.operator;\n case \"user\":\n return seqs.user;\n default:\n return assertExhaustive(kind);\n }\n};\n","export type ProcedureResolverResults =\n | { ok: true; broadcast: unknown; self: unknown }\n | { ok: false; error: unknown };\n\n/**\n * Runs `self` first. A synchronous throw must not start `broadcast`.\n * If `broadcast` throws after `self` returned a promise, that work still runs.\n * The promise stays attached so its rejection is not unhandled.\n */\nexport const invokeProcedureResolvers = (resolvers: {\n broadcast: () => unknown;\n self: () => unknown;\n}): ProcedureResolverResults => {\n let selfResult: unknown;\n\n try {\n selfResult = resolvers.self();\n } catch (error) {\n return { ok: false, error };\n }\n\n try {\n return { ok: true, broadcast: resolvers.broadcast(), self: selfResult };\n } catch (error) {\n void Promise.resolve(selfResult).catch(() => undefined);\n\n return { ok: false, error };\n }\n};\n","export const isThenable = (value: unknown): value is PromiseLike<unknown> =>\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as PromiseLike<unknown>).then === \"function\";\n","import type { JsonObject, ListUsersCursor, OperatorUser, ParticipantKind } from \"@pluv/types\";\nimport type { WebSocketSession } from \"../types\";\nimport { assertExhaustive } from \"./assertExhaustive\";\nimport { groupLiveUsers } from \"./groupLiveUsers\";\n\nconst participantOrder = (kind: ParticipantKind): number => {\n switch (kind) {\n case \"user\":\n return 0;\n case \"operator\":\n return 1;\n default:\n return assertExhaustive(kind);\n }\n};\n\nconst compareToCursor = (\n row: { kind: ParticipantKind; key: string },\n cursor: ListUsersCursor,\n): number => {\n const byKind = participantOrder(row.kind) - participantOrder(cursor.kind);\n\n if (byKind !== 0) return byKind;\n if (row.key < cursor.id) return -1;\n if (row.key > cursor.id) return 1;\n\n return 0;\n};\n\nexport const listLiveUsers = (\n sessions: readonly WebSocketSession<any>[],\n options: { cursor?: ListUsersCursor | null; kinds?: readonly ParticipantKind[]; limit: number },\n): {\n pageInfo: { endCursor: ListUsersCursor | null; hasNextPage: boolean };\n users: { data: JsonObject; kind: ParticipantKind; operator: OperatorUser | null }[];\n} => {\n const rows = groupLiveUsers(sessions, {\n kinds: options.kinds ?? [\"user\"],\n }).toSorted((left, right) => {\n const byKind = participantOrder(left.kind) - participantOrder(right.kind);\n\n if (byKind !== 0) return byKind;\n if (left.key < right.key) return -1;\n if (left.key > right.key) return 1;\n\n return 0;\n });\n const cursor = options.cursor ?? null;\n const startIndex =\n cursor == null ? 0 : rows.findIndex((row) => compareToCursor(row, cursor) > 0);\n const from = startIndex < 0 ? rows.length : startIndex;\n const slice = rows.slice(from, from + options.limit);\n const hasNextPage = from + slice.length < rows.length;\n const last = slice.at(-1);\n const endCursor = last ? { kind: last.kind, id: last.key } : null;\n\n return {\n pageInfo: { endCursor, hasNextPage },\n users: slice.map((row) => ({\n data: row.data,\n kind: row.kind,\n operator: row.operator,\n })),\n };\n};\n","import type { ListUsersError } from \"@pluv/types\";\nimport { LIST_USERS_DEFAULT_LIMIT, LIST_USERS_MAX_LIMIT } from \"../constants\";\n\nexport const resolveListUsersLimit = (\n limit?: number | null,\n): { success: true; limit: number } | { success: false; error: ListUsersError } => {\n const resolved = limit ?? LIST_USERS_DEFAULT_LIMIT;\n\n if (!Number.isInteger(resolved) || resolved < 1 || resolved > LIST_USERS_MAX_LIMIT) {\n return {\n success: false,\n error: {\n code: \"INVALID_LIMIT\",\n message: `Invalid listUsers limit. Limit must be an integer from 1 to ${LIST_USERS_MAX_LIMIT.toLocaleString()}. Received: ${String(limit)}.`,\n },\n };\n }\n\n return { success: true, limit: resolved };\n};\n","import type { ListUsersOptions, ListUsersResult } from \"@pluv/types\";\nimport type { WebSocketSession } from \"../types\";\nimport { listLiveUsers } from \"./listLiveUsers\";\nimport { resolveListUsersLimit } from \"./resolveListUsersLimit\";\n\nexport const pageLiveUsers = (\n sessions: readonly WebSocketSession<any>[],\n options: ListUsersOptions = {},\n): ListUsersResult<any> => {\n const resolved = resolveListUsersLimit(options.limit);\n\n if (!resolved.success) return resolved;\n\n return {\n success: true,\n ...listLiveUsers(sessions, {\n cursor: options.cursor ?? null,\n kinds: options.kinds,\n limit: resolved.limit,\n }),\n } as ListUsersResult<any>;\n};\n","import type { OperatorUser } from \"@pluv/types\";\n\nexport const parseOperatorUser = (value: unknown): OperatorUser => {\n if (!value || typeof value !== \"object\") {\n throw new Error(\"Invalid operator\");\n }\n\n const record = value as Record<string, unknown>;\n\n if (typeof record.id !== \"string\" || !record.id) {\n throw new Error(\"Invalid operator id\");\n }\n\n if (typeof record.name !== \"string\") {\n throw new Error(\"Invalid operator name\");\n }\n\n if (record.imageUrl !== null && typeof record.imageUrl !== \"string\") {\n throw new Error(\"Invalid operator imageUrl\");\n }\n\n return {\n id: record.id,\n name: record.name,\n imageUrl: record.imageUrl,\n };\n};\n","import type { JsonObject, StandardSchemaV1 } from \"@pluv/types\";\n\nexport function parsePluvSchema<TData extends JsonObject>(\n schema: StandardSchemaV1<unknown, TData>,\n data: unknown,\n): TData {\n const result = schema[\"~standard\"].validate(data);\n\n if (result instanceof Promise) {\n throw new Error(\"Async schemas are not supported. Schema validate() must be synchronous.\");\n }\n\n if (result.issues) {\n const message = result.issues[0]?.message ?? \"Invalid input\";\n\n throw new Error(message);\n }\n\n return result.value as TData;\n}\n","export const pickBy = <T extends Record<string, any>>(\n obj: T,\n by: (value: T[keyof T]) => boolean,\n): Partial<T> => {\n const result: Partial<T> = {};\n const keys: (keyof T)[] = Object.keys(obj);\n\n for (let i = 0; i < keys.length; ++i) {\n const key = keys[i];\n const value = obj[key];\n\n if (by(value)) result[key] = value;\n }\n\n return result;\n};\n","/**\n * Resolve a static or context-function JWT secret.\n */\nexport const resolveIOSecret = (\n secret: string | ((context: any) => string) | undefined,\n context: any,\n): string | undefined => {\n if (typeof secret === \"function\") return secret(context);\n\n return secret;\n};\n","export type Throttle = {\n cancel: () => void;\n schedule: () => void;\n};\n\nexport const throttle = (fn: () => void | Promise<void>, options: { wait: number }): Throttle => {\n const { wait } = options;\n\n let lastInvokeMs = Number.NEGATIVE_INFINITY;\n let pending = false;\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const flush = (): void => {\n lastInvokeMs = Date.now();\n pending = false;\n void fn();\n };\n\n const schedule = (): void => {\n pending = true;\n\n if (timer) return;\n\n const remaining = wait - (Date.now() - lastInvokeMs);\n\n timer = setTimeout(\n () => {\n timer = null;\n\n if (!pending) return;\n\n flush();\n },\n remaining <= 0 ? 0 : remaining,\n );\n };\n\n const cancel = (): void => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n\n pending = false;\n };\n\n return { cancel, schedule };\n};\n","import type { JsonObject } from \"@pluv/types\";\n\nexport abstract class AbstractPersistence {\n public abstract addUser(\n room: string,\n connectionId: string,\n user: JsonObject | null,\n ): Promise<void>;\n\n public abstract deleteStorageState(room: string): Promise<void>;\n\n public abstract deleteUser(room: string, connectionId: string): Promise<void>;\n\n public abstract deleteUsers(room: string): Promise<void>;\n\n public abstract getStorageState(room: string): Promise<string | null>;\n\n public abstract getUser(room: string, connectionId: string): Promise<JsonObject | null>;\n\n public abstract getUsers(\n room: string,\n ): Promise<Map<[connectionId: string][0], JsonObject | null>>;\n\n public abstract getUsersSize(room: string): Promise<number>;\n\n public abstract initialize(roomContext: any): typeof this;\n\n public abstract setStorageState(room: string, state: string): Promise<void>;\n}\n","import type { JsonObject } from \"@pluv/types\";\nimport { AbstractPersistence } from \"./AbstractPersistence\";\n\nexport class Persistence extends AbstractPersistence {\n private _storages = new Map<string, string>();\n private _users = new Map<string, Map<string, JsonObject | null>>();\n\n public addUser(room: string, connectionId: string, user: JsonObject | null): Promise<void> {\n const users = this._users.get(room) ?? new Map<string, JsonObject | null>();\n\n this._users.set(room, users);\n users.set(connectionId, user);\n\n return Promise.resolve();\n }\n\n public deleteStorageState(room: string): Promise<void> {\n this._storages.delete(room);\n\n return Promise.resolve();\n }\n\n public async deleteUser(room: string, connectionId: string): Promise<void> {\n const users = this._users.get(room);\n\n if (!users) return;\n\n users.delete(connectionId);\n\n if (!users.size) {\n await this.deleteUsers(room);\n await this.deleteStorageState(room);\n }\n\n return Promise.resolve();\n }\n\n public deleteUsers(room: string): Promise<void> {\n this._users.delete(room);\n\n return Promise.resolve();\n }\n\n public getStorageState(room: string): Promise<string | null> {\n const storage = this._storages.get(room) ?? null;\n\n return Promise.resolve(storage);\n }\n\n public getUser(room: string, connectionId: string): Promise<JsonObject | null> {\n const user = this._users.get(room)?.get(connectionId);\n\n return Promise.resolve(user ?? null);\n }\n\n public async getUsers(room: string): Promise<Map<string, JsonObject | null>> {\n const users = this._users.get(room);\n\n if (!users) return new Map();\n\n return users;\n }\n\n public async getUsersSize(room: string): Promise<number> {\n return this._users.get(room)?.size ?? 0;\n }\n\n public initialize(roomContext: any): this {\n return this;\n }\n\n public setStorageState(room: string, state: string): Promise<void> {\n this._storages.set(room, state);\n\n return Promise.resolve();\n }\n}\n","import type { IOEventMessage, IOLike, InferIOOutput } from \"@pluv/types\";\nimport type { SendMessageOptions } from \"./types\";\n\nexport type IOPubSubEventMessage<\n TIO extends IOLike,\n TEvent extends keyof InferIOOutput<TIO> = keyof InferIOOutput<TIO>,\n> = IOEventMessage<TIO, TEvent> & {\n options?: SendMessageOptions;\n};\n\nexport abstract class AbstractPubSub {\n public abstract publish(roomName: string, payload: IOPubSubEventMessage<any>): Promise<void>;\n\n public abstract subscribe(\n roomName: string,\n onMessage: (message: IOPubSubEventMessage<any>) => void,\n ): Promise<number>;\n\n public abstract unsubscribe(subscriptionId: number): void;\n}\n","import type { IOPubSubEventMessage } from \"./AbstractPubSub\";\nimport { AbstractPubSub } from \"./AbstractPubSub\";\n\ntype PubSubHandler = (message: IOPubSubEventMessage<any>) => void | Promise<void>;\n\nexport class PubSub extends AbstractPubSub {\n private _nextId: number = 0;\n private _rooms = new Map<string, Map<number, PubSubHandler>>();\n\n public async publish(roomName: string, payload: IOPubSubEventMessage<any>): Promise<void> {\n const room = this._rooms.get(roomName);\n\n if (!room?.size) return;\n\n await Promise.all([...room.values()].map((handler) => Promise.resolve(handler(payload))));\n }\n\n public subscribe(roomName: string, onMessage: PubSubHandler): Promise<number> {\n const id = this._nextId++;\n const room = this._rooms.get(roomName) ?? new Map<number, PubSubHandler>();\n\n room.set(id, onMessage);\n this._rooms.set(roomName, room);\n\n return Promise.resolve(id);\n }\n\n public unsubscribe(subscriptionId: number): void {\n for (const [roomName, room] of this._rooms) {\n if (!room.delete(subscriptionId)) continue;\n\n if (room.size === 0) this._rooms.delete(roomName);\n\n return;\n }\n }\n}\n","import type { AbstractPersistence } from \"./AbstractPersistence\";\nimport type { AbstractPubSub } from \"./AbstractPubSub\";\nimport type { AbstractWebSocket, InferWebSocketSource } from \"./AbstractWebSocket\";\nimport type { JWTEncodeParams } from \"./authorize\";\nimport { Persistence } from \"./Persistence\";\nimport { PubSub } from \"./PubSub\";\nimport type { ResolvedPluvIOAuthorize, WebSocketSerializedState } from \"./types\";\nimport { oneLine } from \"./utils\";\n\nexport type InferPlatformWebSocketType<TPlatform extends AbstractPlatform> =\n TPlatform extends AbstractPlatform<infer IAbstractWebSocket> ? IAbstractWebSocket : never;\n\nexport type InferPlatformWebSocketSource<TPlatform> =\n TPlatform extends AbstractPlatform<infer IAbstractWebSocket>\n ? InferWebSocketSource<IAbstractWebSocket>\n : never;\n\nexport type InferInitContextType<TPlatform extends AbstractPlatform> =\n TPlatform extends AbstractPlatform<any, infer IInitContext> ? IInitContext : never;\n\nexport type InferRoomContextType<TPlatform extends AbstractPlatform> =\n TPlatform extends AbstractPlatform<any, any, infer IRoomContext> ? IRoomContext : never;\n\nexport type AbstractPlatformConfig<TRoomContext extends Record<string, any> = {}> = {\n persistence?: AbstractPersistence;\n pubSub?: AbstractPubSub;\n roomContext?: TRoomContext;\n};\n\nexport interface ConvertWebSocketConfig {\n room: string;\n}\n\nexport abstract class AbstractPlatform<\n TWebSocket extends AbstractWebSocket<any> = AbstractWebSocket<any>,\n TInitContext extends Record<string, any> = {},\n TRoomContext extends Record<string, any> = {},\n> {\n protected readonly _initContext: TInitContext | undefined;\n protected readonly _roomContext: TRoomContext | undefined;\n\n private _initialized: boolean = false;\n private readonly _keptAlive = new Set<Promise<unknown>>();\n\n public persistence: AbstractPersistence;\n public pubSub: AbstractPubSub;\n\n public abstract readonly id: string;\n public readonly _createToken?: (\n params: JWTEncodeParams<any, any> & {\n authorize: ResolvedPluvIOAuthorize;\n },\n ) => Promise<string>;\n public abstract readonly _name: string;\n\n constructor(config: AbstractPlatformConfig<TRoomContext> = {}) {\n const { roomContext, persistence, pubSub } = config;\n\n (this as any)._meta = (config as any)._meta;\n if (!!roomContext) this._roomContext = roomContext;\n\n this.persistence = persistence ?? new Persistence();\n this.pubSub = pubSub ?? new PubSub();\n }\n\n public abstract acceptWebSocket(webSocket: AbstractWebSocket): Promise<void>;\n\n public abstract convertWebSocket(\n webSocket: InferWebSocketSource<TWebSocket>,\n config: ConvertWebSocketConfig,\n ): AbstractWebSocket;\n\n public abstract getLastPing(webSocket: AbstractWebSocket): number | null;\n\n public abstract getSerializedState(\n webSocket: InferWebSocketSource<TWebSocket>,\n ): WebSocketSerializedState | null;\n\n public abstract getSessionId(webSocket: InferWebSocketSource<TWebSocket>): string | null;\n\n public abstract getWebSockets(): readonly InferWebSocketSource<TWebSocket>[];\n\n public abstract initialize(config: AbstractPlatformConfig<TRoomContext>): this;\n\n public abstract parseData(data: string | ArrayBuffer): Record<string, any>;\n\n public abstract randomUUID(): string;\n\n public abstract setSerializedState(\n webSocket: AbstractWebSocket,\n state: WebSocketSerializedState,\n ): WebSocketSerializedState;\n\n /**\n * Retain `promise` until it settles. Cloudflare uses this to keep the isolate awake.\n * The default holds the reference and does nothing else.\n */\n public keepAlive(promise: Promise<unknown>): void {\n this._keptAlive.add(promise);\n void promise.finally(() => {\n this._keptAlive.delete(promise);\n });\n }\n\n /**\n * Normalize register/createToken init context before authorize runs.\n * Platforms may convert runtime-specific request types (e.g. Node `IncomingMessage`).\n */\n public normalizeInitContext(initContext: TInitContext): TInitContext {\n return initContext;\n }\n\n public validateConfig(config: any): void {}\n\n protected _initialize(): typeof this {\n if (this._initialized) {\n throw new Error(oneLine`\n Platform is already initialized. The \\`platform\\` factory passed to\n \\`createIO().platform(...)\\` must return a new platform instance each\n time it is called (e.g. \\`platformNode()\\`), not reuse one.\n `);\n }\n\n this._initialized = true;\n\n return this;\n }\n}\n","import type { IODefs } from \"./IODefs\";\nimport type { RoomEffects, Suspended } from \"./types\";\nimport { isThenable } from \"./utils/isThenable\";\n\nconst DEFERRED_RESULT = \"$u\" as const;\n\n/** A handler promise the queue must not wait on. The session manager settles this on a later join. */\nexport type DeferredResult<T> = { readonly [DEFERRED_RESULT]: Promise<T> };\n\nexport const deferredResult = <T>(promise: Promise<T>): DeferredResult<T> => {\n return Object.defineProperty({} as DeferredResult<T>, DEFERRED_RESULT, { value: promise });\n};\n\nexport const isDeferredResult = <T>(value: T | DeferredResult<T>): value is DeferredResult<T> => {\n if (typeof value !== \"object\" || value === null || !(DEFERRED_RESULT in value)) return false;\n\n const descriptor = Object.getOwnPropertyDescriptor(value, DEFERRED_RESULT);\n\n return descriptor?.enumerable === false && isThenable(descriptor.value);\n};\n\nexport const deferredResultPromise = <T>(result: DeferredResult<T>): Promise<T> =>\n result[DEFERRED_RESULT];\n\nexport const isSuspended = (value: unknown): value is Suspended =>\n typeof value === \"object\" &&\n value !== null &&\n \"suspended\" in value &&\n (value as { suspended?: unknown }).suspended === true;\n\nexport const isErrorMessage = (value: unknown): value is { message: string } => {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"message\" in value &&\n typeof value.message === \"string\"\n );\n};\n\nexport const emptyRoomEffects = <T extends IODefs = IODefs>(): RoomEffects<T> => ({\n attachments: [],\n broadcast: [],\n closes: [],\n connectionId: null,\n destroy: false,\n error: null,\n self: [],\n storageDirty: false,\n});\n","import type { BaseUser, IOEventMessage, JsonObject, MaybePromise } from \"@pluv/types\";\nimport { isErrorMessage } from \"./roomEffects\";\nimport type { AbstractPersistence } from \"./AbstractPersistence\";\nimport type { AbstractPlatform } from \"./AbstractPlatform\";\nimport type { WebSocketSerializedState, WebSocketSession } from \"./types\";\n\nexport type AbstractEvent = {};\n\nexport type AbstractCloseEvent = AbstractEvent & {\n readonly code: number;\n readonly reason: string;\n};\n\nexport type AbstractMessageEvent<T = any> = AbstractEvent & {\n readonly data: T;\n};\n\nexport type AbstractErrorEvent = AbstractEvent & {\n error: unknown;\n message?: string;\n};\n\nexport interface AbstractEventMap {\n close: AbstractCloseEvent;\n message: AbstractMessageEvent;\n error: AbstractErrorEvent;\n}\n\nexport type EventType = keyof AbstractEventMap;\n\nexport interface AbstractWebSocketHandleErrorParams {\n error: unknown;\n message?: string;\n room: string;\n session?: WebSocketSession<any>;\n}\n\nexport type AbstractListener<TType extends keyof AbstractEventMap> = (\n event: AbstractEventMap[TType],\n) => MaybePromise<void>;\n\nconst errorMessage = (error: unknown): string => {\n if (isErrorMessage(error)) return error.message;\n\n return \"Unexpected error\";\n};\n\nexport type InferWebSocketSource<TAbstractWebSocket extends AbstractWebSocket> =\n TAbstractWebSocket extends AbstractWebSocket<infer IWebSocket> ? IWebSocket : never;\n\nexport interface AbstractWebSocketConfig {\n persistence: AbstractPersistence;\n platform: AbstractPlatform<any>;\n room: string;\n}\n\nexport abstract class AbstractWebSocket<TWebSocket = any> {\n /** The connection is not yet open. */\n public readonly CONNECTING = 0;\n /** The connection is open and ready to communicate. */\n public readonly OPEN = 1;\n /** The connection is in the process of closing. */\n public readonly CLOSING = 2;\n /** The connection is closed. */\n public readonly CLOSED = 3;\n\n public readonly persistence: AbstractPersistence;\n public readonly room: string;\n public readonly webSocket: TWebSocket;\n\n protected readonly _platform: AbstractPlatform<this>;\n\n public abstract set presence(presence: JsonObject | null);\n public abstract get readyState(): 0 | 1 | 2 | 3;\n public abstract get session(): WebSocketSession<any>;\n public abstract get sessionId(): string;\n public abstract get state(): WebSocketSerializedState;\n public abstract set state(state: WebSocketSerializedState);\n /**\n * @description Authorized user for this socket. `null` until `register` (or hibernation\n * reattach) has assigned one.\n */\n public abstract get user(): BaseUser | null;\n public abstract set user(user: BaseUser);\n\n constructor(webSocket: TWebSocket, config: AbstractWebSocketConfig) {\n const { persistence, platform, room } = config;\n\n this.persistence = persistence;\n this._platform = platform;\n this.room = room;\n this.webSocket = webSocket;\n }\n\n /**\n * TODO\n * @description Return an unsubscribe method to remove the event-listener.\n * This is preferred over adding an explicit abstract removeEventListener\n * method, because the implementing class might have to transform the\n * listener, and removing the same listener might be complicated as a\n * result.\n * @date August 28, 2022\n */\n public abstract addEventListener<TType extends EventType>(\n type: TType,\n handler: AbstractListener<TType>,\n ): void;\n\n public abstract close(code?: number, reason?: string): void;\n\n public abstract send(message: ArrayBuffer | ArrayBufferView | string): void;\n\n public abstract terminate(): void;\n\n public handleError(params: AbstractWebSocketHandleErrorParams): void {\n const { error, message: _message, room, session } = params;\n\n const message = errorMessage(error);\n const stack: string | null = error instanceof Error ? (error.stack ?? null) : null;\n const connectionId = (session?.id ?? null) as string;\n\n return this.sendMessage({\n connectionId,\n data: { message, stack },\n room,\n type: \"$error\" as const,\n user: (session?.user ?? null) as IOEventMessage<any>[\"user\"],\n operator: session?.operator ?? null,\n });\n }\n\n // oxlint-disable-next-line typescript/no-unnecessary-type-parameters -- callers pass a specific message\n public sendMessage<TMessage extends IOEventMessage<any> = IOEventMessage<any>>(\n data: TMessage,\n ): void {\n return this.send(JSON.stringify(data));\n }\n}\n","/**\n * Orders one commit after another.\n * `idle` means the latest reserved turn has already finished.\n * `reserve` takes the next turn. `previous` settles when the earlier turn\n * finishes. `finish` runs once, when this turn's commit has ended.\n */\nexport class CommitGate {\n #turn: { done: boolean; promise: Promise<void> } = {\n done: true,\n promise: Promise.resolve(),\n };\n\n public get idle(): boolean {\n return this.#turn.done;\n }\n\n public reserve(): { previous: Promise<void>; finish: () => void } {\n const previous = this.#turn.promise;\n let settled = false;\n let resolveTurn: () => void = () => undefined;\n const promise = new Promise<void>((resolve) => {\n resolveTurn = resolve;\n });\n const turn = { done: false, promise };\n const finish = (): void => {\n if (settled) return;\n\n settled = true;\n turn.done = true;\n resolveTurn();\n };\n\n this.#turn = turn;\n\n return { previous, finish };\n }\n}\n","import { hkdf } from \"@panva/hkdf\";\nimport type { BaseUser, OperatorUser, ParticipantKind } from \"@pluv/types\";\nimport { EncryptJWT, jwtDecrypt } from \"jose\";\nimport type { AbstractPlatform, InferInitContextType } from \"./AbstractPlatform\";\nimport { assertExhaustive } from \"./utils/assertExhaustive\";\n\n/** Default token lifetime: 60 seconds (passed to jose as seconds). */\nconst DEFAULT_MAX_AGE_MS = 60_000;\n\nexport const getEncryptionKey = async (secret: string): Promise<Uint8Array> => {\n return await hkdf(\"sha256\", secret, \"\", \"Pluv.io Generated Encryption Key\", 32);\n};\n\nexport interface JWT<TUser extends BaseUser> {\n kind: ParticipantKind;\n operator: OperatorUser | null;\n room: string;\n sub: string;\n user: TUser;\n}\n\ntype JWTEncodeBase<TPlatform extends AbstractPlatform<any, any>> = {\n /**\n * Token lifetime in milliseconds. Converted to whole seconds for JWT `exp`.\n * @default 60_000\n */\n maxAge?: number;\n room: string;\n} & InferInitContextType<TPlatform>;\n\ntype OccupantTokenIdentity<TUser extends BaseUser> = {\n kind?: \"user\";\n user: TUser;\n};\n\ntype OperatorTokenIdentity = {\n kind: \"operator\";\n operator: OperatorUser & { email: string };\n};\n\ntype OperatorSessionIdentity = {\n kind: \"operator\";\n operator: OperatorUser;\n};\n\ntype JwtTokenIdentity<TUser extends BaseUser> =\n | OccupantTokenIdentity<TUser>\n | (OperatorSessionIdentity & { user: TUser });\n\nexport type CreateUserTokenParams<\n TUser extends BaseUser,\n TPlatform extends AbstractPlatform<any, any>,\n> = JWTEncodeBase<TPlatform> & OccupantTokenIdentity<TUser>;\n\nexport type CreateOperatorTokenParams<TPlatform extends AbstractPlatform<any, any>> =\n JWTEncodeBase<TPlatform> & OperatorTokenIdentity;\n\nexport type CreateTokenParams<\n TUser extends BaseUser,\n TPlatform extends AbstractPlatform<any, any>,\n> = CreateUserTokenParams<TUser, TPlatform> | CreateOperatorTokenParams<TPlatform>;\n\n/** Identity fields for minting a token, without platform init context. */\nexport type CreateTokenIdentity<TUser extends BaseUser> = {\n maxAge?: number;\n room: string;\n} & (OccupantTokenIdentity<TUser> | OperatorTokenIdentity);\n\nexport type JWTEncodeParams<\n TUser extends BaseUser,\n TPlatform extends AbstractPlatform<any, any>,\n> = JWTEncodeBase<TPlatform> & JwtTokenIdentity<TUser>;\n\nexport const isOperatorToken = <T extends { kind?: ParticipantKind | undefined }>(\n params: T,\n): params is T & { kind: \"operator\" } => {\n return params.kind === \"operator\";\n};\n\nexport interface AuthorizeParams {\n platform: AbstractPlatform<any, any>;\n secret: string;\n}\n\nexport interface AuthorizeModule {\n decode: <TUser extends BaseUser>(jwt: string) => Promise<JWT<TUser> | null>;\n encode: <TUser extends BaseUser, TPlatform extends AbstractPlatform<any, any>>(\n params: JWTEncodeParams<TUser, TPlatform>,\n ) => Promise<string>;\n}\n\nconst now = () => (Date.now() / 1_000) | 0;\n\nconst maxAgeMsToSeconds = (maxAgeMs: number): number => {\n return Math.max(1, Math.ceil(maxAgeMs / 1_000));\n};\n\nconst resolveJwtIdentity = <TUser extends BaseUser>(\n params: JwtTokenIdentity<TUser> & { room: string },\n): JWT<TUser> => {\n const { room } = params;\n\n switch (params.kind) {\n case \"operator\": {\n const { operator, user } = params;\n\n return {\n kind: \"operator\",\n operator,\n room,\n sub: `${room}|operator|${operator.id}`,\n user,\n };\n }\n case \"user\":\n case undefined: {\n const { user } = params;\n\n return {\n kind: \"user\",\n operator: null,\n room,\n sub: `${room}|${user.id}`,\n user,\n };\n }\n default:\n return assertExhaustive(params);\n }\n};\n\nexport const authorize = (params: AuthorizeParams) => {\n const { platform, secret } = params;\n\n const encode = async <TUser extends BaseUser, TPlatform extends AbstractPlatform<any, any>>(\n encodeParams: JWTEncodeParams<TUser, TPlatform>,\n ): Promise<string> => {\n const { maxAge = DEFAULT_MAX_AGE_MS } = encodeParams as JWTEncodeBase<TPlatform>;\n const claims = resolveJwtIdentity(encodeParams);\n\n const encryptionSecret = await getEncryptionKey(secret);\n\n const token = await new EncryptJWT({ ...claims })\n .setProtectedHeader({ alg: \"dir\", enc: \"A256GCM\" })\n .setIssuedAt()\n .setExpirationTime(now() + maxAgeMsToSeconds(maxAge))\n .setJti(platform.randomUUID())\n .encrypt(encryptionSecret);\n\n return token;\n };\n\n const decode = async <TUser extends BaseUser>(jwt: string): Promise<JWT<TUser> | null> => {\n try {\n const encryptionSecret = await getEncryptionKey(secret);\n\n const { payload } = await jwtDecrypt(jwt, encryptionSecret, {\n clockTolerance: 15,\n });\n\n const decoded = (payload as unknown as JWT<TUser> | undefined) ?? null;\n\n if (!decoded) return null;\n\n const kind = decoded.kind as ParticipantKind | undefined;\n\n switch (kind) {\n case \"operator\":\n return {\n kind: \"operator\",\n operator: decoded.operator,\n room: decoded.room,\n sub: decoded.sub,\n user: decoded.user,\n };\n case \"user\":\n case undefined:\n return {\n kind: \"user\",\n operator: null,\n room: decoded.room,\n sub: decoded.sub,\n user: decoded.user,\n };\n default:\n return assertExhaustive(kind);\n }\n } catch {\n return null;\n }\n };\n\n return { decode, encode };\n};\n","import type { EventRecord, JsonObject, ProcedureLike, StandardSchemaV1 } from \"@pluv/types\";\nimport type { IODefs } from \"./IODefs\";\nimport type { EventResolver, MergeEventRecords } from \"./types\";\n\nexport interface PluvProcedureConfig<\n T extends IODefs,\n TInput extends JsonObject = {},\n TOutput extends EventRecord<string, any> = {},\n> {\n broadcast?: EventResolver<\"broadcast\", T, TInput, Partial<TOutput>> | null;\n input?: StandardSchemaV1<unknown, TInput>;\n self?: EventResolver<\"self\", T, TInput, Partial<TOutput>> | null;\n}\n\nexport class PluvProcedure<\n T extends IODefs = IODefs,\n TInput extends JsonObject = {},\n TOutput extends EventRecord<string, any> = {},\n TFilled extends \"input\" | \"broadcast\" | \"self\" | \"\" = \"\",\n> {\n private _broadcast: EventResolver<\"broadcast\", T, TInput, Partial<TOutput>> | null = null;\n private _input: StandardSchemaV1<unknown, TInput> | null = null;\n private _self: EventResolver<\"self\", T, TInput, Partial<TOutput>> | null = null;\n\n public get config(): ProcedureLike<TInput, TOutput>[\"config\"] {\n return {\n broadcast: this._broadcast?.bind(this) ?? null,\n input: this._input ?? null,\n self: this._self?.bind(this) ?? null,\n } as ProcedureLike<TInput, TOutput>[\"config\"];\n }\n\n constructor(config: PluvProcedureConfig<T, TInput, TOutput> = {}) {\n const { broadcast, input, self } = config;\n\n this._broadcast = broadcast ?? null;\n this._input = input ?? null;\n this._self = self ?? null;\n }\n\n public broadcast<TResult extends EventRecord<string, any> = {}>(\n resolver: EventResolver<\"broadcast\", T, TInput, TResult>,\n ): Omit<\n PluvProcedure<\n T,\n TInput,\n MergeEventRecords<[TOutput, TResult]>,\n TFilled | \"input\" | \"broadcast\"\n >,\n TFilled | \"input\" | \"broadcast\"\n > {\n const { broadcast } = this.config;\n\n if (!!broadcast) throw new Error(\"Broadcast was already defined for this procedure\");\n\n return new PluvProcedure<\n T,\n TInput,\n MergeEventRecords<[TOutput, TResult]>,\n TFilled | \"input\" | \"broadcast\"\n >({\n ...(this.config as any),\n broadcast: resolver as any,\n });\n }\n\n public input<TData extends JsonObject>(\n input: StandardSchemaV1<unknown, TData>,\n ): Omit<PluvProcedure<T, TData, {}, TFilled | \"input\">, TFilled | \"input\"> {\n return new PluvProcedure<T, TData, {}, TFilled | \"input\">({\n input,\n });\n }\n\n public self<TResult extends EventRecord<string, any> = {}>(\n resolver: EventResolver<\"self\", T, TInput, TResult>,\n ): Omit<\n PluvProcedure<T, TInput, MergeEventRecords<[TOutput, TResult]>, TFilled | \"input\" | \"self\">,\n TFilled | \"input\" | \"self\"\n > {\n const { self } = this.config;\n\n if (!!self) throw new Error(\"Self was already defined for this procedure\");\n\n return new PluvProcedure<\n T,\n TInput,\n MergeEventRecords<[TOutput, TResult]>,\n TFilled | \"input\" | \"self\"\n >({\n ...(this.config as any),\n self: resolver as any,\n });\n }\n}\n","import type { BaseClientEventRecord } from \"@pluv/types\";\nimport type { IODefs, SetKey } from \"./IODefs\";\nimport { PluvProcedure } from \"./PluvProcedure\";\nimport type { PluvRouter } from \"./PluvRouter\";\nimport type { CreateBaseRouterParams } from \"./createBaseRouter\";\nimport type { SessionEventContext } from \"./types\";\nimport {\n createInternalPluvRouter,\n getMyConnectionIds,\n getSessionKind,\n groupLiveUsers,\n oneLine,\n pageLiveUsers,\n pickBy,\n} from \"./utils\";\n\nconst baseProcedureFactory =\n <T extends IODefs>() =>\n <TEvent extends keyof BaseClientEventRecord>() => {\n return new PluvProcedure<T, BaseClientEventRecord[TEvent], {}>();\n };\n\ntype BaseRouter<T extends IODefs> = PluvRouter<SetKey<T, \"events\", {}>>;\n\nconst asSession = <T extends IODefs>(event: object): SessionEventContext<T> => {\n return event as SessionEventContext<T>;\n};\n\n/**\n * Session `$` events. `$initializeSession` only broadcasts `$userJoined`.\n * `manageSessions` calls `initializeStorage` for the storage half.\n */\ntype SessionLimits<T extends IODefs> =\n | CreateBaseRouterParams<T>[\"limits\"]\n | null\n | (() => CreateBaseRouterParams<T>[\"limits\"] | null);\n\nexport const createSessionRouter = <T extends IODefs = IODefs>(params: {\n limits: SessionLimits<T>;\n}): BaseRouter<T> => {\n const readLimits = (): CreateBaseRouterParams<T>[\"limits\"] | null =>\n typeof params.limits === \"function\" ? params.limits() : params.limits;\n const baseProcedure = baseProcedureFactory<T>();\n\n return createInternalPluvRouter({\n $getOthers: baseProcedure<\"$getOthers\">().self((_data, raw) => {\n const { session, sessions } = asSession<T>(raw);\n const presenceSeqById = new Map(\n sessions.map((item) => [item.id, item.seq.presence] as const),\n );\n const others = groupLiveUsers(sessions, {\n excludeSessionId: session.id,\n }).map(({ connectionIds, data, presence, kind, operator }) => ({\n connectionIds,\n data,\n session: {\n kind,\n operator,\n presence,\n seq: {\n presence: connectionIds.reduce<number | null>((max, id) => {\n const seq = presenceSeqById.get(id) ?? null;\n\n if (typeof seq !== \"number\") return max;\n if (typeof max !== \"number\") return seq;\n\n return seq > max ? seq : max;\n }, null),\n },\n },\n }));\n\n return {\n $othersReceived: {\n myConnectionIds: getMyConnectionIds(sessions, session),\n others,\n },\n };\n }),\n $listUsers: baseProcedure<\"$listUsers\">().self((data, raw) => {\n const { sessions } = asSession<T>(raw);\n const result = pageLiveUsers(sessions, data);\n\n if (!result.success) {\n return {\n $usersPage: {\n requestId: data.requestId,\n success: false,\n error: {\n code:\n result.error.code === \"INVALID_LIMIT\" ? \"INVALID_LIMIT\" : \"FAILED\",\n message: result.error.message,\n },\n },\n };\n }\n\n return {\n $usersPage: {\n requestId: data.requestId,\n success: true,\n pageInfo: result.pageInfo,\n users: result.users,\n },\n };\n }),\n $initializeSession: baseProcedure<\"$initializeSession\">().broadcast((data, raw) => {\n const event = asSession<T>(raw);\n const presence = data.presence ?? null;\n const { session } = event;\n\n if (!session) return {};\n\n const kind = getSessionKind(session);\n const participantId = session.user.id;\n const latestSeq = event.sessions.reduce<number | null>((max, other) => {\n if (other.quit) return max;\n const otherKind = getSessionKind(other);\n const otherId = other.user?.id;\n if (otherKind !== kind || otherId !== participantId) return max;\n\n const seq = other.seq.presence;\n\n if (typeof seq !== \"number\") return max;\n if (typeof max !== \"number\") return seq;\n\n return seq > max ? seq : max;\n }, null);\n\n // Connecting another tab is not a presence write. Keep the last\n // `$updatePresence` instead of last-connect.\n if (typeof latestSeq !== \"number\") {\n event.presence = presence as SessionEventContext<T>[\"presence\"];\n }\n\n return {\n $userJoined: {\n connectionId: session.id,\n user: session.user,\n session: {\n kind,\n operator: session.operator,\n presence: session.presence ?? presence ?? {},\n seq: { presence: session.webSocket.state.seq.presence },\n },\n },\n };\n }),\n $ping: baseProcedure<\"$ping\">().self((_data, raw) => {\n const { platform, session } = asSession<T>(raw);\n if (!session) return {};\n\n const currentTime = new Date().getTime();\n const prevState = session.webSocket.state;\n\n platform.setSerializedState(session.webSocket, {\n ...prevState,\n timers: {\n ...prevState.timers,\n ping: currentTime,\n },\n });\n\n return { $pong: {} };\n }),\n $updatePresence: baseProcedure<\"$updatePresence\">().broadcast((data, raw) => {\n const context = asSession<T>(raw);\n const presence = data.presence;\n const { session } = context;\n\n if (!session) return {};\n\n const cleanedPatch = pickBy(presence ?? {}, (value) => typeof value !== \"undefined\");\n const updated = Object.assign(Object.create(null), session.presence, cleanedPatch);\n const bytes = new TextEncoder().encode(JSON.stringify(updated)).length;\n const limits = readLimits();\n const presenceMaxSize = limits?.presenceMaxSize;\n\n if (!!presenceMaxSize && bytes > presenceMaxSize) {\n throw new Error(oneLine`\n Large presence. Presence must be at most\n ${presenceMaxSize.toLocaleString()} bytes.\n Current size: ${bytes.toLocaleString()} bytes\n `);\n }\n\n context.presence = updated;\n\n return {\n $presenceUpdated: {\n user: session.user,\n session: {\n presence: updated,\n seq: { presence: session.webSocket.state.seq.presence },\n kind: session.kind,\n operator: session.operator,\n },\n },\n };\n }),\n });\n};\n","import type { BaseClientEventRecord } from \"@pluv/types\";\nimport type { IODefs, SetKey } from \"./IODefs\";\nimport { PluvProcedure } from \"./PluvProcedure\";\nimport type { PluvRouter } from \"./PluvRouter\";\nimport type { CreateBaseRouterParams } from \"./createBaseRouter\";\nimport type { StorageEventContext } from \"./types\";\nimport { createInternalPluvRouter, oneLine } from \"./utils\";\n\nconst baseProcedureFactory =\n <T extends IODefs>() =>\n <TEvent extends keyof BaseClientEventRecord>() => {\n return new PluvProcedure<T, BaseClientEventRecord[TEvent], {}>();\n };\n\ntype BaseRouter<T extends IODefs> = PluvRouter<SetKey<T, \"events\", {}>>;\n\nconst asStorage = <T extends IODefs>(event: object): StorageEventContext<T> => {\n return event as StorageEventContext<T>;\n};\n\n/** Storage `$` events. These run beside the doc. */\nexport const createStorageRouter = <T extends IODefs = IODefs>(\n params: CreateBaseRouterParams<T>,\n): BaseRouter<T> => {\n const { limits } = params;\n const logDebug = params.logDebug ?? (() => undefined);\n const baseProcedure = baseProcedureFactory<T>();\n\n return createInternalPluvRouter({\n $syncStorage: baseProcedure<\"$syncStorage\">().self((data, { doc }) => {\n const update = data.stateVector\n ? doc.encodeDiff(data.stateVector)\n : doc.getEncodedState();\n\n return { $storageDiff: { update } };\n }),\n $updateStorage: baseProcedure<\"$updateStorage\">().broadcast((data, raw) => {\n const { doc } = asStorage<T>(raw);\n const origin = data.origin;\n const update = data.update ?? null;\n\n if (origin === \"$initialized\") return {};\n if (!update) return {};\n\n const before = doc.getStateVector();\n const wasPending = doc.hasPending();\n\n doc.applyEncodedState({ update });\n\n const integrated = doc.getStateVector() !== before;\n\n // These bytes did not enter the document. Ask the sender for the missing\n // history. A resync reply that still does not integrate stops here.\n if (!integrated && (doc.hasPending() || !doc.canDetectPending())) {\n logDebug(\"Storage update did not integrate\");\n\n if (data.resync) return {};\n\n return { $storageResync: { stateVector: doc.getStateVector() } };\n }\n\n const state = integrated ? doc.encodeDiff(before) : update;\n const encodedState = doc.getEncodedState();\n const storageSize = new TextEncoder().encode(encodedState).length;\n\n if (!!limits.storageMaxSize && storageSize > limits.storageMaxSize) {\n throw new Error(oneLine`\n Large Storage. Storage must be at most\n ${limits.storageMaxSize.toLocaleString()} bytes.\n Current size: ${storageSize.toLocaleString()} bytes\n `);\n }\n\n if (doc.hasPending() && !wasPending) {\n return {\n $storageUpdated: { state },\n $storageResync: { stateVector: doc.getStateVector() },\n };\n }\n\n return { $storageUpdated: { state } };\n }),\n });\n};\n","import type { IODefs, SetKey } from \"./IODefs\";\nimport { PluvRouter } from \"./PluvRouter\";\nimport { createSessionRouter } from \"./createSessionRouter\";\nimport { createStorageRouter } from \"./createStorageRouter\";\nimport type { IOStorageSnapshotEvent, PluvIOLimits } from \"./types\";\n\nexport type CreateBaseRouterParams<T extends IODefs = IODefs> = {\n limits: Pick<PluvIOLimits, \"presenceMaxSize\" | \"storageMaxSize\">;\n logDebug?: (...data: any[]) => void;\n onStorageSnapshot: (event: IOStorageSnapshotEvent<T>) => void;\n};\n\ntype BaseRouter<T extends IODefs> = PluvRouter<SetKey<T, \"events\", {}>>;\n\n/**\n * Built-in `$` protocol events. Kept separate from `PluvServer` so the protocol\n * can be constructed/tested without a full server instance. This merge only\n * fills `_defs`. `manageSessions` dispatches the session slice. The room\n * dispatches storage events plus the user's router.\n */\nexport const createBaseRouter = <T extends IODefs = IODefs>(\n params: CreateBaseRouterParams<T>,\n): BaseRouter<T> => {\n return PluvRouter.merge(\n createSessionRouter(params),\n createStorageRouter(params),\n ) as BaseRouter<T>;\n};\n","import type { AbstractCrdtDocFactory } from \"@pluv/crdt\";\nimport type { CrdtDocLike } from \"@pluv/types\";\nimport type { IODefs } from \"./IODefs\";\nimport type { GetInitialStorageFn } from \"./types\";\n\nexport interface RoomStorageConfig<T extends IODefs = IODefs> {\n docFactory: AbstractCrdtDocFactory<any, any>;\n getContext: () => Promise<T[\"context\"]>;\n getInitialStorage: GetInitialStorageFn<T[\"context\"]>;\n platform: T[\"platform\"];\n room: string;\n}\n\nexport interface RoomStorageDestroyResult {\n encodedState: string;\n refusedEmptyPersist: boolean;\n shouldDestroyStorage: boolean;\n}\n\nexport class RoomStorage<T extends IODefs = IODefs> {\n private readonly _docFactory: AbstractCrdtDocFactory<any, any>;\n private readonly _getContext: () => Promise<T[\"context\"]>;\n private readonly _getInitialStorage: GetInitialStorageFn<T[\"context\"]>;\n private readonly _platform: T[\"platform\"];\n private readonly _room: string;\n\n private _doc: Promise<CrdtDocLike<any, any>>;\n private _storageSeeded: boolean = false;\n\n constructor(config: RoomStorageConfig<T>) {\n this._docFactory = config.docFactory;\n this._getContext = config.getContext;\n this._getInitialStorage = config.getInitialStorage;\n this._platform = config.platform;\n this._room = config.room;\n this._doc = Promise.resolve(this._docFactory.getEmpty());\n }\n\n public get doc(): Promise<CrdtDocLike<any, any>> {\n return this._doc;\n }\n\n public getEmptyDoc(): CrdtDocLike<any, any> {\n return this._docFactory.getEmpty();\n }\n\n public get storageSeeded(): boolean {\n return this._storageSeeded;\n }\n\n public set storageSeeded(value: boolean) {\n this._storageSeeded = value;\n }\n\n public async destroy(): Promise<RoomStorageDestroyResult> {\n const resolvedDoc = await this._doc;\n const encodedState = resolvedDoc.getEncodedState();\n const shouldDestroyStorage = this._storageSeeded && resolvedDoc.isDirty();\n const refusedEmptyPersist = this._storageSeeded && !shouldDestroyStorage;\n\n this._storageSeeded = false;\n resolvedDoc.destroy();\n this._doc = Promise.resolve(this._docFactory.getEmpty());\n\n return { encodedState, refusedEmptyPersist, shouldDestroyStorage };\n }\n\n public initialize(): Promise<CrdtDocLike<any, any>> {\n this._doc = this._loadInitialDoc();\n\n return this._doc;\n }\n\n private async _loadInitialDoc(): Promise<CrdtDocLike<any, any>> {\n const doc = this._docFactory.getEmpty();\n\n const [encodedState, context] = await Promise.all([\n this._platform.persistence.getStorageState(this._room),\n this._getContext(),\n ]);\n\n if (!encodedState) {\n const loadedState = await this._getInitialStorage({\n context,\n room: this._room,\n });\n\n if (!!loadedState && !this._docFactory.isEmpty(loadedState)) {\n doc.applyEncodedState({ update: loadedState });\n this._storageSeeded = true;\n }\n }\n\n if (typeof encodedState === \"string\") {\n doc.applyEncodedState({ update: encodedState });\n\n if (!doc.isEmpty()) {\n this._storageSeeded = true;\n }\n }\n\n doc.rebuildStorage();\n\n return doc;\n }\n}\n","import type { MaybePromise } from \"@pluv/types\";\nimport { ArmedWait } from \"./utils\";\nimport type { IODefs } from \"./IODefs\";\nimport type { IOStorageEdit, IOStorageEditsEvent } from \"./types\";\n\n/**\n * Ordered document edits for `onStorageEdits`. The first edit starts the wait.\n * Edits during that wait join the same list. A room with no listener does not\n * construct this.\n */\nexport class StorageChangeLog<T extends IODefs = IODefs> {\n private _changes: IOStorageEdit<T>[] = [];\n private _closed = false;\n private _queue: Promise<void> = Promise.resolve();\n\n private readonly _getContext: () => Promise<T[\"context\"]>;\n private readonly _onEdits: (event: IOStorageEditsEvent<T>) => MaybePromise<void>;\n private readonly _room: string;\n private readonly _wait: ArmedWait;\n\n constructor(config: {\n getContext: () => Promise<T[\"context\"]>;\n intervalMs: number;\n keepAlive: (promise: Promise<unknown>) => void;\n onEdits: (event: IOStorageEditsEvent<T>) => MaybePromise<void>;\n room: string;\n }) {\n this._getContext = config.getContext;\n this._onEdits = config.onEdits;\n this._room = config.room;\n this._wait = new ArmedWait(config.intervalMs, config.keepAlive);\n }\n\n public push(changes: readonly IOStorageEdit<T>[]): void {\n if (this._closed || changes.length === 0) return;\n\n this._changes.push(...changes);\n this._arm();\n }\n\n public detach(): void {\n this._closed = true;\n this._wait.clear();\n }\n\n /** Send the waiting list now, then one follow-up list if that call writes. */\n public flush(): Promise<void> {\n const run = this._queue.then(() => this._flush());\n\n this._queue = run.then(\n () => undefined,\n () => undefined,\n );\n\n return run;\n }\n\n public reopen(): void {\n this._closed = false;\n this._changes = [];\n this._wait.clear();\n }\n\n private _arm(): void {\n if (this._closed) return;\n\n this._wait.arm(() => this.flush());\n }\n\n private async _emit(): Promise<void> {\n if (this._changes.length === 0) return;\n\n const changes = this._changes;\n\n this._changes = [];\n\n try {\n const context = await this._getContext();\n\n await this._onEdits({ changes, context, room: this._room });\n } catch (error) {\n console.error(error);\n }\n }\n\n private async _flush(): Promise<void> {\n this._wait.clear();\n await this._emit();\n this._wait.clear();\n\n if (this._changes.length > 0) await this._emit();\n }\n}\n","import type { IODefs } from \"./IODefs\";\nimport type { IOStorageEdit } from \"./types\";\n\ntype ClientClock = readonly [string, number];\n\ntype Reservation<T extends IODefs> = IOStorageEdit<T> & {\n seq: number;\n version: readonly ClientClock[];\n};\n\nconst covers = (doc: ReadonlyMap<string, number>, version: readonly ClientClock[]): boolean => {\n for (const [id, clock] of version) {\n if ((doc.get(id) ?? 0) < clock) return false;\n }\n\n return true;\n};\n\n/**\n * Same-client updates leave in clock order. Updates from different clients keep\n * the order their groups first arrived. Counters from different clients are not\n * comparable.\n */\nconst orderCovered = <T extends IODefs>(ready: readonly Reservation<T>[]): IOStorageEdit<T>[] => {\n const groups = new Map<string, Reservation<T>[]>();\n\n for (const item of ready) {\n const key = item.version.length === 1 ? item.version[0][0] : `\\0${item.seq}`;\n const group = groups.get(key);\n\n if (group) group.push(item);\n else groups.set(key, [item]);\n }\n\n return (\n [...groups.values()]\n // oxlint-disable-next-line unicorn/no-array-sort -- the spread is already a new array\n .sort(\n (left, right) =>\n Math.min(...left.map((item) => item.seq)) -\n Math.min(...right.map((item) => item.seq)),\n )\n .flatMap((group) =>\n group\n .toSorted((left, right) => {\n const leftClock = left.version[0]?.[1] ?? 0;\n const rightClock = right.version[0]?.[1] ?? 0;\n\n if (\n left.version.length === 1 &&\n right.version.length === 1 &&\n leftClock !== rightClock\n ) {\n return leftClock - rightClock;\n }\n\n return left.seq - right.seq;\n })\n .map(({ operator, procedure, update, user }) => ({\n operator,\n procedure,\n update,\n user,\n })),\n )\n );\n};\n\n/** Bytes waiting until the document version covers them. Not an edit yet. */\nexport class StorageReservations<T extends IODefs = IODefs> {\n private _bytes = 0;\n private _items: Reservation<T>[] = [];\n private _seq = 0;\n\n /** `0` keeps every waiting update. A positive cap matches the document size limit. */\n constructor(private readonly _maxBytes = 0) {}\n\n public add(input: IOStorageEdit<T> & { version: readonly ClientClock[] }): void {\n const bytes = input.update.length;\n\n // One update larger than the document limit is never retained.\n if (this._maxBytes > 0 && bytes > this._maxBytes) return;\n\n this._seq += 1;\n this._items.push({ ...input, seq: this._seq });\n this._bytes += bytes;\n }\n\n public clear(): void {\n this._bytes = 0;\n this._items = [];\n }\n\n public holds(update: string): boolean {\n return this._items.some((item) => item.update === update);\n }\n\n public takeCovered(\n doc: ReadonlyMap<string, number>,\n contained: (update: string) => boolean,\n ): IOStorageEdit<T>[] {\n const ready: Reservation<T>[] = [];\n const waiting: Reservation<T>[] = [];\n\n for (const item of this._items) {\n // `covers` is first, so `contained` runs only after the clock check passes.\n // A delete-only update has an empty clock list. Yjs then snapshots the\n // document on every note until that update is contained.\n if (covers(doc, item.version) && contained(item.update)) {\n ready.push(item);\n this._bytes -= item.update.length;\n } else waiting.push(item);\n }\n\n this._items = waiting;\n\n return orderCovered(ready);\n }\n\n /**\n * Drop the oldest waiting updates until the retained bytes fit. Call this after\n * the covered ones are admitted. The apply runs between `add` and that\n * admission, so trimming inside `add` drops an update the apply is about to\n * make reportable.\n */\n public trim(): void {\n while (this._maxBytes > 0 && this._bytes > this._maxBytes && this._items.length > 1) {\n const oldest = this._items.shift();\n\n if (!oldest) return;\n\n this._bytes -= oldest.update.length;\n }\n }\n}\n","import type { CrdtDocLike, MaybePromise } from \"@pluv/types\";\nimport { StorageChangeLog } from \"./StorageChangeLog\";\nimport { StorageReservations } from \"./StorageReservations\";\nimport type { IODefs } from \"./IODefs\";\nimport type { IOStorageEdit, IOStorageEditsEvent } from \"./types\";\n\n/**\n * Reservations become edits once the document covers them. A write that was\n * never reserved is still reported, with no author, so a replay includes it.\n */\nexport class StorageEdits<T extends IODefs = IODefs> {\n private _paused = false;\n private _unsubscribe: (() => void) | null = null;\n\n private readonly _log: StorageChangeLog<T>;\n private readonly _reservations: StorageReservations<T>;\n\n constructor(config: {\n getContext: () => Promise<T[\"context\"]>;\n intervalMs: number;\n keepAlive: (promise: Promise<unknown>) => void;\n /** Waiting updates are dropped past this many bytes. `0` keeps them all. */\n maxBytes?: number;\n onEdits: (event: IOStorageEditsEvent<T>) => MaybePromise<void>;\n room: string;\n }) {\n this._log = new StorageChangeLog(config);\n this._reservations = new StorageReservations(config.maxBytes ?? 0);\n }\n\n public attach(doc: CrdtDocLike<any, any>): void {\n this.detach();\n this._log.reopen();\n this._paused = false;\n this._unsubscribe = doc.subscribe((notice) => {\n if (this._paused || !notice.update) return;\n\n this.note(doc, notice.update);\n });\n }\n\n public clearReservations(): void {\n this._reservations.clear();\n }\n\n public detach(): void {\n this._reservations.clear();\n this._unsubscribe?.();\n this._unsubscribe = null;\n this._log.detach();\n }\n\n public flush(): Promise<void> {\n return this._log.flush();\n }\n\n public note(doc: CrdtDocLike<any, any>, notice?: string): void {\n const version = new Map(doc.readStateVersion(doc.getStateVector()));\n const admitted = this._reservations.takeCovered(version, (update) =>\n doc.containsUpdate(update),\n );\n const edits: IOStorageEdit<T>[] = [...admitted];\n\n // A pending update is still a reservation. A notice already in the document,\n // and not reserved, is an edit with no author. Skip that notice when a\n // reservation was just admitted. A separate write in this same note is\n // dropped with it. The reserved paths call `note` with no notice.\n if (\n notice &&\n admitted.length === 0 &&\n !this._reservations.holds(notice) &&\n doc.containsUpdate(notice)\n ) {\n edits.push({ update: notice, user: null, operator: null, procedure: null });\n }\n\n this._reservations.trim();\n this._log.push(edits);\n }\n\n /** Skip subscription notes while a capture is still collecting its bytes. */\n public pause(paused: boolean): void {\n this._paused = paused;\n }\n\n public reopen(): void {\n this._reservations.clear();\n this._log.reopen();\n }\n\n public reserve(\n doc: CrdtDocLike<any, any>,\n input: {\n operator: IOStorageEdit<T>[\"operator\"];\n procedure: string | null;\n update: string;\n user: IOStorageEdit<T>[\"user\"];\n },\n ): void {\n if (!input.update) return;\n\n this._reservations.add({\n ...input,\n version: doc.readUpdateVersion(input.update),\n });\n }\n}\n","import type { CrdtDocLike } from \"@pluv/types\";\nimport type { PluvIOLimits, SnapshotFlush } from \"./types\";\nimport { oneLine } from \"./utils\";\n\n/** A write during the snapshot, a write from `onStorageSnapshot`, or a document past the size limit. */\ntype StoreInfo = {\n duringNotify: boolean;\n duringSnapshot: boolean;\n oversized: boolean;\n};\n\n/**\n * The room's snapshot. The document stays live. This copies it when asked.\n * The session manager owns the clock.\n */\nexport class StorageSnapshot<TContext> {\n private _closed = false;\n private _dirty = false;\n private _epoch = 0;\n private _generation = 0;\n private _hold = 0;\n private _pending: string[] = [];\n private _release: (() => void) | null = null;\n private _unsubscribe: (() => void) | null = null;\n private _untilClean: Promise<void> | null = null;\n\n private readonly _getContext: () => Promise<TContext>;\n private readonly _getDoc: () => Promise<CrdtDocLike<any, any>>;\n private readonly _keepAlive: (promise: Promise<unknown>) => void;\n private readonly _limits: Pick<PluvIOLimits, \"storageMaxSize\">;\n private readonly _onStored: (event: {\n context: TContext;\n encodedState: string;\n room: string;\n }) => void;\n private readonly _room: string;\n private readonly _setStorageState: (encodedState: string) => Promise<unknown>;\n\n constructor(config: {\n getContext: () => Promise<TContext>;\n getDoc: () => Promise<CrdtDocLike<any, any>>;\n keepAlive: (promise: Promise<unknown>) => void;\n limits: Pick<PluvIOLimits, \"storageMaxSize\">;\n onStored: (event: { context: TContext; encodedState: string; room: string }) => void;\n room: string;\n setStorageState: (encodedState: string) => Promise<unknown>;\n }) {\n this._getContext = config.getContext;\n this._getDoc = config.getDoc;\n this._keepAlive = config.keepAlive;\n this._limits = config.limits;\n this._onStored = config.onStored;\n this._room = config.room;\n this._setStorageState = config.setStorageState;\n }\n\n public get closed(): boolean {\n return this._closed;\n }\n\n public get dirty(): boolean {\n return this._dirty && !this._closed;\n }\n\n /** Updates still need a `$storageUpdated` frame. A closed room does not retry them. */\n public get hasPending(): boolean {\n return !this._closed && this._pending.length > 0;\n }\n\n public get epoch(): number {\n return this._epoch;\n }\n\n /** Increments in `seal`. Stays put across `reopen`. */\n public get generation(): number {\n return this._generation;\n }\n\n /** The seed snapshot already stored this epoch. A later write still needs a copy. */\n public acknowledge(epoch: number): void {\n if (this._epoch === epoch) this._markClean();\n }\n\n public assertSize(encodedState: string): void {\n if (!this._exceedsLimit(encodedState)) return;\n\n const limit = this._limits.storageMaxSize ?? 0;\n const storageSize = new TextEncoder().encode(encodedState).length;\n\n throw new Error(oneLine`\n Large Storage. Storage must be at most\n ${limit.toLocaleString()} bytes.\n Current size: ${storageSize.toLocaleString()} bytes\n `);\n }\n\n public attach(doc: CrdtDocLike<any, any>): void {\n this.detach();\n this._unsubscribe = doc.subscribe((notice) => {\n if (!notice.update) return;\n\n this._epoch += 1;\n this._markDirty();\n\n if (this._hold > 0 || this._closed) return;\n\n this._pending.push(notice.update);\n });\n }\n\n public detach(): void {\n this._unsubscribe?.();\n this._unsubscribe = null;\n }\n\n public async flush(): Promise<SnapshotFlush> {\n if (this._closed) return \"closed\";\n if (!this._dirty) return \"clean\";\n\n const doc = await this._getDoc();\n const context = await this._getContext();\n\n if (this._closed) return \"closed\";\n if (!this._dirty) return \"clean\";\n\n const stored = await this._store({ context, doc, notify: true });\n\n if (this._closed) return \"closed\";\n if (stored.oversized || (!stored.duringNotify && !stored.duringSnapshot)) {\n this._markClean();\n\n return \"clean\";\n }\n\n // The listener's write is stored next. That snapshot does not call the listener\n // again, so a write on every snapshot cannot keep this clock alive.\n const follow = await this._store({ context, doc, notify: false });\n\n if (this._closed) return \"closed\";\n if (follow.oversized || !follow.duringSnapshot) {\n this._markClean();\n\n return \"clean\";\n }\n\n this._markDirty();\n\n return \"dirty\";\n }\n\n /** Doc updates inside `fn` mark the snapshot stale and do not broadcast again. */\n public hold<TResult>(fn: () => TResult): TResult {\n this._hold += 1;\n\n try {\n return fn();\n } finally {\n this._hold -= 1;\n }\n }\n\n /** An update made inside `hold` still needs a `$storageUpdated` frame. */\n public queueUpdate(update: string): void {\n if (this._closed || update.length === 0) return;\n\n this._pending.push(update);\n }\n\n /** Drop updates whose `$storageUpdated` frames were delivered. */\n public dropUpdates(updates: readonly string[]): void {\n if (updates.length === 0 || this._pending.length === 0) return;\n\n const remaining = new Map<string, number>();\n\n for (const update of updates) {\n remaining.set(update, (remaining.get(update) ?? 0) + 1);\n }\n\n this._pending = this._pending.filter((update) => {\n const count = remaining.get(update);\n\n if (!count) return true;\n\n if (count === 1) remaining.delete(update);\n else remaining.set(update, count - 1);\n\n return false;\n });\n }\n\n /** A copy of the updates that still need a `$storageUpdated` frame. */\n public pendingUpdates(): string[] {\n return [...this._pending];\n }\n\n public reopen(): void {\n this._closed = false;\n this._markClean();\n this._epoch = 0;\n this._hold = 0;\n this._pending = [];\n }\n\n public async seal(): Promise<void> {\n this._closed = true;\n this._generation += 1;\n\n if (!this._dirty) return;\n\n const doc = await this._getDoc();\n const context = await this._getContext();\n\n let notify = true;\n\n for (;;) {\n // oxlint-disable-next-line eslint/no-await-in-loop\n const stored = await this._store({ context, doc, notify });\n\n notify = false;\n\n if (stored.oversized || (!stored.duringNotify && !stored.duringSnapshot)) {\n this._markClean();\n\n return;\n }\n\n if (stored.duringSnapshot) continue;\n\n // oxlint-disable-next-line eslint/no-await-in-loop\n const follow = await this._store({ context, doc, notify: false });\n\n if (follow.oversized || !follow.duringSnapshot) {\n this._markClean();\n\n return;\n }\n }\n }\n\n private async _store(params: {\n context: TContext;\n doc: CrdtDocLike<any, any>;\n notify: boolean;\n }): Promise<StoreInfo> {\n const { context, doc, notify } = params;\n const encodedState = doc.getEncodedState();\n\n if (this._exceedsLimit(encodedState)) {\n this._markClean();\n\n return { duringNotify: false, duringSnapshot: false, oversized: true };\n }\n\n const epoch = this._epoch;\n\n await this._setStorageState(encodedState);\n\n const duringSnapshot = this._epoch !== epoch;\n const notifiedAt = this._epoch;\n\n if (notify) {\n this._onStored({\n context,\n encodedState,\n room: this._room,\n });\n }\n\n return {\n duringNotify: this._epoch !== notifiedAt,\n duringSnapshot,\n oversized: false,\n };\n }\n\n private _arm(): void {\n if (this._untilClean) return;\n\n let release!: () => void;\n const held = new Promise<void>((resolve) => {\n release = resolve;\n });\n\n this._untilClean = held;\n this._release = release;\n this._keepAlive(held);\n }\n\n private _exceedsLimit(encodedState: string): boolean {\n const storageSize = new TextEncoder().encode(encodedState).length;\n\n return !!this._limits.storageMaxSize && storageSize > this._limits.storageMaxSize;\n }\n\n private _markClean(): void {\n this._dirty = false;\n this._release?.();\n this._release = null;\n this._untilClean = null;\n }\n\n private _markDirty(): void {\n this._dirty = true;\n\n if (this._closed) return;\n\n this._arm();\n }\n}\n","import type { AbstractCrdtDocFactory } from \"@pluv/crdt\";\nimport { noop } from \"@pluv/crdt\";\nimport type {\n CrdtDocLike,\n InferTreatyProcedureInput,\n IOLike,\n InferEventMessage,\n InferEventsOutput,\n InferTreatyUser,\n JsonObject,\n Maybe,\n MaybePromise,\n OperatorUser,\n ParticipantKind,\n PresenceProcedureProxy,\n TreatyProcedureLike,\n} from \"@pluv/types\";\nimport colors from \"kleur\";\nimport type { InferInitContextType, InferRoomContextType } from \"./AbstractPlatform\";\nimport type { IODefs, IOLikeFromDefs } from \"./IODefs\";\nimport type { PluvRouter } from \"./PluvRouter\";\nimport { RoomStorage } from \"./RoomStorage\";\nimport { StorageEdits } from \"./StorageEdits\";\nimport { StorageSnapshot } from \"./StorageSnapshot\";\nimport { STORAGE_EDITS_INTERVAL_MS } from \"./constants\";\nimport { authorize } from \"./authorize\";\nimport type {\n DeferredResult,\n EventResolverContext,\n GetInitialStorageFn,\n IORoomDestroyedEvent,\n IORoomListenerEvent,\n IORoomMessageEvent,\n IOStorageEditsEvent,\n IOStorageSnapshotEvent,\n IOUserConnectedEvent,\n IOUserDisconnectedEvent,\n PluvContext,\n PluvIOLimits,\n PluvIOSecret,\n IORoomInternal,\n LoadedStorage,\n RoomAttachment,\n RoomEffectFrame,\n RoomEffects,\n RoomJoinActor,\n RoomPresenceSession,\n RoomRegisterResult,\n RoomSessionSnapshot,\n RoomStorageActor,\n SessionEventContext,\n SessionRoom,\n StorageEventContext,\n WebSocketRegisterConfig,\n WebSocketSession,\n} from \"./types\";\nimport { deferredResult, emptyRoomEffects } from \"./roomEffects\";\nimport {\n assertExhaustive,\n invokeProcedureResolvers,\n isThenable,\n parseOperatorUser,\n parsePluvSchema,\n resolveIOSecret,\n} from \"./utils\";\n\n/**\n * @experimental\n * @description Connection the host treaty procedure invoke runs as. Breaking changes may ship\n * without a major version bump.\n */\nexport type HostTreatyProcedureActor = {\n senderId: string;\n};\n\n/**\n * @experimental\n * @description Bound host invoke for treaty storage procedures (async). Client\n * `StorageProcedureProxy` methods return `void`; host invokes are async. Breaking changes may ship\n * without a major version bump.\n */\nexport type HostStorageProcedureProxy<\n TProcedures extends Record<string, TreatyProcedureLike<\"storage\">> = {},\n> = (<TName extends Extract<keyof TProcedures, string>>(\n name: TName,\n data: InferTreatyProcedureInput<TProcedures[TName]>,\n) => Promise<void>) & {\n [TName in Extract<keyof TProcedures, string>]: (\n data: InferTreatyProcedureInput<TProcedures[TName]>,\n ) => Promise<void>;\n};\n\n/**\n * @experimental\n * @description Binds a live connection id and returns the client-shaped presence procedure proxy.\n * Breaking changes may ship without a major version bump.\n */\nexport type HostPresenceInvoke<TIO extends IORoom<any>> = (\n actor: HostTreatyProcedureActor,\n) => PresenceProcedureProxy<TIO[\"_defs\"][\"treaty\"][\"_defs\"][\"procedures\"][\"presence\"]>;\n\n/**\n * @experimental\n * @description Binds a live connection id and returns {@link HostStorageProcedureProxy}. Breaking\n * changes may ship without a major version bump.\n */\nexport type HostStorageInvoke<TIO extends IORoom<any>> = (\n actor: HostTreatyProcedureActor,\n) => HostStorageProcedureProxy<TIO[\"_defs\"][\"treaty\"][\"_defs\"][\"procedures\"][\"storage\"]>;\n\nexport interface IORoomListeners<T extends IODefs = IODefs> {\n onRoomDestroyed: (event: IORoomDestroyedEvent<T>) => void;\n onStorageDestroyed: (event: IORoomListenerEvent<T>) => void;\n onMessage: (event: IORoomMessageEvent<T>) => void;\n onStorageEdits?: (event: IOStorageEditsEvent<T>) => MaybePromise<void>;\n onStorageSnapshot: (event: IOStorageSnapshotEvent<T>) => MaybePromise<void>;\n onUserConnected: (event: IOUserConnectedEvent<T>) => void;\n onUserDisconnected: (event: IOUserDisconnectedEvent<T>) => void;\n}\n\nexport type IORoomConfig<T extends IODefs = IODefs> = Partial<IORoomListeners<T>> & {\n context: PluvContext<T[\"platform\"], T[\"context\"]>;\n debug: boolean;\n getInitialStorage: GetInitialStorageFn<T[\"context\"]>;\n limits: PluvIOLimits;\n platform: T[\"platform\"];\n roomContext: InferRoomContextType<T[\"platform\"]>;\n router: PluvRouter<T>;\n secret?: PluvIOSecret<T[\"platform\"]>;\n treaty: T[\"treaty\"];\n};\n\ntype AuthorizedIdentity<TUser> =\n | { kind: \"operator\"; operator: OperatorUser; user: TUser }\n | { kind: \"user\"; operator: null; user: TUser };\n\n/** Clients ignore `$storageUpdated` when `connectionId` is missing. A listener write has no session. */\nconst SERVER_STORAGE_CONNECTION_ID = \"$server\";\n\nconst effectFrame = <T extends IODefs>(\n type: string,\n data: unknown,\n session: Pick<RoomSessionSnapshot<T>, \"id\" | \"operator\" | \"user\">,\n): RoomEffectFrame<T> => ({\n connectionId: session.id,\n data,\n operator: session.operator,\n type,\n user: session.user,\n});\n\nconst framesFromRecord = <T extends IODefs>(\n record: Record<string, unknown> | null | undefined,\n session: Pick<RoomSessionSnapshot<T>, \"id\" | \"operator\" | \"user\">,\n): RoomEffectFrame<T>[] => {\n if (!record) return [];\n\n return Object.entries(record).map(([type, data]) => effectFrame<T>(type, data, session));\n};\n\nexport class IORoom<T extends IODefs = IODefs>\n implements IOLike<IOLikeFromDefs<T>>, SessionRoom<T>\n{\n public readonly id: string;\n public readonly limits: PluvIOLimits;\n public readonly treaty: T[\"treaty\"];\n public readonly \"~\": IORoomInternal<T>;\n\n private _teardown: Promise<void> | null = null;\n private _uninitialize: Promise<() => Promise<void>> | null = null;\n\n private readonly _edits: StorageEdits<T> | null;\n\n private readonly _snapshot: StorageSnapshot<T[\"context\"]>;\n private readonly _context: PluvContext<T[\"platform\"], T[\"context\"]>;\n private readonly _debug: boolean;\n private readonly _listeners: IORoomListeners<T>;\n private readonly _platform: T[\"platform\"];\n private readonly _roomContext: InferRoomContextType<T[\"platform\"]>;\n private readonly _router: PluvRouter<T>;\n private readonly _secret?: PluvIOSecret<T[\"platform\"]>;\n private readonly _storage: RoomStorage<T>;\n\n /**\n * @ignore\n * @readonly\n * @deprecated Internal use only. Changes to this will never be marked as breaking.\n */\n public get _defs() {\n return {\n context: this._context,\n events: this._router._defs.events,\n platform: this._platform,\n treaty: this.treaty,\n } as {\n context: T[\"context\"];\n events: T[\"events\"];\n platform: T[\"platform\"];\n treaty: T[\"treaty\"];\n };\n }\n\n constructor(id: string, config: IORoomConfig<T>) {\n const {\n _meta,\n context,\n debug,\n getInitialStorage,\n limits,\n onRoomDestroyed,\n onStorageDestroyed,\n onStorageEdits,\n onStorageSnapshot,\n onMessage,\n onUserConnected,\n onUserDisconnected,\n platform,\n roomContext,\n router,\n secret,\n treaty,\n } = config as IORoomConfig<T> & { _meta?: any };\n\n this.id = id;\n this.limits = limits;\n\n this._context = context;\n this._debug = debug;\n this._roomContext = roomContext;\n this._router = router;\n this._secret = secret;\n this.treaty = treaty;\n this._platform = platform.initialize({ ...(!!_meta ? { _meta } : {}), roomContext });\n this._storage = new RoomStorage({\n docFactory:\n (treaty.storage as AbstractCrdtDocFactory<any, any> | undefined) ?? noop.doc(),\n getContext: () => this._getContext(),\n getInitialStorage,\n platform: this._platform,\n room: this.id,\n });\n\n this._edits = onStorageEdits\n ? new StorageEdits({\n getContext: () => this._getContext(),\n intervalMs: STORAGE_EDITS_INTERVAL_MS,\n keepAlive: (promise) => {\n this._platform.keepAlive(promise);\n },\n maxBytes: this.limits.storageMaxSize ?? 0,\n onEdits: (event) => onStorageEdits(event),\n room: this.id,\n })\n : null;\n this._snapshot = new StorageSnapshot({\n getContext: () => this._getContext(),\n getDoc: () => this._doc,\n keepAlive: (promise) => {\n this._platform.keepAlive(promise);\n },\n limits: this.limits,\n onStored: (event) => {\n void this._listeners.onStorageSnapshot(event);\n },\n room: this.id,\n setStorageState: (encodedState) =>\n this._platform.persistence.setStorageState(this.id, encodedState),\n });\n\n this._listeners = {\n onRoomDestroyed: (event) => onRoomDestroyed?.(event),\n onStorageDestroyed: (event) => onStorageDestroyed?.(event),\n onStorageSnapshot: (event) => {\n // Already settled when the listener returns nothing. A returned promise\n // is kept until it settles. The snapshot does not wait for it.\n this._platform.keepAlive(\n Promise.resolve(onStorageSnapshot?.(event)).catch((error: unknown) => {\n console.error(error);\n }),\n );\n },\n onMessage: (event) => {\n // Already settled when the listener returns nothing. A returned promise\n // is kept until it settles. The message handler does not wait for it.\n this._platform.keepAlive(\n Promise.resolve(onMessage?.(event)).catch((error: unknown) => {\n console.error(error);\n }),\n );\n },\n onUserConnected: (event) => onUserConnected?.(event),\n onUserDisconnected: (event) => onUserDisconnected?.(event),\n };\n\n this[\"~\"] = {\n applyPresencePatch: this._applyPresencePatch.bind(this),\n applyStorageProcedure: this._applyStorageProcedure.bind(this),\n commitLoadedStorage: this._commitLoadedStorage.bind(this),\n close: this._close.bind(this),\n destroy: this._destroyRoom.bind(this),\n flushSnapshot: async () => {\n const status = await this._snapshot.flush();\n const updates = this._snapshot.pendingUpdates();\n\n return {\n broadcast: updates.map((update): RoomEffectFrame<T> => ({\n connectionId: SERVER_STORAGE_CONNECTION_ID,\n data: { state: update },\n operator: null,\n type: \"$storageUpdated\",\n user: null,\n })),\n status,\n };\n },\n initializeStorage: this._initializeStorage.bind(this),\n logDebug: this._logDebug.bind(this),\n message: this._message.bind(this),\n register: this._register.bind(this),\n dropStorageUpdates: this._dropStorageUpdates.bind(this),\n queueStorageFrames: this._queueStorageFrames.bind(this),\n storageDirty: () => this._snapshot.dirty || this._snapshot.hasPending,\n userConnected: this._userConnected.bind(this),\n whenReady: () => this._initialized,\n };\n\n this._initialize();\n }\n\n /**\n * @internal Opens the stored document and applies a treaty presence procedure.\n */\n private async _applyPresencePatch(params: {\n name: string;\n data: unknown;\n session: RoomPresenceSession<T>;\n }): Promise<JsonObject | null | DeferredResult<JsonObject | null>> {\n const { name, data, session } = params;\n const procedures = this.treaty._defs.procedures.presence;\n\n if (!procedures || !Object.hasOwn(procedures, name)) {\n throw new Error(`Unknown presence procedure \"${name}\"`);\n }\n\n const procedure = procedures[name];\n const doc = await this._doc;\n const applied = procedure.apply(data, {\n user: session.user,\n operator: session.operator,\n presence: session.presence,\n doc,\n }) as JsonObject | null | PromiseLike<JsonObject | null>;\n\n if (isThenable(applied)) return deferredResult(Promise.resolve(applied));\n\n return applied;\n }\n\n private async _applyStorageProcedure(params: {\n name: string;\n data: unknown;\n actor: RoomStorageActor<T>;\n }): Promise<RoomEffects<T> | DeferredResult<LoadedStorage<T>>> {\n if (!(await this._initialized) || this._snapshot.closed) {\n return this._releaseStorage(emptyRoomEffects<T>(), params.actor);\n }\n\n const generation = this._snapshot.generation;\n const { name, data, actor } = params;\n const procedures = this.treaty._defs.procedures.storage;\n\n if (!procedures || !Object.hasOwn(procedures, name)) {\n throw new Error(`Unknown storage procedure \"${name}\"`);\n }\n\n const procedure = procedures[name];\n\n // The load waits off the queue. The next turn writes and broadcasts.\n // A rejection rejects the host call. There is no commit on that turn.\n if (procedure.prepared && procedure.load) {\n const loaded = procedure\n .load(data, {\n user: actor.user,\n operator: actor.operator,\n presence: actor.presence,\n })\n .then((result): LoadedStorage<T> => ({\n actor,\n data: result.input,\n generation,\n name,\n prepared: result.prepared,\n }));\n\n // The caller observes `loaded`. This copy only keeps the load alive.\n this._platform.keepAlive(\n loaded.then(\n () => undefined,\n () => undefined,\n ),\n );\n\n return deferredResult(loaded);\n }\n\n return this._commitLoadedStorage({\n actor,\n data,\n generation,\n name,\n prepared: undefined,\n });\n }\n\n private async _commitLoadedStorage(\n loaded: LoadedStorage<T>,\n releasePending = true,\n ): Promise<RoomEffects<T>> {\n const { actor, data, name, prepared } = loaded;\n const procedures = this.treaty._defs.procedures.storage;\n const procedure = procedures?.[name];\n\n if (!procedure) throw new Error(`Unknown storage procedure \"${name}\"`);\n\n const doc = await this._doc;\n\n // The load can outlive this room. The next register opens another one.\n if (loaded.generation !== this._snapshot.generation) {\n throw new Error(\"The room closed before this storage write\");\n }\n\n this._edits?.pause(true);\n\n let update: string | null;\n\n try {\n update = this._snapshot.hold(() =>\n doc.captureUpdate(() => {\n doc.transact(() => {\n procedure.apply(\n data,\n {\n user: actor.user,\n operator: actor.operator,\n presence: actor.presence,\n doc,\n },\n prepared,\n );\n }, actor.id);\n }),\n );\n } finally {\n this._edits?.pause(false);\n }\n\n if (update) {\n this._edits?.reserve(doc, {\n operator: actor.operator,\n procedure: name,\n update,\n user: actor.user,\n });\n this._edits?.note(doc);\n }\n\n // A throw refuses the broadcast and does not revert the write. While the room\n // is open, a full sync and `onUserDisconnected` read this document, and the\n // snapshot store is what refuses to save it.\n this._snapshot.assertSize(doc.getEncodedState());\n\n // Releasing sends this update with the others already waiting. A slow hosted\n // send carries its own frame and stays off that list, so another turn cannot\n // release these bytes under a different actor.\n if (releasePending && update) this._snapshot.queueUpdate(update);\n\n if (!update) {\n return releasePending\n ? this._releaseStorage(emptyRoomEffects<T>(), actor)\n : {\n ...emptyRoomEffects<T>(),\n connectionId: actor.id,\n storageDirty: this._snapshot.dirty,\n };\n }\n\n // Pending already carries this update. Releasing it here sends that copy once.\n if (releasePending) return this._releaseStorage(emptyRoomEffects<T>(), actor);\n\n return {\n ...emptyRoomEffects<T>(),\n broadcast: [effectFrame(\"$storageUpdated\", { state: update }, actor)],\n connectionId: actor.id,\n storageDirty: true,\n };\n }\n\n private async _close(session: RoomSessionSnapshot<T>): Promise<RoomEffects<T>> {\n if (!(await this._initialized)) {\n return { ...emptyRoomEffects<T>(), connectionId: session.id };\n }\n\n await this._emitDisconnected(session);\n\n return this._releaseStorage(\n {\n ...emptyRoomEffects<T>(),\n broadcast: [\n effectFrame(\n \"$exit\",\n {\n operator: session.operator,\n sessionId: session.id,\n user: session.user,\n },\n session,\n ),\n ],\n closes: [session.id],\n },\n session,\n );\n }\n\n private async _destroyRoom(): Promise<void> {\n if (!this._uninitialize) return;\n\n const uninitialize = (await this._uninitialize).bind(this);\n\n await uninitialize();\n }\n\n private get _doc(): Promise<CrdtDocLike<any, any>> {\n if (!this._uninitialize) return this._storage.doc;\n\n return this._uninitialize.then(() => this._storage.doc);\n }\n\n private async _emitDisconnected(session: RoomSessionSnapshot<T>): Promise<void> {\n try {\n const [doc, context] = await Promise.all([this._doc, this._getContext()]);\n const encodedState = doc.getEncodedState();\n\n await Promise.resolve(\n this._listeners.onUserDisconnected({\n context,\n encodedState,\n kind: session.kind,\n operator: session.operator,\n room: this.id,\n user: session.user,\n }),\n );\n } catch (error) {\n console.error(error);\n }\n }\n\n private async _getAuthorizedUser(\n token: Maybe<string>,\n options: WebSocketRegisterConfig<T[\"platform\"]>,\n ): Promise<AuthorizedIdentity<InferTreatyUser<T[\"treaty\"]>> | null> {\n const secret = resolveIOSecret(this._secret, options);\n\n if (!token) return null;\n\n if (!secret) throw new Error(\"`secret` was not provided\");\n\n const payload = await authorize({\n platform: this._platform,\n secret,\n }).decode(token);\n\n if (!payload) {\n this._logDebug(colors.blue(\"Could not decode token:\"));\n this._logDebug(token);\n\n return null;\n }\n\n if (payload.room !== this.id) {\n this._logDebug(colors.blue(`Token is not authorized for room ${this.id}:`));\n this._logDebug(colors.blue(\"Received:\"), payload.room);\n this._logDebug(token);\n\n return null;\n }\n\n const user = parsePluvSchema(this.treaty.user, payload.user) as InferTreatyUser<\n T[\"treaty\"]\n >;\n\n switch (payload.kind) {\n case \"operator\": {\n try {\n const operator = parseOperatorUser(payload.operator);\n\n return { kind: \"operator\", operator, user };\n } catch {\n this._logDebug(`${colors.blue(\"Operator token fails validation:\")} ${token}`);\n\n return null;\n }\n }\n case \"user\": {\n try {\n return { kind: \"user\", operator: null, user };\n } catch {\n this._logDebug(`${colors.blue(\"Token fails validation:\")} ${token}`);\n\n return null;\n }\n }\n default:\n return assertExhaustive(payload.kind);\n }\n }\n\n /** User context for session procedures. `.config({ context })` runs here. */\n private async _getContext(): Promise<T[\"context\"]> {\n const context = this._context as PluvContext<T[\"platform\"], T[\"context\"]>;\n\n if (typeof context === \"function\") {\n return await Promise.resolve(context(this._roomContext));\n }\n\n return await Promise.resolve(context);\n }\n\n private _getProcedure(message: {\n type: string;\n }):\n | (typeof this._router)[\"_defs\"][\"events\"][keyof (typeof this._router)[\"_defs\"][\"events\"]]\n | null {\n return (\n this._router._defs.events[\n message.type as keyof (typeof this._router)[\"_defs\"][\"events\"]\n ] ?? null\n );\n }\n\n private _initialize() {\n const promise = (async () => {\n this._logDebug(colors.blue(`Initializing room: ${this.id}`));\n\n if (!!this._uninitialize) {\n const uninitialize = (await this._uninitialize).bind(this);\n await uninitialize();\n\n this._uninitialize = null;\n }\n\n await this._storage.initialize();\n\n const doc = await this._storage.doc;\n\n this._snapshot.reopen();\n this._snapshot.attach(doc);\n this._edits?.reopen();\n this._edits?.attach(doc);\n\n const uninitialize = async (): Promise<void> => {\n if (this._teardown) return this._teardown;\n\n this._teardown = (async () => {\n await this._edits?.flush();\n this._edits?.clearReservations();\n await this._snapshot.seal();\n await this._edits?.flush();\n this._snapshot.detach();\n this._edits?.detach();\n\n const context = await this._getContext();\n const { encodedState, refusedEmptyPersist, shouldDestroyStorage } =\n await this._storage.destroy();\n\n if (refusedEmptyPersist) {\n this._logDebug(\n colors.blue(\n `Refusing to persist an unwritten document for room: ${this.id}`,\n ),\n );\n }\n\n await Promise.resolve(\n this._listeners.onRoomDestroyed({\n ...(\"_meta\" in this._platform && !!this._platform._meta\n ? { _meta: this._platform._meta }\n : {}),\n context,\n room: this.id,\n }),\n );\n\n if (shouldDestroyStorage) {\n await Promise.resolve(\n this._listeners.onStorageDestroyed({\n ...(\"_meta\" in this._platform && !!this._platform._meta\n ? { _meta: this._platform._meta }\n : {}),\n context,\n encodedState,\n room: this.id,\n }),\n );\n await this._platform.persistence.deleteStorageState(this.id);\n }\n\n this._uninitialize = null;\n })();\n\n try {\n await this._teardown;\n } finally {\n this._teardown = null;\n }\n };\n\n return { uninitialize };\n })();\n\n this._uninitialize = promise.then((result) => result.uninitialize);\n }\n\n private get _initialized(): Promise<boolean> {\n if (!this._uninitialize) return Promise.resolve(false);\n\n return this._uninitialize.then(() => true);\n }\n\n private async _initializeStorage(params: {\n input: { stateVector?: string | null; update?: string | null };\n actor: RoomJoinActor<T>;\n }): Promise<{\n changeKind: \"unchanged\" | \"initialized\" | \"empty\";\n state: string | null;\n storageDirty: boolean;\n }> {\n if (!(await this._initialized))\n return { changeKind: \"empty\", state: null, storageDirty: false };\n\n const { input } = params;\n const doc = await this._doc;\n const context = await this._getContext();\n const update = input.update ?? null;\n const stateVector = input.stateVector ?? null;\n const stateForClient = (encodedState: string): string => {\n if (!stateVector) return encodedState;\n\n return doc.encodeDiff(stateVector);\n };\n\n if (this._storage.storageSeeded) {\n return {\n changeKind: \"unchanged\",\n state: stateVector ? doc.encodeDiff(stateVector) : doc.getEncodedState(),\n storageDirty: this._snapshot.dirty,\n };\n }\n\n if (update) {\n // A gap integrates part of these bytes. Pausing keeps that fragment off the log.\n this._edits?.pause(true);\n\n let encodedState: string;\n\n try {\n this._edits?.reserve(doc, {\n operator: params.actor.operator,\n procedure: null,\n update,\n user: params.actor.user,\n });\n\n encodedState = this._snapshot.hold(() =>\n doc.applyEncodedState({ update }).getEncodedState(),\n );\n } finally {\n this._edits?.pause(false);\n }\n\n // Admit the reserved bytes now that the apply has finished.\n this._edits?.note(doc);\n\n const storageSize = new TextEncoder().encode(encodedState).length;\n\n if (!!this.limits.storageMaxSize && storageSize > this.limits.storageMaxSize) {\n throw new Error(\"Storage has exceeded the size limit\");\n }\n\n this._storage.storageSeeded = true;\n\n const epoch = this._snapshot.epoch;\n const stored = await this._platform.persistence\n .setStorageState(this.id, encodedState)\n .then(() => true)\n .catch((error: unknown) => {\n this._logDebug(error);\n\n return false;\n });\n\n if (stored) {\n this._snapshot.acknowledge(epoch);\n void this._listeners.onStorageSnapshot({\n context,\n encodedState,\n room: this.id,\n });\n }\n\n return {\n changeKind: \"initialized\",\n state: stateForClient(encodedState),\n storageDirty: this._snapshot.dirty,\n };\n }\n\n const encodedState = doc.getEncodedState();\n\n return {\n changeKind: \"empty\",\n state: stateForClient(encodedState),\n storageDirty: this._snapshot.dirty,\n };\n }\n\n private _logDebug(...data: unknown[]): void {\n if (this._debug) console.log(...data);\n }\n\n private async _message(\n session: RoomSessionSnapshot<T>,\n event: { data: unknown; type: string },\n ): Promise<RoomEffects<T> | DeferredResult<RoomEffects<T>>> {\n if (!(await this._initialized)) return this._releaseStorage(emptyRoomEffects<T>(), session);\n\n const context = await this._getContext();\n\n this._listeners.onMessage({\n ...(\"_meta\" in this._platform && !!this._platform._meta\n ? { _meta: this._platform._meta }\n : {}),\n context,\n message: event as InferEventMessage<\n InferEventsOutput<T[\"events\"]>,\n keyof InferEventsOutput<T[\"events\"]>\n >,\n kind: session.kind,\n operator: session.operator,\n room: this.id,\n user: session.user,\n });\n\n const procedure = this._getProcedure(event);\n\n if (!procedure) {\n if (event.type.startsWith(\"$\")) {\n return this._releaseStorage(emptyRoomEffects<T>(), session);\n }\n\n return this._releaseStorage(\n {\n ...emptyRoomEffects<T>(),\n broadcast: [effectFrame(event.type, event.data, session)],\n },\n session,\n );\n }\n\n let inputs: unknown;\n\n try {\n inputs = procedure.config.input\n ? parsePluvSchema(procedure.config.input, event.data)\n : event.data;\n } catch (error) {\n return this._releaseStorage({ ...emptyRoomEffects<T>(), error }, session);\n }\n\n const attachments: RoomAttachment[] = [];\n let presence = session.presence;\n const doc = await this._doc;\n const storageEvent = event.type === \"$syncStorage\" || event.type === \"$updateStorage\";\n\n if (storageEvent && this._snapshot.closed) {\n return this._releaseStorage(emptyRoomEffects<T>(), session);\n }\n\n let releaseNotice = false;\n\n const wide = this._resolverContext({\n attachments,\n context,\n doc,\n getPresence: () => presence,\n session,\n setPresence: (value) => {\n presence = value;\n },\n });\n const resolverContext = storageEvent ? wide : this._userContext(wide);\n const finish = (\n broadcast: Record<string, unknown> | null | undefined,\n self: Record<string, unknown> | null | undefined,\n ): RoomEffects<T> =>\n this._releaseStorage(\n {\n ...emptyRoomEffects<T>(),\n attachments,\n broadcast: framesFromRecord(broadcast, session),\n self: framesFromRecord(self, session),\n },\n session,\n );\n\n try {\n if (this._edits && event.type === \"$updateStorage\") {\n const data = inputs as {\n origin?: string | null;\n procedure?: string | null;\n update?: string | null;\n };\n const incoming = data.update ?? null;\n\n if (incoming && data.origin !== \"$initialized\") {\n // Reading the version throws when the bytes are not an update.\n // This catch reports that to the sender.\n this._edits.reserve(doc, {\n operator: session.operator,\n procedure: typeof data.procedure === \"string\" ? data.procedure : null,\n update: incoming,\n user: session.user,\n });\n // A gap integrates part of these bytes. That notice is shorter than\n // the reservation, so recording it would report the edit twice.\n this._edits.pause(true);\n releaseNotice = true;\n }\n }\n\n const invoked = invokeProcedureResolvers({\n broadcast: () =>\n storageEvent\n ? this._snapshot.hold(() =>\n procedure.config.broadcast?.(inputs, resolverContext),\n )\n : procedure.config.broadcast?.(inputs, resolverContext),\n self: () => procedure.config.self?.(inputs, resolverContext),\n });\n\n if (!invoked.ok) {\n return this._releaseStorage(\n { ...emptyRoomEffects<T>(), attachments, error: invoked.error },\n session,\n );\n }\n\n const { broadcast: broadcastResult, self: selfResult } = invoked;\n\n // The storage broadcast stays on this join. Other resolvers can await the\n // session manager, so this join must finish before those promises do.\n if (!storageEvent && (isThenable(broadcastResult) || isThenable(selfResult))) {\n return deferredResult(\n Promise.all([broadcastResult, selfResult])\n .then(([broadcast, self]) =>\n finish(\n broadcast as Record<string, unknown> | null,\n self as Record<string, unknown> | null,\n ),\n )\n .catch((error: unknown) =>\n this._releaseStorage(\n {\n ...emptyRoomEffects<T>(),\n attachments,\n error,\n },\n session,\n ),\n ),\n );\n }\n\n const [broadcast, self] = await Promise.all([broadcastResult, selfResult]);\n\n return finish(\n broadcast as Record<string, unknown> | null,\n self as Record<string, unknown> | null,\n );\n } catch (error) {\n return this._releaseStorage({ ...emptyRoomEffects<T>(), attachments, error }, session);\n } finally {\n if (releaseNotice) {\n this._edits?.pause(false);\n // The subscription was paused, and a repeated update does not notify.\n // Admit the reserved bytes here. Other messages do not read them.\n this._edits?.note(doc);\n }\n }\n }\n\n private async _register(\n ...options: keyof InferInitContextType<T[\"platform\"]> extends never\n ? [{ token?: string }?]\n : [WebSocketRegisterConfig<T[\"platform\"]>]\n ): Promise<RoomRegisterResult<T>> {\n const _options = (options[0] ?? {}) as WebSocketRegisterConfig<T[\"platform\"]>;\n const { token: tokenOption, ...initRest } = _options as WebSocketRegisterConfig<\n T[\"platform\"]\n > & { token?: string | null };\n const token = tokenOption ?? null;\n const registerConfig = {\n ...this._platform.normalizeInitContext(initRest as InferInitContextType<T[\"platform\"]>),\n token,\n } as WebSocketRegisterConfig<T[\"platform\"]>;\n\n if (this._teardown) await this._teardown;\n\n if (!(await this._initialized)) {\n this._initialize();\n await this._initialized;\n }\n\n const identity = await this._getAuthorizedUser(token, registerConfig);\n\n if (!identity) {\n this._logDebug(colors.blue(\"Authorization failed for connection\"));\n\n return {\n encodedState: null,\n error: new Error(\"Not authorized\"),\n kind: null,\n operator: null,\n user: null,\n };\n }\n\n const doc = await this._doc;\n const encodedState = doc.isEmpty() ? null : doc.getEncodedState();\n\n return {\n encodedState,\n error: null,\n kind: identity.kind,\n operator: identity.operator,\n user: identity.user,\n };\n }\n\n private _resolverContext(params: {\n attachments: RoomAttachment[];\n context: T[\"context\"];\n doc: CrdtDocLike<any, any>;\n getPresence: () => JsonObject | null;\n session: RoomSessionSnapshot<T>;\n setPresence: (presence: JsonObject | null) => void;\n }): StorageEventContext<T> & SessionEventContext<T> & { context: T[\"context\"] } {\n const { attachments, context, doc, getPresence, session, setPresence } = params;\n const storage = this._storage;\n const time = new Date().getTime();\n\n return {\n connectionId: session.id,\n context,\n doc,\n kind: session.kind,\n operator: session.operator,\n platform: this._platform,\n get presence() {\n return getPresence() as SessionEventContext<T>[\"presence\"];\n },\n persistence: this._platform.persistence,\n set presence(presence) {\n const next = (presence ?? null) as JsonObject | null;\n\n setPresence(next);\n\n const attachment: RoomAttachment = {\n presence: next,\n seq: session.seq.presence,\n sessionId: session.id,\n };\n const index = attachments.findIndex((item) => item.sessionId === session.id);\n\n if (index === -1) attachments.push(attachment);\n else attachments[index] = attachment;\n },\n room: this.id,\n session: {\n id: session.id,\n kind: session.kind,\n operator: session.operator,\n presence: session.presence,\n quit: session.quit,\n room: this.id,\n seq: session.seq,\n timers: { ping: session.lastPing },\n user: session.user,\n } as WebSocketSession<T>,\n sessions: [],\n get storageSeeded() {\n return storage.storageSeeded;\n },\n set storageSeeded(value: boolean) {\n storage.storageSeeded = value;\n },\n user: session.user,\n time,\n } as unknown as StorageEventContext<T> & SessionEventContext<T> & { context: T[\"context\"] };\n }\n\n private async _dropStorageUpdates(frames: readonly RoomEffectFrame<T>[]): Promise<void> {\n const updates: string[] = [];\n\n for (const frame of frames) {\n if (frame.type !== \"$storageUpdated\") continue;\n\n const data = frame.data as { state?: unknown } | null;\n const state = data?.state;\n\n if (typeof state !== \"string\" || state.length === 0) continue;\n\n updates.push(state);\n }\n\n this._snapshot.dropUpdates(updates);\n }\n\n /** Keeps frames from a failed send on the pending list. Ones already queued stay once. */\n private _queueStorageFrames(frames: readonly RoomEffectFrame<T>[]): void {\n const pending = new Set(this._snapshot.pendingUpdates());\n\n for (const frame of frames) {\n if (frame.type !== \"$storageUpdated\") continue;\n\n const data = frame.data as { state?: unknown } | null;\n const state = data?.state;\n\n if (typeof state !== \"string\" || state.length === 0 || pending.has(state)) continue;\n\n this._snapshot.queueUpdate(state);\n pending.add(state);\n }\n }\n\n private _releaseStorage(\n effects: RoomEffects<T>,\n session: Pick<RoomSessionSnapshot<T>, \"id\" | \"operator\" | \"user\">,\n ): RoomEffects<T> {\n const updates = this._snapshot.pendingUpdates();\n const broadcast = updates.length\n ? [\n ...effects.broadcast,\n ...updates.map((update) =>\n effectFrame(\"$storageUpdated\", { state: update }, session),\n ),\n ]\n : effects.broadcast;\n\n return {\n ...effects,\n broadcast,\n connectionId: session.id,\n storageDirty:\n this._snapshot.dirty || broadcast.some((frame) => frame.type === \"$storageUpdated\"),\n };\n }\n\n private async _userConnected(params: {\n id: string;\n encodedState: string | null;\n kind: ParticipantKind;\n operator: OperatorUser | null;\n user: InferTreatyUser<T[\"treaty\"]>;\n }): Promise<RoomEffects<T>> {\n const { encodedState, id, kind, operator, user } = params;\n const context = await this._getContext();\n\n try {\n await Promise.resolve(\n this._listeners.onUserConnected({\n context,\n encodedState,\n kind,\n operator,\n room: this.id,\n user,\n }),\n );\n } catch (error) {\n console.error(error);\n }\n\n return this._releaseStorage(emptyRoomEffects<T>(), { id, operator, user });\n }\n\n private _userContext(\n event: SessionEventContext<T> & Pick<EventResolverContext<T>, \"context\" | \"doc\">,\n ): EventResolverContext<T> {\n return {\n connectionId: event.connectionId,\n context: event.context,\n doc: event.doc,\n kind: event.kind,\n operator: event.operator,\n get presence() {\n return event.presence;\n },\n set presence(value) {\n event.presence = value;\n },\n room: event.room,\n time: event.time,\n user: event.user,\n };\n }\n}\n","// Generated by genversion.\nexport const version = '0.0.0-canary-20261027014949'\n","import type { AbstractCrdtDocFactory, HasStorage } from \"@pluv/crdt\";\nimport { noop } from \"@pluv/crdt\";\nimport type { IOLike, Id, InferTreatyUser, NonNilProps, OnGetOperator } from \"@pluv/types\";\nimport colors from \"kleur\";\nimport type { InferRoomContextType } from \"./AbstractPlatform\";\nimport { createBaseRouter } from \"./createBaseRouter\";\nimport { createStorageRouter } from \"./createStorageRouter\";\nimport type { IODefs, IOLikeFromDefs, SetKey } from \"./IODefs\";\nimport { IORoom } from \"./IORoom\";\nimport type { PluvIO } from \"./PluvIO\";\nimport { PluvRouter } from \"./PluvRouter\";\nimport type { CreateTokenParams } from \"./authorize\";\nimport type {\n BasePluvIOListeners,\n GetInitialStorageFn,\n PluvContext,\n PluvIOLimits,\n PluvIOListeners,\n PluvIOSecret,\n} from \"./types\";\nimport { __PLUV_VERSION } from \"./version\";\n\nexport type InferIORoom<TServer extends PluvServer<any>> =\n TServer extends PluvServer<infer IDefs extends IODefs> ? IORoom<IDefs> : never;\n\nexport type PluvServerConfig<T extends IODefs = IODefs> = Partial<PluvIOListeners<T>> & {\n context?: PluvContext<T[\"platform\"], T[\"context\"]>;\n debug?: boolean;\n limits: PluvIOLimits;\n io: PluvIO<SetKey<T, \"events\", {}>>;\n onGetOperator?: OnGetOperator<InferTreatyUser<T[\"treaty\"]>>;\n platform: () => T[\"platform\"];\n router?: PluvRouter<T>;\n secret: PluvIOSecret<T[\"platform\"]>;\n treaty: T[\"treaty\"];\n} & (HasStorage<T[\"treaty\"][\"storage\"]> extends true\n ? { getInitialStorage: GetInitialStorageFn<T[\"context\"]> }\n : {\n getInitialStorage?: \"[ERROR]: Must specify storage on treaty to use getInitialStorage\";\n });\n\ntype BaseCreateRoomOptions<_T extends IODefs> = {\n debug?: boolean;\n};\n\nexport type CreateRoomOptions<T extends IODefs = IODefs> = keyof Omit<\n InferRoomContextType<T[\"platform\"]>,\n \"meta\"\n> extends never\n ? [BaseCreateRoomOptions<T>] | []\n : [Id<BaseCreateRoomOptions<T> & InferRoomContextType<T[\"platform\"]>>];\n\nexport class PluvServer<T extends IODefs = IODefs> implements IOLike<IOLikeFromDefs<T>> {\n public readonly version: string = __PLUV_VERSION as any;\n\n private readonly _config: NonNilProps<PluvServerConfig<T>>;\n private readonly _docFactory: AbstractCrdtDocFactory<any, any>;\n private readonly _listeners: BasePluvIOListeners<T>;\n private readonly _onGetOperator: OnGetOperator<InferTreatyUser<T[\"treaty\"]>> | null;\n private readonly _onStorageEdits: BasePluvIOListeners<T>[\"onStorageEdits\"] | null;\n\n /**\n * @description The `createIO()` instance this server was built from.\n */\n public get io(): PluvIO<SetKey<T, \"events\", {}>> {\n return this._config.io;\n }\n\n /**\n * @ignore\n * @readonly\n * @deprecated Internal use only. Changes to this will never be marked as breaking.\n */\n public get _defs() {\n return {\n context: this._config.context,\n events: this._router._defs.events,\n platform: this._config.platform(),\n treaty: this._config.treaty,\n } as unknown as T;\n }\n\n /**\n * `_router` fills `_defs` with the session slice, the storage slice, and the\n * user's router. `createRoom` receives `_docRouter`: storage events plus the\n * user's router. `manageSessions` dispatches session events.\n */\n private get _baseRouter(): PluvRouter<SetKey<T, \"events\", {}>> {\n return createBaseRouter<T>({\n limits: this._config.limits,\n logDebug: (...data) => this._logDebug(...data),\n onStorageSnapshot: (event) => this._listeners.onStorageSnapshot(event),\n }) as PluvRouter<SetKey<T, \"events\", {}>>;\n }\n\n private get _router(): PluvRouter<T> {\n return (\n this._config.router\n ? PluvRouter.merge(this._baseRouter, this._config.router)\n : this._baseRouter\n ) as PluvRouter<T>;\n }\n\n private get _docRouter(): PluvRouter<T> {\n const storage = createStorageRouter<T>({\n limits: this._config.limits,\n logDebug: (...data) => this._logDebug(...data),\n onStorageSnapshot: (event) => this._listeners.onStorageSnapshot(event),\n });\n\n return (\n this._config.router ? PluvRouter.merge(storage, this._config.router) : storage\n ) as PluvRouter<T>;\n }\n\n constructor(options: PluvServerConfig<T>) {\n this._config = {\n debug: false,\n router: new PluvRouter<T>({} as T[\"events\"]),\n ...options,\n } as NonNilProps<PluvServerConfig<T>>;\n\n const { onGetOperator } = options;\n const {\n onRoomDestroyed,\n onRoomMessage,\n onStorageDestroyed,\n onStorageEdits,\n onStorageSnapshot,\n onUserConnected,\n onUserDisconnected,\n } = options as Partial<BasePluvIOListeners<T>>;\n\n this._onGetOperator = onGetOperator ?? null;\n this._onStorageEdits = onStorageEdits ?? null;\n this._docFactory =\n (this._config.treaty.storage as AbstractCrdtDocFactory<any, any> | undefined) ??\n noop.doc();\n this._listeners = {\n onRoomDestroyed: (event) => onRoomDestroyed?.(event),\n onRoomMessage: (event) => onRoomMessage?.(event),\n onStorageDestroyed: (event) => onStorageDestroyed?.(event),\n onStorageEdits: (event) => onStorageEdits?.(event),\n onStorageSnapshot: (event) => onStorageSnapshot?.(event),\n onUserConnected: (event) => onUserConnected?.(event),\n onUserDisconnected: (event) => onUserDisconnected?.(event),\n };\n }\n\n public createRoom(room: string, ...options: CreateRoomOptions<T>): IORoom<T> {\n const { _meta, debug, ...platformRoomContext } = (options[0] ??\n {}) as CreateRoomOptions<T>[0] & {\n _meta?: any;\n };\n\n const platform = this._config.platform();\n\n platform.validateConfig(this._config);\n\n if (!/^[a-z0-9](?:[a-z0-9-_]*[a-z0-9])?$/i.test(room))\n throw new Error(\"Unsupported room name\");\n\n const roomContext = platformRoomContext as InferRoomContextType<T[\"platform\"]>;\n const listeners = this._listeners;\n const logDebug = this._logDebug.bind(this);\n\n const newRoom = new IORoom<T>(room, {\n ...(!!_meta ? { _meta } : {}),\n context: this._config.context,\n debug: debug ?? this._config.debug,\n getInitialStorage: this._getInitialStorage,\n limits: this._config.limits,\n async onRoomDestroyed(event) {\n logDebug(`${colors.blue(\"Deleting empty room:\")} ${room}`);\n\n // Always fire server-level onRoomDestroyed\n await Promise.resolve(listeners.onRoomDestroyed(event));\n\n logDebug(`${colors.blue(\"Deleted room:\")} ${room}`);\n },\n async onStorageDestroyed(event) {\n logDebug(`${colors.blue(\"Destroying storage for room:\")} ${room}`);\n\n // Always fire server-level onStorageDestroyed. The room deletes its\n // initialized store after this returns.\n await Promise.resolve(listeners.onStorageDestroyed(event));\n },\n onStorageSnapshot(event) {\n return listeners.onStorageSnapshot(event);\n },\n // Absent when nobody subscribed, so the room does not queue edits.\n onStorageEdits: this._onStorageEdits\n ? (event) => listeners.onStorageEdits(event)\n : undefined,\n async onMessage(event) {\n await Promise.resolve(listeners.onRoomMessage(event));\n },\n async onUserConnected(event) {\n await Promise.resolve(listeners.onUserConnected(event));\n },\n async onUserDisconnected(event) {\n await Promise.resolve(listeners.onUserDisconnected(event));\n },\n secret: this._config.secret,\n treaty: this._config.treaty,\n platform,\n roomContext,\n router: this._docRouter,\n });\n\n this._logDebug(`${colors.blue(\"Created room:\")} ${room}`);\n\n return newRoom;\n }\n\n public async createToken(\n params: CreateTokenParams<InferTreatyUser<T[\"treaty\"]>, T[\"platform\"]>,\n ): Promise<string> {\n return await this._config.io.createToken(params, {\n onGetOperator: this._onGetOperator,\n });\n }\n\n private _getInitialStorage: GetInitialStorageFn<T[\"context\"]> = (...args) => {\n const getInitialStorage = this._config.getInitialStorage;\n\n if (typeof getInitialStorage !== \"function\") return null;\n\n return getInitialStorage(...args);\n };\n\n private _logDebug(...data: any[]): void {\n if (this._config.debug) console.log(...data);\n }\n}\n","import type { HasStorage } from \"@pluv/crdt\";\nimport type {\n HasRequiredProperty,\n InferTreatyUser,\n OnGetOperator,\n OperatorUser,\n SetKey,\n} from \"@pluv/types\";\nimport type { InferInitContextType } from \"./AbstractPlatform\";\nimport type { IODefs } from \"./IODefs\";\nimport { PluvProcedure } from \"./PluvProcedure\";\nimport type { MergedRouter, PluvRouterEventConfig } from \"./PluvRouter\";\nimport { PluvRouter } from \"./PluvRouter\";\nimport { PluvServer, PluvServerConfig } from \"./PluvServer\";\nimport type {\n CreateTokenIdentity,\n CreateTokenParams,\n CreateUserTokenParams,\n JWTEncodeParams,\n} from \"./authorize\";\nimport { authorize, isOperatorToken } from \"./authorize\";\nimport {\n DEFAULT_MAX_CONNECTIONS,\n MAX_PRESENCE_SIZE_BYTES,\n MAX_STORAGE_SIZE_BYTES,\n MAX_USER_ID_LENGTH,\n MAX_USER_SIZE_BYTES,\n} from \"./constants\";\nimport type {\n GetInitialStorageFn,\n PluvContext,\n PluvIOLimits,\n PluvIOListeners,\n PluvIORouter,\n PluvIOSecret,\n} from \"./types\";\nimport {\n oneLine,\n parseOperatorUser,\n parsePluvSchema,\n resolveIOSecret,\n assertExhaustive,\n assertPresenceFanoutBudget,\n} from \"./utils\";\nimport { __PLUV_VERSION } from \"./version\";\n\nexport type PluvIOConfig<T extends IODefs = IODefs> = {\n context?: PluvContext<T[\"platform\"], T[\"context\"]>;\n debug?: boolean;\n limits?: PluvIOLimits;\n platform: () => T[\"platform\"];\n secret: PluvIOSecret<T[\"platform\"]>;\n treaty: T[\"treaty\"];\n};\n\ntype ResolvedServerConfig<T extends IODefs = IODefs> = Partial<PluvIOListeners<T>> &\n PluvIORouter<T> & {\n onGetOperator?: OnGetOperator<InferTreatyUser<T[\"treaty\"]>>;\n } & (HasStorage<T[\"treaty\"][\"storage\"]> extends true\n ? { getInitialStorage: GetInitialStorageFn<T[\"context\"]> }\n : {\n getInitialStorage?: \"[ERROR]: Must specify storage on treaty to use getInitialStorage\";\n });\n\nexport type BaseServerConfig<T extends IODefs = IODefs> = {\n [\n P in keyof ResolvedServerConfig<T> as ResolvedServerConfig<T>[P] extends undefined\n ? never\n : P\n ]: ResolvedServerConfig<T>[P];\n};\n\nexport type ServerConfig<T extends IODefs = IODefs> =\n HasRequiredProperty<BaseServerConfig<T>> extends true\n ? [BaseServerConfig<T>]\n : [BaseServerConfig<T>?];\n\ntype ResolveEncodeParams<T extends IODefs = IODefs> = {\n initContext: InferInitContextType<T[\"platform\"]>;\n onGetOperator: OnGetOperator<InferTreatyUser<T[\"treaty\"]>> | null;\n token: CreateTokenIdentity<InferTreatyUser<T[\"treaty\"]>>;\n};\n\nexport class PluvIO<T extends IODefs = IODefs> {\n public readonly version: string = __PLUV_VERSION as any;\n\n private readonly _context: PluvContext<T[\"platform\"], T[\"context\"]> = {} as PluvContext<\n T[\"platform\"],\n T[\"context\"]\n >;\n private readonly _debug: boolean;\n private readonly _limits: PluvIOLimits;\n private readonly _platform: () => T[\"platform\"];\n private readonly _secret: PluvIOSecret<T[\"platform\"]>;\n private readonly _treaty: T[\"treaty\"];\n\n public get procedure(): PluvProcedure<T, {}, {}> {\n return new PluvProcedure();\n }\n\n constructor(options: PluvIOConfig<T>) {\n const { context, debug = false, limits, platform, secret, treaty } = options;\n\n this._debug = debug;\n this._limits = {\n dangerouslyAllowHighPresenceFanout: false,\n maxConnections: DEFAULT_MAX_CONNECTIONS,\n presenceMaxSize: MAX_PRESENCE_SIZE_BYTES,\n storageMaxSize: MAX_STORAGE_SIZE_BYTES,\n userIdMaxLength: MAX_USER_ID_LENGTH,\n userMaxSize: MAX_USER_SIZE_BYTES,\n ...limits,\n };\n this._platform = platform;\n this._secret = secret;\n this._treaty = treaty;\n\n if (context) this._context = context;\n\n assertPresenceFanoutBudget(this._limits);\n }\n\n public async createToken(\n params: CreateUserTokenParams<InferTreatyUser<T[\"treaty\"]>, T[\"platform\"]>,\n ): Promise<string>;\n public async createToken(\n params: CreateTokenParams<InferTreatyUser<T[\"treaty\"]>, T[\"platform\"]>,\n options: { onGetOperator?: OnGetOperator<InferTreatyUser<T[\"treaty\"]>> | null },\n ): Promise<string>;\n public async createToken(\n params: CreateTokenParams<InferTreatyUser<T[\"treaty\"]>, T[\"platform\"]>,\n options?: { onGetOperator?: OnGetOperator<InferTreatyUser<T[\"treaty\"]>> | null },\n ): Promise<string> {\n const platform = this._platform();\n const token = params as {\n kind?: \"user\" | \"operator\";\n maxAge?: number;\n operator?: unknown;\n room: string;\n user?: unknown;\n };\n const { maxAge: _maxAge, room: _room, ...rest } = token;\n const initRest = isOperatorToken(token)\n ? (() => {\n const { operator: _operator, kind: _kind, ...init } = rest;\n return init;\n })()\n : (() => {\n const { user: _user, kind: _kind, ...init } = rest;\n return init;\n })();\n const initContext = platform.normalizeInitContext(\n initRest as InferInitContextType<T[\"platform\"]>,\n );\n\n const encodeParams = await this._resolveEncodeParams({\n initContext,\n onGetOperator: options?.onGetOperator ?? null,\n token: params,\n });\n const secret = resolveIOSecret(this._secret, encodeParams);\n const ioAuthorize = { user: this._treaty.user, secret };\n\n if (platform._createToken) {\n return await platform._createToken({ ...encodeParams, authorize: ioAuthorize });\n }\n\n if (!secret) throw new Error(\"`secret` was not provided\");\n\n return await authorize({ platform, secret }).encode(\n encodeParams as JWTEncodeParams<any, T[\"platform\"]>,\n );\n }\n\n private async _resolveEncodeParams(\n params: ResolveEncodeParams<T>,\n ): Promise<JWTEncodeParams<InferTreatyUser<T[\"treaty\"]>, T[\"platform\"]>> {\n const { initContext, onGetOperator, token } = params;\n switch (token.kind) {\n case \"operator\": {\n if (!onGetOperator) {\n throw new Error(\n \"`onGetOperator` must be set on `io.server()`; mint operator tokens with `ioServer.createToken`\",\n );\n }\n\n const operator = parseOperatorUser(token.operator);\n\n if (typeof token.operator.email !== \"string\" || token.operator.email.length === 0) {\n throw new Error(\"Invalid operator email\");\n }\n\n this._assertIdLength(operator.id, \"operator\");\n\n const derived = await onGetOperator({\n operator: { ...operator, email: token.operator.email },\n room: token.room,\n });\n\n if (!derived) {\n throw new Error(\"`onGetOperator` returned null\");\n }\n\n const parsed = parsePluvSchema(this._treaty.user, derived) as InferTreatyUser<\n T[\"treaty\"]\n >;\n\n this._assertUserLimits({ operator, user: parsed });\n\n return {\n ...token,\n ...initContext,\n kind: \"operator\",\n operator,\n user: parsed,\n };\n }\n case \"user\":\n case undefined: {\n const parsed = parsePluvSchema(this._treaty.user, token.user) as InferTreatyUser<\n T[\"treaty\"]\n >;\n\n this._assertUserLimits({ user: parsed });\n\n return {\n ...token,\n ...initContext,\n kind: \"user\",\n user: parsed,\n };\n }\n default:\n return assertExhaustive(token);\n }\n }\n\n private _assertIdLength(id: string, label: \"user\" | \"operator\"): void {\n if (!this._limits.userIdMaxLength || id.length <= this._limits.userIdMaxLength) return;\n\n throw new Error(oneLine`\n createToken was called with a long ${label} id. ID must be at\n most ${this._limits.userIdMaxLength.toLocaleString()} characters.\n Current length: ${id.length.toLocaleString()}\n `);\n }\n\n private _assertUserLimits(params: {\n operator?: OperatorUser | null;\n user: InferTreatyUser<T[\"treaty\"]>;\n }): void {\n const { operator, user } = params;\n this._assertIdLength(user.id, \"user\");\n\n const userBytes = new TextEncoder().encode(JSON.stringify(user)).length;\n const operatorBytes = operator\n ? new TextEncoder().encode(JSON.stringify(operator)).length\n : 0;\n const bytes = userBytes + operatorBytes;\n\n if (!this._limits.userMaxSize || bytes <= this._limits.userMaxSize) return;\n\n const subject = operator ? \"User and operator together must\" : \"User must\";\n\n throw new Error(oneLine`\n createToken called with large payload. ${subject} be at most\n ${this._limits.userMaxSize.toLocaleString()} bytes. Current size:\n ${bytes.toLocaleString()} bytes\n `);\n }\n\n public mergeRouters<TRouters extends PluvRouter<SetKey<T, \"events\", any>>[]>(\n ...routers: TRouters\n ): MergedRouter<TRouters, T> {\n return PluvRouter.merge(...routers) as MergedRouter<TRouters, T>;\n }\n\n public router<TEvents extends PluvRouterEventConfig<T>>(\n events: TEvents,\n ): PluvRouter<SetKey<T, \"events\", TEvents>> {\n return new PluvRouter<SetKey<T, \"events\", TEvents>>(events);\n }\n\n public server<TEvents extends PluvRouterEventConfig<T> = {}>(\n ...config: ServerConfig<SetKey<T, \"events\", TEvents>>\n ): PluvServer<SetKey<T, \"events\", TEvents>> {\n const serverConfig = (config[0] ?? {}) as PluvServerConfig<SetKey<T, \"events\", TEvents>>;\n\n return new PluvServer<SetKey<T, \"events\", TEvents>>({\n ...serverConfig,\n context: this._context,\n debug: this._debug,\n io: this,\n limits: this._limits,\n platform: this._platform,\n secret: this._secret,\n treaty: this._treaty,\n });\n }\n}\n","import type { TreatyLike } from \"@pluv/types\";\nimport type { AbstractPlatform } from \"./AbstractPlatform\";\nimport { PluvIO } from \"./PluvIO\";\nimport type { PluvContext, PluvIOLimits, PluvIOSecret } from \"./types\";\n\nexport type IOConfigParams<\n TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,\n TTreaty extends TreatyLike = TreatyLike,\n TContext extends Record<string, any> = {},\n> = {\n context?: PluvContext<TPlatform, TContext>;\n debug?: boolean;\n limits?: PluvIOLimits;\n secret: PluvIOSecret<TPlatform>;\n treaty: TTreaty;\n};\n\nexport type IOPlatformFactory<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>> =\n () => TPlatform;\n\ntype ConfiguredIODefs<\n TPlatform extends AbstractPlatform<any>,\n TTreaty extends TreatyLike,\n TContext extends Record<string, any>,\n> = {\n platform: TPlatform;\n treaty: TTreaty;\n context: TContext;\n events: {};\n};\n\nexport interface IOConfigBuilder<TPlatform extends AbstractPlatform<any>> {\n config: <TTreaty extends TreatyLike, TContext extends Record<string, any> = {}>(\n params: IOConfigParams<TPlatform, TTreaty, TContext>,\n ) => PluvIO<ConfiguredIODefs<TPlatform, TTreaty, TContext>>;\n}\n\nexport interface IOPlatformBuilder {\n platform: <TPlatform extends AbstractPlatform<any>>(\n platform: IOPlatformFactory<TPlatform>,\n ) => IOConfigBuilder<TPlatform>;\n}\n\nexport const createIO = (): IOPlatformBuilder => ({\n platform: <TPlatform extends AbstractPlatform<any>>(\n platform: IOPlatformFactory<TPlatform>,\n ) => ({\n config: <TTreaty extends TreatyLike, TContext extends Record<string, any> = {}>(\n params: IOConfigParams<TPlatform, TTreaty, TContext>,\n ): PluvIO<ConfiguredIODefs<TPlatform, TTreaty, TContext>> => {\n const { context, debug, limits, secret, treaty } = params;\n\n return new PluvIO<ConfiguredIODefs<TPlatform, TTreaty, TContext>>({\n context,\n debug,\n limits,\n platform,\n secret,\n treaty,\n });\n },\n }),\n});\n","import { ROOM_STATS_THROTTLE_MS, SERVER_ORIGIN_EVENTS, isServerOriginEvent } from \"./constants\";\nimport { createBaseRouter } from \"./createBaseRouter\";\nimport {\n assertPresenceFanoutBudget,\n createInternalPluvRouter,\n getMyConnectionIds,\n getRoomStatsFromSessions,\n groupLiveUsers,\n listLiveUsers,\n pageLiveUsers,\n resolveListUsersLimit,\n resolveMaxConnections,\n throttle,\n} from \"./utils\";\n\n/**\n * Maintainer / test-only surface. Not part of the public API — shape and\n * contents may change without a semver bump. Prefer public exports for apps.\n */\nexport const __internal = {\n assertPresenceFanoutBudget,\n createBaseRouter,\n createInternalPluvRouter,\n getMyConnectionIds,\n getRoomStatsFromSessions,\n groupLiveUsers,\n isServerOriginEvent,\n listLiveUsers,\n pageLiveUsers,\n resolveListUsersLimit,\n resolveMaxConnections,\n ROOM_STATS_THROTTLE_MS,\n SERVER_ORIGIN_EVENTS,\n throttle,\n};\n","/**\n * Runs tasks one at a time while `known` is false.\n * Once `known` returns true, tasks run immediately.\n * A task already running here cannot call `run`; that waits for itself.\n */\nexport class ExclusiveUntil {\n private _tail: Promise<void> = Promise.resolve();\n\n public constructor(private readonly known: () => boolean) {}\n\n public async run<T>(task: () => Promise<T>): Promise<T> {\n if (this.known()) return task();\n\n const previous = this._tail;\n let release!: () => void;\n\n this._tail = new Promise<void>((resolve) => {\n release = resolve;\n });\n\n await previous;\n\n if (this.known()) {\n release();\n\n return task();\n }\n\n try {\n return await task();\n } finally {\n release();\n }\n }\n}\n","/**\n * Runs async tasks one at a time.\n * A task already running here cannot wait on `join`; that waits for itself.\n * `finish` is how a task waits for a promise and then comes back.\n */\nexport class JoinQueue {\n private _tail: Promise<void> = Promise.resolve();\n\n /**\n * Runs `task` on this queue. `{ value }` is passed to `finish` before the\n * task releases. `{ pending }` is awaited after it releases, and `finish`\n * runs on the next join. `{ suspended: true }` releases the queue and does\n * not run `finish`.\n */\n public async finish<TValue>(\n task: () => Promise<{ pending: Promise<TValue> } | { value: TValue } | { suspended: true }>,\n finish: (value: TValue) => Promise<void>,\n ): Promise<void> {\n const deferred: { pending: Promise<TValue> | null } = { pending: null };\n\n await this.join(async () => {\n const result = await task();\n\n if (\"suspended\" in result) return;\n\n if (\"pending\" in result) {\n deferred.pending = result.pending;\n\n return;\n }\n\n await finish(result.value);\n });\n\n if (!deferred.pending) return;\n\n const value = await deferred.pending;\n\n await this.join(() => finish(value));\n }\n\n public join<TResult>(task: () => Promise<TResult>): Promise<TResult> {\n const run = this._tail.then(task, task);\n\n this._tail = run.then(\n () => undefined,\n () => undefined,\n );\n\n return run;\n }\n}\n","import type { JsonObject, ParticipantKind } from \"@pluv/types\";\nimport { AbstractWebSocket } from \"./AbstractWebSocket\";\nimport { PING_TIMEOUT_MS } from \"./constants\";\nimport type { IODefs } from \"./IODefs\";\nimport type { WebSocketSession, WebSocketType } from \"./types\";\nimport { assertExhaustive, getSessionKind } from \"./utils\";\n\nexport interface ParticipantSessionParams {\n id: string;\n kind: ParticipantKind;\n sessionId: string;\n}\n\nexport interface PatchPresenceParams {\n presence: JsonObject | null;\n seq?: number | null;\n sessionId: string;\n}\n\nexport interface RoomSessionsConfig<T extends IODefs = IODefs> {\n platform: T[\"platform\"];\n}\n\nexport class RoomSessions<T extends IODefs = IODefs> {\n private readonly _platform: T[\"platform\"];\n private readonly _participantSessions = {\n operator: new Map<string, Set<string>>(),\n user: new Map<string, Set<string>>(),\n };\n private readonly _sessions = new Map<[sessionId: string][0], AbstractWebSocket>();\n\n constructor(config: RoomSessionsConfig<T>) {\n this._platform = config.platform;\n }\n\n public all(): ReadonlyMap<string, AbstractWebSocket> {\n return this._sessions;\n }\n\n public addUserSession(userId: string, sessionId: string): Set<[sessionId: string][0]> {\n return this.addParticipantSession({ id: userId, kind: \"user\", sessionId });\n }\n\n public addParticipantSession(params: ParticipantSessionParams): Set<[sessionId: string][0]> {\n const { id, kind, sessionId } = params;\n const sessions = this._sessionsForKind(kind);\n const set = sessions.get(id) ?? new Set<string>();\n const updated = set.add(sessionId);\n\n sessions.set(id, updated);\n\n return updated;\n }\n\n public delete(sessionId: string): boolean {\n return this._sessions.delete(sessionId);\n }\n\n public deleteConnection(sessionId: string): AbstractWebSocket | null {\n const webSocket = this._sessions.get(sessionId) ?? null;\n\n if (!webSocket) return null;\n\n webSocket.state = { ...webSocket.state, quit: true };\n this._sessions.delete(sessionId);\n\n return webSocket;\n }\n\n public get(sessionId: string): AbstractWebSocket | undefined {\n return this._sessions.get(sessionId);\n }\n\n public getLatestPresence(\n id: string,\n kind: ParticipantKind = \"user\",\n ): {\n presence: JsonObject | null;\n seq: number | null;\n } {\n const sessionIds = Array.from(this._sessionsForKind(kind).get(id)?.values() ?? []);\n\n if (!sessionIds.length) return { presence: null, seq: null };\n\n return sessionIds.reduce(\n (state, sessionId) => {\n const pluvWs = this._sessions.get(sessionId) ?? null;\n\n if (!pluvWs) return state;\n\n const session = pluvWs.session;\n const presence = session.presence;\n const seq = session.seq.presence;\n const sessionKind = getSessionKind(session);\n const participantId = session.user?.id;\n\n if (sessionKind !== kind || participantId !== id) return state;\n if (typeof state.seq !== \"number\") return { presence, seq };\n if (typeof seq !== \"number\") return state;\n\n return seq > state.seq ? { presence, seq } : state;\n },\n { presence: null, seq: null } as {\n presence: JsonObject | null;\n seq: number | null;\n },\n );\n }\n\n public getQuitters(): readonly AbstractWebSocket[] {\n const currentTime = new Date().getTime();\n\n return Array.from(this._sessions.values()).filter(\n (pluvWs) => !this._isLive(pluvWs, currentTime),\n );\n }\n\n public getSession(webSocket: WebSocketType<T[\"platform\"]>): WebSocketSession<T> {\n const pluvWs = this.resolve(webSocket);\n\n if (!pluvWs) throw new Error(\"Session could not be found\");\n\n return this.toSession(pluvWs);\n }\n\n public getSessions(): readonly WebSocketSession<T>[] {\n return Array.from(this._sessions.values()).map((pluvWs) => this.toSession(pluvWs));\n }\n\n public getLiveSessions(currentTime: number = Date.now()): readonly WebSocketSession<T>[] {\n return Array.from(this._sessions.values())\n .filter((pluvWs) => this._isLive(pluvWs, currentTime))\n .map((pluvWs) => this.toSession(pluvWs));\n }\n\n public getSize(): number {\n const currentTime = new Date().getTime();\n\n /**\n * @description Doing this instead of .size because some sessions\n * in the map can be considered as \"omitted\".\n * @date December 21, 2022\n */\n return Array.from(this._sessions.values()).reduce((count, pluvWs) => {\n return this._isLive(pluvWs, currentTime) ? count + 1 : count;\n }, 0);\n }\n\n public has(sessionId: string): boolean {\n return this._sessions.has(sessionId);\n }\n\n public removeUserSession(\n userId: string,\n sessionId: string,\n ): Set<[sessionId: string][0]> | null {\n return this.removeParticipantSession({ id: userId, kind: \"user\", sessionId });\n }\n\n public removeParticipantSession(\n params: ParticipantSessionParams,\n ): Set<[sessionId: string][0]> | null {\n const { id, kind, sessionId } = params;\n const sessions = this._sessionsForKind(kind);\n const set = sessions.get(id);\n\n if (!set) return null;\n\n set.delete(sessionId);\n\n if (!!set.size) return set;\n\n sessions.delete(id);\n\n return set;\n }\n\n public resolve(webSocket: WebSocketType<T[\"platform\"]>): AbstractWebSocket | null {\n if ((webSocket as unknown as any) instanceof AbstractWebSocket) return webSocket;\n\n const sessionId = this._platform.getSessionId(webSocket);\n\n if (typeof sessionId === \"string\") {\n const session = this._sessions.get(sessionId) ?? null;\n\n if (session) return session;\n }\n\n const sessions = Array.from(this._sessions.values());\n\n return sessions.find((pluvWs) => pluvWs.webSocket === webSocket) ?? null;\n }\n\n public set(sessionId: string, webSocket: AbstractWebSocket): this {\n this._sessions.set(sessionId, webSocket);\n\n return this;\n }\n\n public setPresence(params: PatchPresenceParams): void {\n const { presence, seq: requested, sessionId } = params;\n const pluvWs = this._sessions.get(sessionId) ?? null;\n\n if (!pluvWs) return;\n\n // `seq` is the value the caller observed. A newer write, such as\n // $updatePresence during an async procedure, bumps the socket first.\n if (requested !== undefined && (pluvWs.session.seq.presence ?? null) !== requested) return;\n\n const wsSession = pluvWs.session;\n const kind = getSessionKind(wsSession);\n const participantId = wsSession.user?.id;\n const sessionIds = participantId\n ? new Set<string>([\n ...(this._sessionsForKind(kind).get(participantId) ?? []),\n sessionId,\n ])\n : new Set([sessionId]);\n const currentMax = Array.from(sessionIds).reduce<number | null>((max, sId) => {\n const seq = this._sessions.get(sId)?.session.seq.presence ?? null;\n\n if (typeof seq !== \"number\") return max;\n if (typeof max !== \"number\") return seq;\n\n return seq > max ? seq : max;\n }, null);\n const next = typeof currentMax === \"number\" ? currentMax + 1 : 1;\n\n sessionIds.forEach((sId) => {\n const session = this._sessions.get(sId)?.session;\n\n if (!session) return;\n\n const prevState = session.webSocket.state;\n\n this._platform.setSerializedState(session.webSocket, {\n ...prevState,\n presence,\n seq: {\n ...prevState.seq,\n presence: next,\n },\n });\n });\n }\n\n public toSession(pluvWs: AbstractWebSocket): WebSocketSession<T> {\n return pluvWs.session as WebSocketSession<T>;\n }\n\n public values(): IterableIterator<AbstractWebSocket> {\n return this._sessions.values();\n }\n\n private _sessionsForKind(kind: ParticipantKind): Map<string, Set<string>> {\n switch (kind) {\n case \"operator\":\n return this._participantSessions.operator;\n case \"user\":\n return this._participantSessions.user;\n default:\n return assertExhaustive(kind);\n }\n }\n\n private _isLive(pluvWs: AbstractWebSocket, currentTime: number): boolean {\n if (pluvWs.state.quit) return false;\n\n const pingTime = this._platform.getLastPing(pluvWs) ?? pluvWs.state.timers.ping;\n\n return currentTime - pingTime <= PING_TIMEOUT_MS;\n }\n}\n","const PROMISE_TRAP_KEYS = new Set([\"then\", \"catch\", \"finally\"]);\n\nexport const createHostTreatyProcedureProxy = <\n TInvoke extends (name: string, data: unknown) => Promise<void>,\n>(\n invoke: TInvoke,\n): TInvoke => {\n return new Proxy(invoke, {\n get(target, prop, receiver) {\n if (typeof prop !== \"string\" || PROMISE_TRAP_KEYS.has(prop)) {\n return Reflect.get(target, prop, receiver);\n }\n\n return (data: unknown) => target(prop, data);\n },\n });\n};\n","import type { TreatyLike, TreatyProcedureInputJson } from \"@pluv/types\";\n\nexport type TreatyDomainSchema = {\n schema: unknown;\n procedures: Record<string, TreatyProcedureInputJson>;\n};\n\nexport type TreatySchemaJson = {\n user: unknown;\n presence: TreatyDomainSchema | null;\n storage: TreatyDomainSchema | null;\n};\n\nexport const readTreatySchema = (treaty: TreatyLike): TreatySchemaJson => {\n const procedures = treaty.toProceduresJson();\n\n return {\n user: treaty.toUserJson(),\n presence: treaty.presence\n ? { schema: treaty.toPresenceJson(), procedures: procedures.presence }\n : null,\n storage: treaty.storage\n ? { schema: treaty.toStorageJson(), procedures: procedures.storage }\n : null,\n };\n};\n","import type { HostTreatyProcedureActor } from \"../IORoom\";\n\nexport const resolveHostTreatyProcedureSenderId = (\n actor: HostTreatyProcedureActor | null | undefined,\n): string => {\n const senderId = actor != null && typeof actor === \"object\" ? actor.senderId : undefined;\n\n if (typeof senderId !== \"string\") {\n throw new Error(\"Host treaty invoke expected { senderId: string }\");\n }\n\n return senderId;\n};\n","import type {\n EventMessage,\n Id,\n InferIOInput,\n IOEventMessage,\n JsonObject,\n ListUsersOptions,\n ListUsersResult,\n PresenceProcedureProxy,\n} from \"@pluv/types\";\nimport type { InferInitContextType, InferPlatformWebSocketSource } from \"../AbstractPlatform\";\nimport type { IOPubSubEventMessage } from \"../AbstractPubSub\";\nimport type {\n AbstractCloseEvent,\n AbstractErrorEvent,\n AbstractMessageEvent,\n} from \"../AbstractWebSocket\";\nimport { AbstractWebSocket } from \"../AbstractWebSocket\";\nimport type { IODefs } from \"../IODefs\";\nimport type {\n HostPresenceInvoke,\n HostStorageInvoke,\n HostTreatyProcedureActor,\n IORoom,\n} from \"../IORoom\";\nimport type {\n LoadedStorage,\n RoomEffectFrame,\n RoomEffects,\n RoomSessionSnapshot,\n SessionRoom,\n WebSocketRegisterConfig,\n} from \"../types\";\nimport {\n deferredResultPromise,\n isDeferredResult,\n isErrorMessage,\n isSuspended,\n} from \"../roomEffects\";\nimport { ExclusiveUntil } from \"../ExclusiveUntil\";\nimport { CommitGate } from \"../CommitGate\";\nimport { JoinQueue } from \"../JoinQueue\";\n\nconst isLoadedStorage = <T extends IODefs>(\n value: RoomEffects<T> | LoadedStorage<T>,\n): value is LoadedStorage<T> => !(\"broadcast\" in value);\nimport { RoomSessions } from \"../RoomSessions\";\nimport { createSessionRouter } from \"../createSessionRouter\";\nimport {\n GARBAGE_COLLECT_INTERVAL_MS,\n PING_TIMEOUT_MS,\n ROOM_STATS_THROTTLE_MS,\n STORAGE_SNAPSHOT_INTERVAL_MS,\n isServerOriginEvent,\n} from \"../constants\";\nimport type { SendMessageOptions, SessionEventContext, WebSocketType } from \"../types\";\nimport { createHostTreatyProcedureProxy } from \"./createHostTreatyProcedureProxy\";\nimport { readTreatySchema, type TreatySchemaJson } from \"./readTreatySchema\";\nimport { resolveHostTreatyProcedureSenderId } from \"./resolveHostTreatyProcedureSenderId\";\nimport {\n assertExhaustive,\n getRoomStatsFromSessions,\n getSessionKind,\n getSessionOperator,\n invokeProcedureResolvers,\n oneLine,\n pageLiveUsers,\n parsePluvSchema,\n resolveMaxConnections,\n throttle,\n} from \"../utils\";\nimport colors from \"kleur\";\n\nexport type BroadcastProxy<TIO extends IORoom<any>> = (<TEvent extends keyof InferIOInput<TIO>>(\n event: TEvent,\n data: Id<InferIOInput<TIO>[TEvent]>,\n senderId: string,\n) => Promise<void>) & {\n [event in keyof InferIOInput<TIO>]: (\n data: Id<InferIOInput<TIO>>[event],\n senderId: string,\n ) => Promise<void>;\n};\n\n/**\n * Session manager for one room. `createRoom` returns the room.\n * `manageSessions` attaches the sockets.\n */\nexport class RoomSessionManager<T extends IODefs = IODefs> {\n public readonly broadcast: BroadcastProxy<IORoom<T>>;\n public readonly __experimental_presence: HostPresenceInvoke<IORoom<T>>;\n public readonly __experimental_storage: HostStorageInvoke<IORoom<T>>;\n\n private readonly _platform: T[\"platform\"];\n private readonly _sessions: RoomSessions<T>;\n private readonly _sessionRouter: ReturnType<typeof createSessionRouter<T>>;\n private readonly _roomStats: ReturnType<typeof throttle>;\n private readonly _queue = new JoinQueue();\n private readonly _limits = new ExclusiveUntil(() => this._room.limits !== null);\n private _closing = 0;\n private _connecting = 0;\n private _registering = 0;\n private _storageSnapshotRun: Promise<void> | null = null;\n private readonly _commitGate = new CommitGate();\n private _retry: Promise<void> | null = null;\n private _lastGarbageCollectMs = -1 * (GARBAGE_COLLECT_INTERVAL_MS + 1);\n /** Procedure frames whose delivery failed. This isolate outlives the facet. */\n private _unsent: { effects: RoomEffects<T>; id: number }[] = [];\n private _unsentId = 0;\n private _treatySchema?: TreatySchemaJson;\n\n constructor(\n private readonly _room: SessionRoom<T>,\n platform: T[\"platform\"],\n ) {\n this._platform = platform;\n this._sessions = new RoomSessions<T>({ platform: this._platform });\n this._sessionRouter = createSessionRouter<T>({\n limits: () => this._room.limits,\n });\n this._roomStats = throttle(\n () => {\n void this._emitRoomStats();\n },\n { wait: ROOM_STATS_THROTTLE_MS },\n );\n this.broadcast = this._createBroadcast();\n this.__experimental_presence = this._createPresence();\n this.__experimental_storage = this._createStorage();\n\n this._hydrate();\n void this._platform.pubSub.subscribe(this._room.id, async (payload) => {\n await this._onPublished(payload);\n });\n }\n\n public get id(): string {\n return this._room.id;\n }\n\n public getTreatySchema(): TreatySchemaJson {\n this._treatySchema ??= readTreatySchema(this._room.treaty);\n\n return structuredClone(this._treatySchema);\n }\n\n public async register(\n webSocket: InferPlatformWebSocketSource<T[\"platform\"]>,\n ...options: keyof InferInitContextType<T[\"platform\"]> extends never\n ? [{ token?: string }?]\n : [WebSocketRegisterConfig<T[\"platform\"]>]\n ): Promise<void> {\n const sessionId = this._platform.getSessionId(webSocket);\n\n if (typeof sessionId === \"string\" && this._sessions.has(sessionId)) return;\n\n await this._limits.run(async () => {\n const limits = this._room.limits;\n const maxConnections = limits ? resolveMaxConnections(limits) : null;\n const rejectMaxConnections = (): void => {\n const rejected = this._platform.convertWebSocket(webSocket, {\n room: this._room.id,\n });\n const limit = maxConnections ?? 0;\n\n rejected.handleError({\n error: new Error(`Room is at maxConnections (${limit.toLocaleString()}).`),\n room: this._room.id,\n });\n rejected.close(4000, \"Room is at maxConnections\");\n };\n\n if (\n maxConnections !== null &&\n this._sessions.getSize() + this._registering >= maxConnections\n ) {\n rejectMaxConnections();\n\n return;\n }\n\n this._registering += 1;\n\n let reserved = true;\n const releaseReservation = (): void => {\n if (!reserved) return;\n\n reserved = false;\n this._registering -= 1;\n };\n\n await this._queue.finish<{\n effects: RoomEffects<T> | null;\n socket: AbstractWebSocket;\n } | null>(\n async () => {\n try {\n const result = await this._room[\"~\"].register(...options);\n\n if (result.error || !result.user || !result.kind) {\n const rejected = this._platform.convertWebSocket(webSocket, {\n room: this._room.id,\n });\n\n rejected.handleError({\n error: result.error ?? new Error(\"Not authorized\"),\n room: this._room.id,\n });\n rejected.close(3000, \"WebSocket unauthorized.\");\n\n return { value: null };\n }\n\n const pluvWs = this._platform.convertWebSocket(webSocket, {\n room: this._room.id,\n });\n const participantId = result.user.id;\n const latest = this._sessions.getLatestPresence(participantId, result.kind);\n const prevState = pluvWs.state;\n\n pluvWs.user = result.user;\n this._platform.setSerializedState(pluvWs, {\n ...prevState,\n kind: result.kind,\n operator: result.operator,\n presence: latest.presence,\n seq: { ...prevState.seq, presence: latest.seq },\n });\n this._sessions.addParticipantSession({\n id: participantId,\n kind: result.kind,\n sessionId: pluvWs.sessionId,\n });\n this._room[\"~\"].logDebug(\n `${colors.blue(`Registering connection for room ${this._room.id}:`)} ${pluvWs.sessionId}`,\n );\n await this._platform.acceptWebSocket(pluvWs);\n this._sessions.set(pluvWs.sessionId, pluvWs);\n releaseReservation();\n await this._platform.persistence.addUser(\n this._room.id,\n pluvWs.sessionId,\n result.user,\n );\n\n const registered = this._sessions.toSession(pluvWs);\n const stats = getRoomStatsFromSessions(this._sessions.getLiveSessions());\n\n await this._writeFrames(\n [\n {\n connectionId: registered.id,\n data: {\n session: {\n kind: result.kind,\n operator: result.operator,\n presence: registered.presence,\n seq: { presence: registered.seq.presence },\n },\n sessionId: registered.id,\n state: result.encodedState,\n stats,\n },\n operator: result.operator,\n type: \"$registered\",\n user: result.user,\n },\n ],\n \"self\",\n );\n\n const { encodedState, kind, operator, user } = result;\n\n if (!kind || !user) return { value: null };\n\n this._connecting += 1;\n\n return {\n pending: this._room[\"~\"]\n .userConnected({\n encodedState,\n id: pluvWs.sessionId,\n kind,\n operator,\n user,\n })\n .then(\n (effects) => ({ effects, socket: pluvWs }),\n (error: unknown) => {\n console.error(error);\n\n return { effects: null, socket: pluvWs };\n },\n ),\n };\n } catch (error) {\n releaseReservation();\n\n throw error;\n }\n },\n async (connected) => {\n try {\n if (!connected?.effects) return;\n\n await this._applyEffects(connected.effects, connected.socket);\n this._roomStats.schedule();\n this._room[\"~\"].logDebug(oneLine`\n ${colors.blue(`Registered connection for room ${this._room.id}:`)}\n ${connected.socket.sessionId}\n `);\n this._room[\"~\"].logDebug(\n `${colors.blue(`Room ${this._room.id} size:`)} ${this._sessions.getSize()}`,\n );\n } finally {\n releaseReservation();\n\n if (connected) {\n this._connecting -= 1;\n await this._destroyEmptyRoom();\n }\n }\n },\n );\n });\n }\n\n public applyFrames(effects: RoomEffects<T>, senderId: string): Promise<void> {\n return this._queue.join(async () => {\n await this._applyEffects(effects, this._socket(senderId));\n });\n }\n\n /** Writes sockets only. The facet drops storage after `deliverFrames` returns. */\n public writeFrames(effects: RoomEffects<T>, senderId: string): Promise<void> {\n return this._queue.join(async () => {\n await this._applyEffects(effects, this._socket(senderId), false);\n });\n }\n\n public applyPresence(params: {\n name: string;\n patch: JsonObject | null;\n senderId: string;\n }): Promise<void> {\n const socket = this._sessions.get(params.senderId) ?? null;\n\n if (!socket) return Promise.resolve();\n\n return this._queue.join(async () => {\n const context = this._sessionContext(socket);\n const broadcastResult =\n await this._sessionRouter._defs.events.$updatePresence.config.broadcast?.(\n { presence: params.patch, procedure: params.name },\n context,\n );\n\n await this._deliverRecord(\n broadcastResult as Record<string, unknown> | null,\n socket,\n \"broadcast\",\n );\n });\n }\n\n public onMessage(\n webSocket: WebSocketType<T[\"platform\"]>,\n ): (event: AbstractMessageEvent) => Promise<void> {\n const socket = this._sessions.resolve(webSocket);\n\n if (!socket) return async () => undefined;\n\n return this._onSocketMessage(webSocket);\n }\n\n public onClose(\n webSocket: WebSocketType<T[\"platform\"]>,\n ): (event: AbstractCloseEvent) => Promise<void> {\n return async (event) => {\n const socket = this._sessions.resolve(webSocket);\n\n if (!socket) return;\n if (!this._sessions.has(socket.sessionId)) return;\n\n await this._disconnect(socket, event.code, event.reason, false);\n };\n }\n\n public onError(\n webSocket: WebSocketType<T[\"platform\"]>,\n ): (event: AbstractErrorEvent) => Promise<void> {\n return async () => {\n const socket = this._sessions.resolve(webSocket);\n\n if (!socket) return;\n if (!this._sessions.has(socket.sessionId)) return;\n\n await this._disconnect(socket, 1011, \"\", false);\n };\n }\n\n public async garbageCollect(): Promise<void> {\n this._lastGarbageCollectMs = Date.now();\n\n const quitting = await this._queue.join(async () =>\n Array.from(this._sessions.values()).filter((socket) => !this._isLiveSocket(socket)),\n );\n\n if (!quitting.length) {\n if (this._sessions.getSize() === 0) this._roomStats.cancel();\n else this._roomStats.schedule();\n\n return;\n }\n\n await this._unregisterSockets({\n code: 1000,\n reason: \"Ping timed out.\",\n sockets: quitting,\n closeSocket: true,\n sync: true,\n });\n }\n\n public async evict(sessionId: string): Promise<void> {\n const socket = this._sessions.get(sessionId);\n\n if (!socket) return;\n\n socket.state.quit = true;\n await this._evictSockets({ code: 1000, reason: \"\", sockets: [socket] });\n }\n\n public async evictAll(): Promise<void> {\n const sockets = Array.from(this._sessions.values());\n\n sockets.forEach((socket) => {\n socket.state.quit = true;\n });\n await this._evictSockets({ code: 1000, reason: \"\", sockets });\n }\n\n public getSize(): number {\n return this._sessions.getSize();\n }\n\n public noteStorageDirty(): void {\n if (this._storageSnapshotRun) return;\n\n const run = this._snapshotUntilClean();\n\n this._storageSnapshotRun = run;\n this._platform.keepAlive(run);\n void run.finally(() => {\n if (this._storageSnapshotRun === run) this._storageSnapshotRun = null;\n });\n }\n\n public retryUnsent(effects: RoomEffects<T>): void {\n this._unsentId += 1;\n this._unsent.push({ effects, id: this._unsentId });\n\n if (this._retry) return;\n\n const run = this._deliverUnsent();\n\n this._retry = run;\n this._platform.keepAlive(run);\n void run.finally(() => {\n if (this._retry === run) this._retry = null;\n });\n }\n\n public listUsers(options: ListUsersOptions = {}): ListUsersResult<IORoom<T>> {\n return pageLiveUsers(this._sessions.getLiveSessions(), options) as ListUsersResult<\n IORoom<T>\n >;\n }\n\n private _socket(senderId: string): AbstractWebSocket | null {\n return this._sessions.get(senderId) ?? null;\n }\n\n private async _applyEffects(\n effects: RoomEffects<T>,\n sender: AbstractWebSocket | null,\n dropStorage = true,\n ): Promise<void> {\n this._noteStorage(effects);\n\n for (const attachment of effects.attachments) {\n this._sessions.setPresence(attachment);\n }\n\n if (effects.error) {\n const storageFrames = effects.broadcast.filter(\n (frame) => frame.type === \"$storageUpdated\",\n );\n\n if (storageFrames.length) {\n await this._writeFrames(storageFrames, \"broadcast\");\n\n if (dropStorage) await this._room[\"~\"].dropStorageUpdates(storageFrames);\n }\n\n sender?.handleError({\n error: effects.error,\n room: this._room.id,\n ...(sender ? { session: this._sessions.toSession(sender) } : {}),\n });\n\n return;\n }\n\n await this._writeFrames(effects.broadcast, \"broadcast\");\n\n if (dropStorage) {\n const storageFrames = effects.broadcast.filter(\n (frame) => frame.type === \"$storageUpdated\",\n );\n\n if (storageFrames.length) await this._room[\"~\"].dropStorageUpdates(storageFrames);\n }\n\n await this._writeFrames(effects.self, \"self\");\n }\n\n private async _collectPong(): Promise<void> {\n if (Date.now() - this._lastGarbageCollectMs > GARBAGE_COLLECT_INTERVAL_MS) {\n await this.garbageCollect();\n }\n }\n\n private _createBroadcast(): BroadcastProxy<IORoom<T>> {\n const send = <TEvent extends keyof InferIOInput<IORoom<T>>>(\n event: TEvent,\n data: Id<InferIOInput<IORoom<T>>[TEvent]>,\n senderId: string,\n ): Promise<void> => {\n if (typeof senderId !== \"string\") {\n throw new Error(\"room.broadcast of a user event requires a senderId\");\n }\n\n const socket = this._sessions.get(senderId) ?? null;\n const session = socket ? this._sessions.toSession(socket) : null;\n\n return this._publish({\n connectionId: senderId,\n data,\n operator: session ? getSessionOperator(session) : null,\n type: event as string,\n user: session?.user ?? null,\n });\n };\n\n return new Proxy(send, {\n get(fn, prop) {\n return (data: unknown, senderId: string) =>\n fn(prop as never, data as never, senderId);\n },\n }) as BroadcastProxy<IORoom<T>>;\n }\n\n private _createPresence(): HostPresenceInvoke<IORoom<T>> {\n return (actor: HostTreatyProcedureActor) => {\n const senderId = resolveHostTreatyProcedureSenderId(actor);\n\n const invoke = async (name: string, data: unknown): Promise<void> => {\n const socket = this._sessions.get(senderId) ?? null;\n\n if (!socket) throw new Error(`Unknown senderId: ${senderId}`);\n\n await this._queue.finish(\n async () => {\n const patch = await this._room[\"~\"].applyPresencePatch({\n name,\n data,\n session: this._toSnapshot(socket),\n });\n\n if (isDeferredResult(patch)) {\n return { pending: deferredResultPromise(patch) };\n }\n\n if (isSuspended(patch)) {\n if (\"error\" in patch && isErrorMessage(patch.error)) {\n socket.handleError({\n error: patch.error,\n room: this._room.id,\n session: this._sessions.toSession(socket),\n });\n }\n\n return { suspended: true as const };\n }\n\n return { value: patch };\n },\n async (patch) => {\n const context = this._sessionContext(socket);\n const broadcastResult =\n await this._sessionRouter._defs.events.$updatePresence.config.broadcast?.(\n { presence: patch, procedure: name },\n context,\n );\n\n await this._deliverRecord(\n broadcastResult as Record<string, unknown> | null,\n socket,\n \"broadcast\",\n );\n },\n );\n };\n\n return createHostTreatyProcedureProxy(invoke) as PresenceProcedureProxy<\n IORoom<T>[\"_defs\"][\"treaty\"][\"_defs\"][\"procedures\"][\"presence\"]\n >;\n };\n }\n\n private _createStorage(): HostStorageInvoke<IORoom<T>> {\n return (actor: HostTreatyProcedureActor) => {\n const senderId = resolveHostTreatyProcedureSenderId(actor);\n\n const invoke = async (name: string, data: unknown): Promise<void> => {\n const socket = this._sessions.get(senderId) ?? null;\n\n if (!socket) throw new Error(`Unknown senderId: ${senderId}`);\n\n let finishCommit: () => void = () => undefined;\n\n await this._queue.finish(\n async () => {\n try {\n const effects = await this._room[\"~\"].applyStorageProcedure({\n name,\n data,\n actor: this._toSnapshot(socket),\n });\n\n if (!isDeferredResult(effects)) return { value: effects };\n\n const loaded = deferredResultPromise(effects);\n const turn = this._commitGate.reserve();\n\n finishCommit = turn.finish;\n\n // This runs only for a prepared load. The commit waits here, off the\n // queue, until the previous prepared commit finishes. An unprepared\n // write can still commit during that wait.\n const pending: Promise<LoadedStorage<T> | RoomEffects<T>> =\n turn.previous\n .then(\n () => loaded,\n () => loaded,\n )\n .then(\n (value) => value,\n (error: unknown) => {\n turn.finish();\n\n throw error;\n },\n );\n\n return { pending };\n } catch (error) {\n finishCommit();\n await this._retainStorage();\n\n throw error;\n }\n },\n async (loaded: LoadedStorage<T> | RoomEffects<T>) => {\n try {\n const effects = isLoadedStorage(loaded)\n ? await this._room[\"~\"].commitLoadedStorage(loaded)\n : loaded;\n\n this._noteStorage(effects);\n await this._writeFrames(effects.broadcast, \"broadcast\");\n await this._room[\"~\"].dropStorageUpdates(effects.broadcast);\n } catch (error) {\n await this._retainStorage();\n\n throw error;\n } finally {\n finishCommit();\n }\n },\n );\n };\n\n return createHostTreatyProcedureProxy(invoke) as ReturnType<\n HostStorageInvoke<IORoom<T>>\n >;\n };\n }\n\n private async _deliverRecord(\n record: Record<string, unknown> | null | undefined,\n socket: AbstractWebSocket,\n mode: \"broadcast\" | \"self\",\n ): Promise<void> {\n if (!record) return;\n\n const session = this._sessions.toSession(socket);\n const frames = Object.entries(record).map(([type, data]) => ({\n connectionId: session.id,\n data,\n operator: getSessionOperator(session),\n type,\n user: session.user,\n }));\n\n await this._writeFrames(frames, mode);\n }\n\n private async _destroyEmptyRoom(): Promise<void> {\n if (this._sessions.all().size !== 0) return;\n\n if (this._connecting !== 0 || this._registering !== 0) {\n void this._queue.join(() => this._destroyIdleRoom());\n\n return;\n }\n\n await this._destroyIdleRoom();\n }\n\n private async _destroyIdleRoom(): Promise<void> {\n if (this._sessions.all().size !== 0) return;\n\n if (this._connecting !== 0 || this._registering !== 0) return;\n\n // A close still has to send $exit. That close destroys once it finishes.\n if (this._closing !== 0) return;\n\n try {\n await this._room[\"~\"].destroy();\n } catch (error) {\n console.error(error);\n }\n }\n\n private async _disconnect(\n socket: AbstractWebSocket,\n code: number,\n reason: string,\n closeSocket: boolean,\n ): Promise<void> {\n await this._unregisterSockets({\n code,\n reason,\n sockets: [socket],\n closeSocket,\n sync: false,\n });\n }\n\n private async _emitRoomStats(): Promise<void> {\n const stats = getRoomStatsFromSessions(this._sessions.getLiveSessions());\n\n await this._publish({\n connectionId: null,\n data: stats,\n operator: null,\n type: \"$roomStats\",\n user: null,\n });\n }\n\n private async _emitSyncState(): Promise<void> {\n const connectionIds = await this._platform.persistence\n .getUsers(this._room.id)\n .then((map: Map<string, JsonObject | null>) => Object.keys(map));\n\n await this._publish({\n connectionId: null,\n data: { connectionIds },\n operator: null,\n type: \"$syncStateReceived\",\n user: null,\n });\n }\n\n private async _evictSockets(params: {\n code: number;\n reason: string;\n sockets: readonly AbstractWebSocket[];\n }): Promise<void> {\n const { code, reason, sockets } = params;\n const closing = sockets.filter((socket) => this._sessions.has(socket.sessionId));\n\n if (!closing.length) return;\n\n await this._unregisterSockets({\n code,\n reason,\n sockets: closing,\n closeSocket: true,\n sync: false,\n });\n }\n\n private _hydrate(): void {\n const webSockets = this._platform.getWebSockets() as readonly InferPlatformWebSocketSource<\n T[\"platform\"]\n >[];\n\n webSockets.forEach((webSocket) => {\n const deserialized = this._platform.getSerializedState(webSocket);\n const sessionId = this._platform.getSessionId(webSocket);\n\n if (!deserialized) return;\n if (typeof sessionId !== \"string\") return;\n\n const pluvWs = this._platform.convertWebSocket(webSocket, { room: this._room.id });\n\n if (!pluvWs.user) return;\n\n this._sessions.set(sessionId, pluvWs);\n\n const session = pluvWs.session;\n\n this._sessions.addParticipantSession({\n id: session.user.id,\n kind: getSessionKind(session),\n sessionId,\n });\n });\n }\n\n private _isLiveSocket(socket: AbstractWebSocket, now = Date.now()): boolean {\n if (socket.state.quit) return false;\n\n const pingTime = this._platform.getLastPing(socket) ?? socket.state.timers.ping;\n\n return now - pingTime <= PING_TIMEOUT_MS;\n }\n\n private _noteStorage(effects: { storageDirty: boolean }): void {\n if (!effects.storageDirty) return;\n\n this.noteStorageDirty();\n }\n\n /** A failed send leaves the queued update for the snapshot loop. */\n private async _retainStorage(): Promise<void> {\n if (await this._room[\"~\"].storageDirty()) this.noteStorageDirty();\n }\n\n private async _onPublished(payload: IOPubSubEventMessage<any>): Promise<void> {\n const { options = {} as SendMessageOptions, ...message } = payload;\n const frame: RoomEffectFrame<T> = {\n connectionId: message.connectionId,\n data: message.data,\n operator: message.operator,\n type: message.type,\n user: message.user as RoomEffectFrame<T>[\"user\"],\n };\n\n switch (options.type) {\n case \"self\": {\n await this._writeFrames([frame], \"self\");\n\n return;\n }\n case \"broadcast\": {\n const targets = options.sessionIds\n ? options.sessionIds\n .map((sessionId) => this._sessions.get(sessionId) ?? null)\n .filter((socket): socket is AbstractWebSocket => !!socket)\n : Array.from(this._sessions.all().values());\n\n await Promise.allSettled(\n targets.map(async (socket) => {\n await Promise.resolve(\n socket.sendMessage({\n ...frame,\n room: this._room.id,\n } as IOEventMessage<any>),\n );\n }),\n );\n\n return;\n }\n case undefined: {\n const targets = Array.from(this._sessions.all().values());\n\n await Promise.allSettled(\n targets.map(async (socket) => {\n await Promise.resolve(\n socket.sendMessage({\n ...frame,\n room: this._room.id,\n } as IOEventMessage<any>),\n );\n }),\n );\n\n return;\n }\n default:\n assertExhaustive(options);\n }\n }\n\n private _onSocketMessage(webSocket: WebSocketType<T[\"platform\"]>) {\n return async (event: AbstractMessageEvent): Promise<void> => {\n const socket = this._sessions.resolve(webSocket);\n\n if (!socket) throw new Error(\"Could not get session\");\n\n if (socket.state.quit) {\n await this._disconnect(socket, 1011, \"WebSocket broken.\", true);\n\n return;\n }\n\n const message = this._parseMessage(event);\n\n if (!message) return;\n\n const sessionEvent = this._sessionRouter.eventNames.has(message.type);\n\n if (!sessionEvent && !(await this._room[\"~\"].whenReady())) return;\n\n if (sessionEvent) {\n if (message.type === \"$initializeSession\") {\n await this._openSession(socket, message);\n\n return;\n }\n\n await this._runSessionProcedure(socket, message);\n\n return;\n }\n\n await this._queue.finish<RoomEffects<T>>(\n async () => {\n const effects = await this._room[\"~\"].message(\n this._toSnapshot(socket),\n message,\n );\n\n if (isDeferredResult(effects))\n return { pending: deferredResultPromise(effects) };\n\n if (isSuspended(effects)) {\n if (\"error\" in effects && isErrorMessage(effects.error)) {\n socket.handleError({\n error: new Error(effects.error.message),\n room: this._room.id,\n session: this._sessions.toSession(socket),\n });\n }\n\n return { suspended: true as const };\n }\n\n return { value: effects };\n },\n (effects) => this._applyEffects(effects, socket),\n );\n };\n }\n\n private async _openSession(\n socket: AbstractWebSocket,\n message: EventMessage<string, any>,\n ): Promise<void> {\n const procedure = this._sessionRouter._defs.events.$initializeSession;\n const session = this._sessions.toSession(socket);\n\n try {\n const inputs = this._readInputs(procedure, message);\n const context = this._sessionContext(socket);\n const broadcast = await procedure.config.broadcast?.(inputs, context);\n\n await this._queue.join(async () => {\n const storage = await this._room[\"~\"].initializeStorage({\n input: inputs ?? {},\n actor: this._toSnapshot(socket),\n });\n const { storageDirty, ...received } = storage;\n\n if (storageDirty) this.noteStorageDirty();\n\n await this._deliverRecord(\n broadcast as Record<string, unknown> | null,\n socket,\n \"broadcast\",\n );\n await this._deliverRecord({ $storageReceived: received }, socket, \"self\");\n });\n } catch (error) {\n socket.handleError({ error, room: this._room.id, session });\n }\n }\n\n private _parseMessage(message: {\n data: string | ArrayBuffer;\n }): EventMessage<string, any> | null {\n try {\n const parsed = this._platform.parseData(message.data);\n\n if (typeof parsed !== \"object\") return null;\n if (typeof parsed.type !== \"string\") return null;\n if (typeof parsed.data !== \"object\") return null;\n\n return parsed as EventMessage<string, any>;\n } catch {\n return null;\n }\n }\n\n private async _publish(message: {\n connectionId: string | null;\n data: unknown;\n operator: RoomEffectFrame<T>[\"operator\"];\n type: string;\n user: RoomEffectFrame<T>[\"user\"];\n options?: SendMessageOptions;\n }): Promise<void> {\n if (typeof message.connectionId !== \"string\" && !isServerOriginEvent(message.type)) return;\n\n await this._platform.pubSub.publish(this._room.id, {\n ...message,\n room: this._room.id,\n } as IOPubSubEventMessage<any>);\n }\n\n private _readInputs(\n procedure: { config: { input?: any } } | null,\n message: EventMessage<string, any>,\n ): unknown {\n if (!procedure?.config.input) return message.data;\n\n return parsePluvSchema(procedure.config.input, message.data);\n }\n\n private async _removeSocket(socket: AbstractWebSocket): Promise<void> {\n const session = this._sessions.toSession(socket);\n const kind = getSessionKind(session);\n const participantId = session.user?.id;\n\n this._sessions.deleteConnection(socket.sessionId);\n\n if (participantId) {\n this._sessions.removeParticipantSession({\n id: participantId,\n kind,\n sessionId: socket.sessionId,\n });\n }\n\n await this._platform.persistence\n .deleteUser(this._room.id, socket.sessionId)\n .catch(() => null);\n }\n\n private async _runSessionProcedure(\n socket: AbstractWebSocket,\n message: EventMessage<string, any>,\n ): Promise<void> {\n const procedure =\n this._sessionRouter._defs.events[\n message.type as keyof (typeof this._sessionRouter)[\"_defs\"][\"events\"]\n ];\n\n if (!procedure) return;\n\n const session = this._sessions.toSession(socket);\n let inputs: unknown;\n\n try {\n inputs = this._readInputs(procedure, message);\n } catch (error) {\n socket.handleError({ error, room: this._room.id, session });\n\n return;\n }\n\n try {\n const context = this._sessionContext(socket);\n const invoked = invokeProcedureResolvers({\n broadcast: () => procedure.config.broadcast?.(inputs, context),\n self: () => procedure.config.self?.(inputs, context),\n });\n\n if (!invoked.ok) {\n socket.handleError({ error: invoked.error, room: this._room.id, session });\n\n return;\n }\n\n const [broadcast, self] = await Promise.all([invoked.broadcast, invoked.self]);\n\n await this._deliverRecord(\n broadcast as Record<string, unknown> | null,\n socket,\n \"broadcast\",\n );\n await this._deliverRecord(self as Record<string, unknown> | null, socket, \"self\");\n } catch (error) {\n socket.handleError({ error, room: this._room.id, session });\n }\n }\n\n /** Sends procedure frames that `deliverFrames` did not. A failed send stays in this promise and retries after the snapshot interval. */\n private async _deliverUnsent(): Promise<void> {\n while (this._unsent.length) {\n try {\n // oxlint-disable-next-line eslint/no-await-in-loop\n await this._queue.join(async () => {\n const pending = this._unsent.slice();\n\n for (const item of pending) {\n const sender = item.effects.connectionId\n ? (this._sessions.get(item.effects.connectionId) ?? null)\n : null;\n\n // oxlint-disable-next-line eslint/no-await-in-loop\n await this._applyEffects(item.effects, sender);\n this._unsent = this._unsent.filter((held) => held.id !== item.id);\n }\n });\n } catch (error) {\n console.error(error);\n\n // oxlint-disable-next-line eslint/no-await-in-loop\n await new Promise<void>((resolve) => {\n setTimeout(resolve, STORAGE_SNAPSHOT_INTERVAL_MS);\n });\n }\n }\n }\n\n /** One promise. Wait, ask the room for a snapshot, and repeat until that snapshot is current. */\n private async _snapshotUntilClean(): Promise<void> {\n for (;;) {\n // oxlint-disable-next-line eslint/no-await-in-loop\n await new Promise<void>((resolve) => {\n setTimeout(resolve, STORAGE_SNAPSHOT_INTERVAL_MS);\n });\n\n try {\n // oxlint-disable-next-line eslint/no-await-in-loop\n const status = await this._queue.join(async () => {\n const flushed = await this._room[\"~\"].flushSnapshot();\n\n if (flushed.broadcast.length) {\n await this._writeFrames(flushed.broadcast, \"broadcast\");\n await this._room[\"~\"].dropStorageUpdates(flushed.broadcast);\n }\n\n return flushed.status;\n });\n\n if (status === \"closed\") return;\n\n // oxlint-disable-next-line eslint/no-await-in-loop\n const stillDirty = status === \"dirty\" || (await this._room[\"~\"].storageDirty());\n\n if (stillDirty) continue;\n } catch (error) {\n console.error(error);\n\n // oxlint-disable-next-line eslint/no-await-in-loop\n if (await this._room[\"~\"].storageDirty()) continue;\n\n return;\n }\n\n // A write queued during the flush runs before the next macrotask.\n // oxlint-disable-next-line eslint/no-await-in-loop\n await Promise.resolve();\n // oxlint-disable-next-line eslint/no-await-in-loop\n if (await this._room[\"~\"].storageDirty()) continue;\n\n return;\n }\n }\n\n private _sessionContext(socket: AbstractWebSocket): SessionEventContext<T> {\n const sessions = this._sessions;\n const session = sessions.toSession(socket);\n const time = new Date().getTime();\n\n return {\n connectionId: session.id,\n kind: getSessionKind(session),\n operator: getSessionOperator(session),\n platform: this._platform,\n get presence() {\n return (session.webSocket.state.presence ??\n session.presence ??\n null) as SessionEventContext<T>[\"presence\"];\n },\n set presence(presence) {\n sessions.setPresence({\n presence: (presence ?? null) as JsonObject | null,\n sessionId: session.id,\n });\n },\n room: this._room.id,\n session,\n sessions: this._sessions.getLiveSessions(),\n time,\n user: session.user,\n };\n }\n\n private _toSnapshot(socket: AbstractWebSocket): RoomSessionSnapshot<T> {\n const session = this._sessions.toSession(socket);\n\n return {\n id: session.id,\n kind: getSessionKind(session),\n lastPing: this._platform.getLastPing(socket) ?? socket.state.timers.ping,\n operator: getSessionOperator(session),\n presence: session.presence,\n quit: socket.state.quit,\n seq: { presence: session.seq.presence },\n user: session.user,\n };\n }\n\n /**\n * Removes each socket on the queue, then runs `onUserDisconnected` after that\n * join so the listener can await the session manager. `$exit` is written on\n * a later join. Destroy waits until every unregister in progress has sent `$exit`.\n */\n private async _unregisterSockets(params: {\n code: number;\n reason: string;\n sockets: readonly AbstractWebSocket[];\n closeSocket: boolean;\n sync: boolean;\n }): Promise<void> {\n const { code, reason, sockets, closeSocket, sync } = params;\n\n if (!sockets.length) return;\n\n this._closing += 1;\n\n try {\n for (const socket of sockets) {\n // oxlint-disable-next-line eslint/no-await-in-loop\n const snapshot = await this._queue.join(async () => {\n if (!this._sessions.has(socket.sessionId)) return null;\n\n const next = this._toSnapshot(socket);\n\n this._room[\"~\"].logDebug(\n `${colors.blue(`Unregistering connection for room ${this._room.id}:`)} ${next.id}`,\n );\n await this._removeSocket(socket);\n\n return next;\n });\n\n if (!snapshot) continue;\n\n let effects: RoomEffects<T> | null = null;\n\n try {\n // oxlint-disable-next-line eslint/no-await-in-loop\n effects = await this._room[\"~\"].close(snapshot);\n } finally {\n if (closeSocket) socket.close(code, reason);\n }\n\n if (!effects) continue;\n\n const produced = effects;\n\n this._noteStorage(produced);\n\n // oxlint-disable-next-line eslint/no-await-in-loop\n await this._queue.join(async () => {\n await this._writeFrames(produced.broadcast, \"broadcast\");\n await this._room[\"~\"].dropStorageUpdates(produced.broadcast);\n this._room[\"~\"].logDebug(\n `${colors.blue(`Unregistered connection for room ${this._room.id}:`)} ${snapshot.id}`,\n );\n });\n }\n } finally {\n this._closing -= 1;\n await this._queue.join(async () => {\n if (sync) await this._emitSyncState();\n\n await this._destroyEmptyRoom();\n\n if (this._sessions.getSize() === 0) this._roomStats.cancel();\n else this._roomStats.schedule();\n });\n }\n }\n\n private async _writeFrames(\n frames: readonly RoomEffectFrame<T>[],\n mode: \"broadcast\" | \"self\",\n ): Promise<void> {\n if (mode === \"self\") {\n await Promise.all(\n frames.map(async (frame) => {\n const socket = frame.connectionId\n ? (this._sessions.get(frame.connectionId) ?? null)\n : null;\n\n if (!socket) return;\n\n await Promise.resolve(\n socket.sendMessage({\n ...frame,\n room: this._room.id,\n } as IOEventMessage<any>),\n );\n\n if (frame.type === \"$pong\") await this._collectPong();\n }),\n );\n\n return;\n }\n\n await Promise.allSettled(\n Array.from(this._sessions.all().values()).flatMap((socket) =>\n frames.map((frame) =>\n Promise.resolve(\n socket.sendMessage({\n ...frame,\n room: this._room.id,\n } as IOEventMessage<any>),\n ),\n ),\n ),\n );\n }\n}\n","import type { IODefs } from \"./IODefs\";\nimport type { IORoom } from \"./IORoom\";\nimport type { SessionRoom } from \"./types\";\nimport { RoomSessionManager } from \"./RoomSessionManager\";\n\nexport function manageSessions<T extends IODefs = IODefs>(room: IORoom<T>): RoomSessionManager<T>;\nexport function manageSessions<T extends IODefs = IODefs>(\n room: SessionRoom<T>,\n platform: T[\"platform\"],\n): RoomSessionManager<T>;\nexport function manageSessions<T extends IODefs = IODefs>(\n room: IORoom<T> | SessionRoom<T>,\n platform?: T[\"platform\"],\n): RoomSessionManager<T> {\n const full = room as IORoom<T>;\n\n return new RoomSessionManager(full, platform ?? full._defs.platform);\n}\n"],"mappings":"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"}
|