y-partyserver 0.0.53 → 0.0.54
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/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/package.json +3 -3
package/dist/server/index.js
CHANGED
|
@@ -29,7 +29,7 @@ var AttachmentCache = class {
|
|
|
29
29
|
if (!attachment) {
|
|
30
30
|
attachment = WebSocket.prototype.deserializeAttachment.call(ws);
|
|
31
31
|
if (attachment !== void 0) this.#cache.set(ws, attachment);
|
|
32
|
-
else throw new Error("Missing websocket attachment. This is most likely an issue in PartyServer, please open an issue at https://github.com/
|
|
32
|
+
else throw new Error("Missing websocket attachment. This is most likely an issue in PartyServer, please open an issue at https://github.com/cloudflare/partykit/issues");
|
|
33
33
|
}
|
|
34
34
|
return attachment;
|
|
35
35
|
}
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["#cache","#connections","#ParentClass","#_props","#_name","#connectionManager","#attachSocketEventHandlers","#status","#initialize","#_longErrorAboutNameThrown","#sendMessageToConnection","YDoc","controlledIds: Set<number>","#ParentClass","encoder"],"sources":["../../../partyserver/dist/index.js","../../src/server/index.ts"],"sourcesContent":["import { DurableObject } from \"cloudflare:workers\";\nimport { nanoid } from \"nanoid\";\n\n//#region src/connection.ts\nif (!(\"OPEN\" in WebSocket)) {\n\tconst WebSocketStatus = {\n\t\tCONNECTING: WebSocket.READY_STATE_CONNECTING,\n\t\tOPEN: WebSocket.READY_STATE_OPEN,\n\t\tCLOSING: WebSocket.READY_STATE_CLOSING,\n\t\tCLOSED: WebSocket.READY_STATE_CLOSED\n\t};\n\tObject.assign(WebSocket, WebSocketStatus);\n\tObject.assign(WebSocket.prototype, WebSocketStatus);\n}\n/**\n* Cache websocket attachments to avoid having to rehydrate them on every property access.\n*/\nvar AttachmentCache = class {\n\t#cache = /* @__PURE__ */ new WeakMap();\n\tget(ws) {\n\t\tlet attachment = this.#cache.get(ws);\n\t\tif (!attachment) {\n\t\t\tattachment = WebSocket.prototype.deserializeAttachment.call(ws);\n\t\t\tif (attachment !== void 0) this.#cache.set(ws, attachment);\n\t\t\telse throw new Error(\"Missing websocket attachment. This is most likely an issue in PartyServer, please open an issue at https://github.com/threepointone/partyserver/issues\");\n\t\t}\n\t\treturn attachment;\n\t}\n\tset(ws, attachment) {\n\t\tthis.#cache.set(ws, attachment);\n\t\tWebSocket.prototype.serializeAttachment.call(ws, attachment);\n\t}\n};\nconst attachments = new AttachmentCache();\nconst connections = /* @__PURE__ */ new WeakSet();\nconst isWrapped = (ws) => {\n\treturn connections.has(ws);\n};\n/**\n* Wraps a WebSocket with Connection fields that rehydrate the\n* socket attachments lazily only when requested.\n*/\nconst createLazyConnection = (ws) => {\n\tif (isWrapped(ws)) return ws;\n\tlet initialState;\n\tif (\"state\" in ws) {\n\t\tinitialState = ws.state;\n\t\tdelete ws.state;\n\t}\n\tconst connection = Object.defineProperties(ws, {\n\t\tid: { get() {\n\t\t\treturn attachments.get(ws).__pk.id;\n\t\t} },\n\t\tserver: { get() {\n\t\t\treturn attachments.get(ws).__pk.server;\n\t\t} },\n\t\tsocket: { get() {\n\t\t\treturn ws;\n\t\t} },\n\t\tstate: { get() {\n\t\t\treturn ws.deserializeAttachment();\n\t\t} },\n\t\tsetState: { value: function setState(setState$1) {\n\t\t\tlet state;\n\t\t\tif (setState$1 instanceof Function) state = setState$1(this.state);\n\t\t\telse state = setState$1;\n\t\t\tws.serializeAttachment(state);\n\t\t\treturn state;\n\t\t} },\n\t\tdeserializeAttachment: { value: function deserializeAttachment() {\n\t\t\treturn attachments.get(ws).__user ?? null;\n\t\t} },\n\t\tserializeAttachment: { value: function serializeAttachment(attachment) {\n\t\t\tconst setting = {\n\t\t\t\t...attachments.get(ws),\n\t\t\t\t__user: attachment ?? null\n\t\t\t};\n\t\t\tattachments.set(ws, setting);\n\t\t} }\n\t});\n\tif (initialState) connection.setState(initialState);\n\tconnections.add(connection);\n\treturn connection;\n};\nvar HibernatingConnectionIterator = class {\n\tindex = 0;\n\tsockets;\n\tconstructor(state, tag) {\n\t\tthis.state = state;\n\t\tthis.tag = tag;\n\t}\n\t[Symbol.iterator]() {\n\t\treturn this;\n\t}\n\tnext() {\n\t\tconst sockets = this.sockets ?? (this.sockets = this.state.getWebSockets(this.tag));\n\t\tlet socket;\n\t\twhile (socket = sockets[this.index++]) if (socket.readyState === WebSocket.READY_STATE_OPEN) return {\n\t\t\tdone: false,\n\t\t\tvalue: createLazyConnection(socket)\n\t\t};\n\t\treturn {\n\t\t\tdone: true,\n\t\t\tvalue: void 0\n\t\t};\n\t}\n};\n/**\n* When not using hibernation, we track active connections manually.\n*/\nvar InMemoryConnectionManager = class {\n\t#connections = /* @__PURE__ */ new Map();\n\ttags = /* @__PURE__ */ new WeakMap();\n\tgetCount() {\n\t\treturn this.#connections.size;\n\t}\n\tgetConnection(id) {\n\t\treturn this.#connections.get(id);\n\t}\n\t*getConnections(tag) {\n\t\tif (!tag) {\n\t\t\tyield* this.#connections.values().filter((c) => c.readyState === WebSocket.READY_STATE_OPEN);\n\t\t\treturn;\n\t\t}\n\t\tfor (const connection of this.#connections.values()) if ((this.tags.get(connection) ?? []).includes(tag)) yield connection;\n\t}\n\taccept(connection, options) {\n\t\tconnection.accept();\n\t\tthis.#connections.set(connection.id, connection);\n\t\tthis.tags.set(connection, [connection.id, ...options.tags.filter((t) => t !== connection.id)]);\n\t\tconst removeConnection = () => {\n\t\t\tthis.#connections.delete(connection.id);\n\t\t\tconnection.removeEventListener(\"close\", removeConnection);\n\t\t\tconnection.removeEventListener(\"error\", removeConnection);\n\t\t};\n\t\tconnection.addEventListener(\"close\", removeConnection);\n\t\tconnection.addEventListener(\"error\", removeConnection);\n\t\treturn connection;\n\t}\n};\n/**\n* When opting into hibernation, the platform tracks connections for us.\n*/\nvar HibernatingConnectionManager = class {\n\tconstructor(controller) {\n\t\tthis.controller = controller;\n\t}\n\tgetCount() {\n\t\treturn Number(this.controller.getWebSockets().length);\n\t}\n\tgetConnection(id) {\n\t\tconst sockets = this.controller.getWebSockets(id);\n\t\tif (sockets.length === 0) return void 0;\n\t\tif (sockets.length === 1) return createLazyConnection(sockets[0]);\n\t\tthrow new Error(`More than one connection found for id ${id}. Did you mean to use getConnections(tag) instead?`);\n\t}\n\tgetConnections(tag) {\n\t\treturn new HibernatingConnectionIterator(this.controller, tag);\n\t}\n\taccept(connection, options) {\n\t\tconst tags = [connection.id, ...options.tags.filter((t) => t !== connection.id)];\n\t\tif (tags.length > 10) throw new Error(\"A connection can only have 10 tags, including the default id tag.\");\n\t\tfor (const tag of tags) {\n\t\t\tif (typeof tag !== \"string\") throw new Error(`A connection tag must be a string. Received: ${tag}`);\n\t\t\tif (tag === \"\") throw new Error(\"A connection tag must not be an empty string.\");\n\t\t\tif (tag.length > 256) throw new Error(\"A connection tag must not exceed 256 characters\");\n\t\t}\n\t\tthis.controller.acceptWebSocket(connection, tags);\n\t\tconnection.serializeAttachment({\n\t\t\t__pk: {\n\t\t\t\tid: connection.id,\n\t\t\t\tserver: options.server\n\t\t\t},\n\t\t\t__user: null\n\t\t});\n\t\treturn createLazyConnection(connection);\n\t}\n};\n\n//#endregion\n//#region src/index.ts\nconst serverMapCache = /* @__PURE__ */ new WeakMap();\n/**\n* For a given server namespace, create a server with a name.\n*/\nasync function getServerByName(serverNamespace, name, options) {\n\tif (options?.jurisdiction) serverNamespace = serverNamespace.jurisdiction(options.jurisdiction);\n\tconst id = serverNamespace.idFromName(name);\n\tconst stub = serverNamespace.get(id, options);\n\tconst req = new Request(\"http://dummy-example.cloudflare.com/cdn-cgi/partyserver/set-name/\");\n\treq.headers.set(\"x-partykit-room\", name);\n\tif (options?.props) req.headers.set(\"x-partykit-props\", JSON.stringify(options?.props));\n\tawait stub.fetch(req).then((res) => res.text()).catch((e) => {\n\t\tconsole.error(\"Could not set server name:\", e);\n\t});\n\treturn stub;\n}\nfunction camelCaseToKebabCase(str) {\n\tif (str === str.toUpperCase() && str !== str.toLowerCase()) return str.toLowerCase().replace(/_/g, \"-\");\n\tlet kebabified = str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n\tkebabified = kebabified.startsWith(\"-\") ? kebabified.slice(1) : kebabified;\n\treturn kebabified.replace(/_/g, \"-\").replace(/-$/, \"\");\n}\n/**\n* A utility function for PartyKit style routing.\n*/\nasync function routePartykitRequest(req, env, options) {\n\tif (!serverMapCache.has(env)) serverMapCache.set(env, Object.entries(env).reduce((acc, [k, v]) => {\n\t\tif (v && typeof v === \"object\" && \"idFromName\" in v && typeof v.idFromName === \"function\") {\n\t\t\tObject.assign(acc, { [camelCaseToKebabCase(k)]: v });\n\t\t\treturn acc;\n\t\t}\n\t\treturn acc;\n\t}, {}));\n\tconst map = serverMapCache.get(env);\n\tconst prefixParts = (options?.prefix || \"parties\").split(\"/\");\n\tconst parts = new URL(req.url).pathname.split(\"/\").filter(Boolean);\n\tif (!prefixParts.every((part, index) => parts[index] === part) || parts.length < prefixParts.length + 2) return null;\n\tconst namespace = parts[prefixParts.length];\n\tconst name = parts[prefixParts.length + 1];\n\tif (name && namespace) {\n\t\tif (!map[namespace]) if (namespace === \"main\") {\n\t\t\tconsole.warn(\"You appear to be migrating a PartyKit project to PartyServer.\");\n\t\t\tconsole.warn(`PartyServer doesn't have a \"main\" party by default. Try adding this to your PartySocket client:\\n \nparty: \"${camelCaseToKebabCase(Object.keys(map)[0])}\"`);\n\t\t} else console.error(`The url ${req.url} does not match any server namespace. \nDid you forget to add a durable object binding to the class in your wrangler.toml?`);\n\t\tlet doNamespace = map[namespace];\n\t\tif (options?.jurisdiction) doNamespace = doNamespace.jurisdiction(options.jurisdiction);\n\t\tconst id = doNamespace.idFromName(name);\n\t\tconst stub = doNamespace.get(id, options);\n\t\treq = new Request(req);\n\t\treq.headers.set(\"x-partykit-room\", name);\n\t\treq.headers.set(\"x-partykit-namespace\", namespace);\n\t\tif (options?.jurisdiction) req.headers.set(\"x-partykit-jurisdiction\", options.jurisdiction);\n\t\tif (options?.props) req.headers.set(\"x-partykit-props\", JSON.stringify(options?.props));\n\t\tif (req.headers.get(\"Upgrade\")?.toLowerCase() === \"websocket\") {\n\t\t\tif (options?.onBeforeConnect) {\n\t\t\t\tconst reqOrRes = await options.onBeforeConnect(req, {\n\t\t\t\t\tparty: namespace,\n\t\t\t\t\tname\n\t\t\t\t});\n\t\t\t\tif (reqOrRes instanceof Request) req = reqOrRes;\n\t\t\t\telse if (reqOrRes instanceof Response) return reqOrRes;\n\t\t\t}\n\t\t} else if (options?.onBeforeRequest) {\n\t\t\tconst reqOrRes = await options.onBeforeRequest(req, {\n\t\t\t\tparty: namespace,\n\t\t\t\tname\n\t\t\t});\n\t\t\tif (reqOrRes instanceof Request) req = reqOrRes;\n\t\t\telse if (reqOrRes instanceof Response) return reqOrRes;\n\t\t}\n\t\treturn stub.fetch(req);\n\t} else return null;\n}\nvar Server = class extends DurableObject {\n\tstatic options = { hibernate: false };\n\t#status = \"zero\";\n\t#ParentClass = Object.getPrototypeOf(this).constructor;\n\t#connectionManager = this.#ParentClass.options.hibernate ? new HibernatingConnectionManager(this.ctx) : new InMemoryConnectionManager();\n\t/**\n\t* Execute SQL queries against the Server's database\n\t* @template T Type of the returned rows\n\t* @param strings SQL query template strings\n\t* @param values Values to be inserted into the query\n\t* @returns Array of query results\n\t*/\n\tsql(strings, ...values) {\n\t\tlet query = \"\";\n\t\ttry {\n\t\t\tquery = strings.reduce((acc, str, i) => acc + str + (i < values.length ? \"?\" : \"\"), \"\");\n\t\t\treturn [...this.ctx.storage.sql.exec(query, ...values)];\n\t\t} catch (e) {\n\t\t\tconsole.error(`failed to execute sql query: ${query}`, e);\n\t\t\tthrow this.onException(e);\n\t\t}\n\t}\n\tconstructor(ctx, env) {\n\t\tsuper(ctx, env);\n\t}\n\t/**\n\t* Handle incoming requests to the server.\n\t*/\n\tasync fetch(request) {\n\t\tconst props = request.headers.get(\"x-partykit-props\");\n\t\tif (props) try {\n\t\t\tthis.#_props = JSON.parse(props);\n\t\t} catch {\n\t\t\tconsole.error(\"Internal error parsing context props.\");\n\t\t}\n\t\tif (!this.#_name) {\n\t\t\tconst room = request.headers.get(\"x-partykit-room\");\n\t\t\tif (!room) throw new Error(`Missing namespace or room headers when connecting to ${this.#ParentClass.name}.\nDid you try connecting directly to this Durable Object? Try using getServerByName(namespace, id) instead.`);\n\t\t\tawait this.setName(room);\n\t\t}\n\t\ttry {\n\t\t\tconst url = new URL(request.url);\n\t\t\tif (url.pathname === \"/cdn-cgi/partyserver/set-name/\") return Response.json({ ok: true });\n\t\t\tif (url.pathname === \"/cdn-cgi/partyserver/keep-alive/\") {\n\t\t\t\tif (request.headers.get(\"Upgrade\")?.toLowerCase() === \"websocket\") {\n\t\t\t\t\tconst { 0: client, 1: server } = new WebSocketPair();\n\t\t\t\t\tthis.ctx.acceptWebSocket(server, [\"partyserver-keepalive\"]);\n\t\t\t\t\treturn new Response(null, {\n\t\t\t\t\t\tstatus: 101,\n\t\t\t\t\t\twebSocket: client\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn new Response(\"WebSocket required\", { status: 426 });\n\t\t\t}\n\t\t\tif (request.headers.get(\"Upgrade\")?.toLowerCase() !== \"websocket\") return await this.onRequest(request);\n\t\t\telse {\n\t\t\t\tconst { 0: clientWebSocket, 1: serverWebSocket } = new WebSocketPair();\n\t\t\t\tlet connectionId = url.searchParams.get(\"_pk\");\n\t\t\t\tif (!connectionId) connectionId = nanoid();\n\t\t\t\tlet connection = Object.assign(serverWebSocket, {\n\t\t\t\t\tid: connectionId,\n\t\t\t\t\tserver: this.name,\n\t\t\t\t\tstate: null,\n\t\t\t\t\tsetState(setState) {\n\t\t\t\t\t\tlet state;\n\t\t\t\t\t\tif (setState instanceof Function) state = setState(this.state);\n\t\t\t\t\t\telse state = setState;\n\t\t\t\t\t\tthis.state = state;\n\t\t\t\t\t\treturn this.state;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tconst ctx = { request };\n\t\t\t\tconst tags = await this.getConnectionTags(connection, ctx);\n\t\t\t\tconnection = this.#connectionManager.accept(connection, {\n\t\t\t\t\ttags,\n\t\t\t\t\tserver: this.name\n\t\t\t\t});\n\t\t\t\tif (!this.#ParentClass.options.hibernate) this.#attachSocketEventHandlers(connection);\n\t\t\t\tawait this.onConnect(connection, ctx);\n\t\t\t\treturn new Response(null, {\n\t\t\t\t\tstatus: 101,\n\t\t\t\t\twebSocket: clientWebSocket\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error(`Error in ${this.#ParentClass.name}:${this.name} fetch:`, err);\n\t\t\tif (!(err instanceof Error)) throw err;\n\t\t\tif (request.headers.get(\"Upgrade\") === \"websocket\") {\n\t\t\t\tconst pair = new WebSocketPair();\n\t\t\t\tpair[1].accept();\n\t\t\t\tpair[1].send(JSON.stringify({ error: err.stack }));\n\t\t\t\tpair[1].close(1011, \"Uncaught exception during session setup\");\n\t\t\t\treturn new Response(null, {\n\t\t\t\t\tstatus: 101,\n\t\t\t\t\twebSocket: pair[0]\n\t\t\t\t});\n\t\t\t} else return new Response(err.stack, { status: 500 });\n\t\t}\n\t}\n\tasync webSocketMessage(ws, message) {\n\t\tif (this.ctx.getTags(ws).includes(\"partyserver-keepalive\")) {\n\t\t\tif (message === \"ping\") ws.send(\"pong\");\n\t\t\treturn;\n\t\t}\n\t\tconst connection = createLazyConnection(ws);\n\t\tawait this.setName(connection.server);\n\t\tif (this.#status !== \"started\") await this.#initialize();\n\t\treturn this.onMessage(connection, message);\n\t}\n\tasync webSocketClose(ws, code, reason, wasClean) {\n\t\tif (this.ctx.getTags(ws).includes(\"partyserver-keepalive\")) return;\n\t\tconst connection = createLazyConnection(ws);\n\t\tawait this.setName(connection.server);\n\t\tif (this.#status !== \"started\") await this.#initialize();\n\t\treturn this.onClose(connection, code, reason, wasClean);\n\t}\n\tasync webSocketError(ws, error) {\n\t\tif (this.ctx.getTags(ws).includes(\"partyserver-keepalive\")) return;\n\t\tconst connection = createLazyConnection(ws);\n\t\tawait this.setName(connection.server);\n\t\tif (this.#status !== \"started\") await this.#initialize();\n\t\treturn this.onError(connection, error);\n\t}\n\tasync #initialize() {\n\t\tawait this.ctx.blockConcurrencyWhile(async () => {\n\t\t\tthis.#status = \"starting\";\n\t\t\tawait this.onStart(this.#_props);\n\t\t\tthis.#status = \"started\";\n\t\t});\n\t}\n\t#attachSocketEventHandlers(connection) {\n\t\tconst handleMessageFromClient = (event) => {\n\t\t\tthis.onMessage(connection, event.data)?.catch((e) => {\n\t\t\t\tconsole.error(\"onMessage error:\", e);\n\t\t\t});\n\t\t};\n\t\tconst handleCloseFromClient = (event) => {\n\t\t\tconnection.removeEventListener(\"message\", handleMessageFromClient);\n\t\t\tconnection.removeEventListener(\"close\", handleCloseFromClient);\n\t\t\tthis.onClose(connection, event.code, event.reason, event.wasClean)?.catch((e) => {\n\t\t\t\tconsole.error(\"onClose error:\", e);\n\t\t\t});\n\t\t};\n\t\tconst handleErrorFromClient = (e) => {\n\t\t\tconnection.removeEventListener(\"message\", handleMessageFromClient);\n\t\t\tconnection.removeEventListener(\"error\", handleErrorFromClient);\n\t\t\tthis.onError(connection, e.error)?.catch((e$1) => {\n\t\t\t\tconsole.error(\"onError error:\", e$1);\n\t\t\t});\n\t\t};\n\t\tconnection.addEventListener(\"close\", handleCloseFromClient);\n\t\tconnection.addEventListener(\"error\", handleErrorFromClient);\n\t\tconnection.addEventListener(\"message\", handleMessageFromClient);\n\t}\n\t#_name;\n\t#_longErrorAboutNameThrown = false;\n\t/**\n\t* The name for this server. Write-once-only.\n\t*/\n\tget name() {\n\t\tif (!this.#_name) if (!this.#_longErrorAboutNameThrown) {\n\t\t\tthis.#_longErrorAboutNameThrown = true;\n\t\t\tthrow new Error(`Attempting to read .name on ${this.#ParentClass.name} before it was set. The name can be set by explicitly calling .setName(name) on the stub, or by using routePartyKitRequest(). This is a known issue and will be fixed soon. Follow https://github.com/cloudflare/workerd/issues/2240 for more updates.`);\n\t\t} else throw new Error(`Attempting to read .name on ${this.#ParentClass.name} before it was set.`);\n\t\treturn this.#_name;\n\t}\n\tasync setName(name) {\n\t\tif (!name) throw new Error(\"A name is required.\");\n\t\tif (this.#_name && this.#_name !== name) throw new Error(\"This server already has a name.\");\n\t\tthis.#_name = name;\n\t\tif (this.#status !== \"started\") await this.ctx.blockConcurrencyWhile(async () => {\n\t\t\tawait this.#initialize();\n\t\t});\n\t}\n\t#sendMessageToConnection(connection, message) {\n\t\ttry {\n\t\t\tconnection.send(message);\n\t\t} catch (_e) {\n\t\t\tconnection.close(1011, \"Unexpected error\");\n\t\t}\n\t}\n\t/** Send a message to all connected clients, except connection ids listed in `without` */\n\tbroadcast(msg, without) {\n\t\tfor (const connection of this.#connectionManager.getConnections()) if (!without || !without.includes(connection.id)) this.#sendMessageToConnection(connection, msg);\n\t}\n\t/** Get a connection by connection id */\n\tgetConnection(id) {\n\t\treturn this.#connectionManager.getConnection(id);\n\t}\n\t/**\n\t* Get all connections. Optionally, you can provide a tag to filter returned connections.\n\t* Use `Server#getConnectionTags` to tag the connection on connect.\n\t*/\n\tgetConnections(tag) {\n\t\treturn this.#connectionManager.getConnections(tag);\n\t}\n\t/**\n\t* You can tag a connection to filter them in Server#getConnections.\n\t* Each connection supports up to 9 tags, each tag max length is 256 characters.\n\t*/\n\tgetConnectionTags(connection, context) {\n\t\treturn [];\n\t}\n\t/**\n\t* Execute a long-running async function while keeping the Durable Object alive.\n\t*\n\t* Durable Objects normally terminate 70-140s after the last network request.\n\t* This method keeps the DO alive by establishing a WebSocket connection to itself\n\t* and sending periodic ping messages.\n\t*\n\t* @experimental This API is experimental and may change in future versions.\n\t*\n\t* @param fn - The async function to execute\n\t* @param timeoutMs - Maximum time to keep the DO alive (default: 30 minutes)\n\t* @returns The result of the async function\n\t*\n\t* @remarks\n\t* Requires the `enable_ctx_exports` compatibility flag in wrangler.jsonc:\n\t* ```json\n\t* {\n\t* \"compatibility_flags\": [\"enable_ctx_exports\"]\n\t* }\n\t* ```\n\t*\n\t* @example\n\t* ```typescript\n\t* const result = await this.experimental_waitUntil(async () => {\n\t* // Long-running operation\n\t* await processLargeDataset();\n\t* return { success: true };\n\t* }, 60 * 60 * 1000); // 1 hour timeout\n\t* ```\n\t*/\n\tasync experimental_waitUntil(fn, timeoutMs = 1800 * 1e3) {\n\t\tconst exports = this.ctx.exports;\n\t\tif (!exports) throw new Error(\"waitUntil requires the 'enable_ctx_exports' compatibility flag. Add it to your wrangler.jsonc: { \\\"compatibility_flags\\\": [\\\"enable_ctx_exports\\\"] }\");\n\t\tconst namespace = exports[this.#ParentClass.name];\n\t\tif (!namespace) throw new Error(`Could not find namespace for ${this.#ParentClass.name} in ctx.exports. Make sure the class name matches your Durable Object binding.`);\n\t\tconst ws = (await namespace.get(this.ctx.id).fetch(\"http://dummy-example.cloudflare.com/cdn-cgi/partyserver/keep-alive/\", { headers: {\n\t\t\tUpgrade: \"websocket\",\n\t\t\t\"x-partykit-room\": this.name\n\t\t} })).webSocket;\n\t\tif (!ws) throw new Error(\"Failed to establish keep-alive WebSocket connection\");\n\t\tws.accept();\n\t\tconst pingInterval = setInterval(() => {\n\t\t\ttry {\n\t\t\t\tws.send(\"ping\");\n\t\t\t} catch {}\n\t\t}, 1e4);\n\t\tlet timeoutId;\n\t\tconst timeoutPromise = new Promise((_, reject) => {\n\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\treject(/* @__PURE__ */ new Error(`experimental_waitUntil timed out after ${timeoutMs}ms`));\n\t\t\t}, timeoutMs);\n\t\t});\n\t\ttry {\n\t\t\treturn await Promise.race([fn(), timeoutPromise]);\n\t\t} finally {\n\t\t\tclearTimeout(timeoutId);\n\t\t\tclearInterval(pingInterval);\n\t\t\ttry {\n\t\t\t\tws.close(1e3, \"Complete\");\n\t\t\t} catch {}\n\t\t}\n\t}\n\t#_props;\n\t/**\n\t* Called when the server is started for the first time.\n\t*/\n\tonStart(props) {}\n\t/**\n\t* Called when a new connection is made to the server.\n\t*/\n\tonConnect(connection, ctx) {\n\t\tconsole.log(`Connection ${connection.id} connected to ${this.#ParentClass.name}:${this.name}`);\n\t}\n\t/**\n\t* Called when a message is received from a connection.\n\t*/\n\tonMessage(connection, message) {\n\t\tconsole.log(`Received message on connection ${this.#ParentClass.name}:${connection.id}`);\n\t\tconsole.info(`Implement onMessage on ${this.#ParentClass.name} to handle this message.`);\n\t}\n\t/**\n\t* Called when a connection is closed.\n\t*/\n\tonClose(connection, code, reason, wasClean) {}\n\t/**\n\t* Called when an error occurs on a connection.\n\t*/\n\tonError(connection, error) {\n\t\tconsole.error(`Error on connection ${connection.id} in ${this.#ParentClass.name}:${this.name}:`, error);\n\t\tconsole.info(`Implement onError on ${this.#ParentClass.name} to handle this error.`);\n\t}\n\t/**\n\t* Called when a request is made to the server.\n\t*/\n\tonRequest(request) {\n\t\tconsole.warn(`onRequest hasn't been implemented on ${this.#ParentClass.name}:${this.name} responding to ${request.url}`);\n\t\treturn new Response(\"Not implemented\", { status: 404 });\n\t}\n\t/**\n\t* Called when an exception occurs.\n\t* @param error - The error that occurred.\n\t*/\n\tonException(error) {\n\t\tconsole.error(`Exception in ${this.#ParentClass.name}:${this.name}:`, error);\n\t\tconsole.info(`Implement onException on ${this.#ParentClass.name} to handle this error.`);\n\t}\n\tonAlarm() {\n\t\tconsole.log(`Implement onAlarm on ${this.#ParentClass.name} to handle alarms.`);\n\t}\n\tasync alarm() {\n\t\tif (this.#status !== \"started\") await this.#initialize();\n\t\tawait this.onAlarm();\n\t}\n};\n\n//#endregion\nexport { Server, getServerByName, routePartykitRequest };\n//# sourceMappingURL=index.js.map","import * as decoding from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport debounce from \"lodash.debounce\";\nimport type { Connection, ConnectionContext, WSMessage } from \"partyserver\";\nimport { Server } from \"partyserver\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport {\n applyUpdate,\n Doc as YDoc,\n encodeStateAsUpdate,\n encodeStateVector,\n UndoManager,\n XmlText,\n XmlElement,\n XmlFragment\n} from \"yjs\";\n\nimport { handleChunked } from \"../shared/chunking\";\n\nconst snapshotOrigin = Symbol(\"snapshot-origin\");\ntype YjsRootType =\n | \"Text\"\n | \"Map\"\n | \"Array\"\n | \"XmlText\"\n | \"XmlElement\"\n | \"XmlFragment\";\n\nconst wsReadyStateConnecting = 0;\nconst wsReadyStateOpen = 1;\n// biome-ignore lint/correctness/noUnusedVariables: it's fine\nconst wsReadyStateClosing = 2;\n// biome-ignore lint/correctness/noUnusedVariables: it's fine\nconst wsReadyStateClosed = 3;\n\nconst messageSync = 0;\nconst messageAwareness = 1;\n// biome-ignore lint/correctness/noUnusedVariables: it's fine\nconst messageAuth = 2;\n\nfunction updateHandler(update: Uint8Array, _origin: unknown, doc: WSSharedDoc) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeUpdate(encoder, update);\n const message = encoding.toUint8Array(encoder);\n doc.conns.forEach((_, conn) => {\n send(doc, conn, message);\n });\n}\n\nclass WSSharedDoc extends YDoc {\n conns: Map<Connection, Set<number>>;\n awareness: awarenessProtocol.Awareness;\n\n constructor() {\n super({ gc: true });\n\n /**\n * Maps from conn to set of controlled user ids. Delete all user ids from awareness when this conn is closed\n */\n this.conns = new Map();\n\n this.awareness = new awarenessProtocol.Awareness(this);\n this.awareness.setLocalState(null);\n\n const awarenessChangeHandler = (\n {\n added,\n updated,\n removed\n }: {\n added: Array<number>;\n updated: Array<number>;\n removed: Array<number>;\n },\n conn: Connection | null // Origin is the connection that made the change\n ) => {\n const changedClients = added.concat(updated, removed);\n if (conn !== null) {\n const connControlledIDs =\n /** @type {Set<number>} */ this.conns.get(conn);\n if (connControlledIDs !== undefined) {\n added.forEach((clientID) => {\n connControlledIDs.add(clientID);\n });\n removed.forEach((clientID) => {\n connControlledIDs.delete(clientID);\n });\n }\n }\n // broadcast awareness update\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(this.awareness, changedClients)\n );\n const buff = encoding.toUint8Array(encoder);\n this.conns.forEach((_, c) => {\n send(this, c, buff);\n });\n };\n this.awareness.on(\"update\", awarenessChangeHandler);\n // @ts-expect-error - TODO: fix this\n this.on(\"update\", updateHandler);\n }\n}\n\nconst CALLBACK_DEFAULTS = {\n debounceWait: 2000,\n debounceMaxWait: 10000,\n timeout: 5000\n};\n\nfunction readSyncMessage(\n decoder: decoding.Decoder,\n encoder: encoding.Encoder,\n doc: YDoc,\n transactionOrigin: Connection,\n readOnly = false\n) {\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case syncProtocol.messageYjsSyncStep1:\n syncProtocol.readSyncStep1(decoder, encoder, doc);\n break;\n case syncProtocol.messageYjsSyncStep2:\n if (!readOnly)\n syncProtocol.readSyncStep2(decoder, doc, transactionOrigin);\n break;\n case syncProtocol.messageYjsUpdate:\n if (!readOnly) syncProtocol.readUpdate(decoder, doc, transactionOrigin);\n break;\n default:\n throw new Error(\"Unknown message type\");\n }\n return messageType;\n}\n\nfunction closeConn(doc: WSSharedDoc, conn: Connection): void {\n if (doc.conns.has(conn)) {\n const controlledIds: Set<number> = doc.conns.get(conn)!;\n doc.conns.delete(conn);\n awarenessProtocol.removeAwarenessStates(\n doc.awareness,\n Array.from(controlledIds),\n null\n );\n }\n try {\n conn.close();\n } catch (e) {\n console.warn(\"failed to close connection\", e);\n }\n}\n\nfunction send(doc: WSSharedDoc, conn: Connection, m: Uint8Array) {\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n closeConn(doc, conn);\n }\n try {\n conn.send(m);\n } catch (_e) {\n closeConn(doc, conn);\n }\n}\n\nexport interface CallbackOptions {\n debounceWait?: number;\n debounceMaxWait?: number;\n timeout?: number;\n}\n\nexport class YServer<Env = unknown> extends Server<Env> {\n static callbackOptions: CallbackOptions = {};\n\n #ParentClass: typeof YServer = Object.getPrototypeOf(this).constructor;\n readonly document: WSSharedDoc = new WSSharedDoc();\n\n async onLoad(): Promise<void> {\n // to be implemented by the user\n return;\n }\n\n async onSave(): Promise<void> {\n // to be implemented by the user\n }\n\n /**\n * Replaces the document with a different state using Yjs UndoManager key remapping.\n *\n * @param snapshotUpdate - The snapshot update to replace the document with.\n * @param getMetadata (optional) - A function that returns the type of the root for a given key.\n */\n unstable_replaceDocument(\n snapshotUpdate: Uint8Array,\n getMetadata: (key: string) => YjsRootType = () => \"Map\"\n ): void {\n try {\n const doc = this.document;\n const snapshotDoc = new YDoc();\n applyUpdate(snapshotDoc, snapshotUpdate, snapshotOrigin);\n\n const currentStateVector = encodeStateVector(doc);\n const snapshotStateVector = encodeStateVector(snapshotDoc);\n\n const changesSinceSnapshotUpdate = encodeStateAsUpdate(\n doc,\n snapshotStateVector\n );\n\n const undoManager = new UndoManager(\n [...snapshotDoc.share.keys()].map((key) => {\n const type = getMetadata(key);\n if (type === \"Text\") {\n return snapshotDoc.getText(key);\n } else if (type === \"Map\") {\n return snapshotDoc.getMap(key);\n } else if (type === \"Array\") {\n return snapshotDoc.getArray(key);\n } else if (type === \"XmlText\") {\n return snapshotDoc.get(key, XmlText);\n } else if (type === \"XmlElement\") {\n return snapshotDoc.get(key, XmlElement);\n } else if (type === \"XmlFragment\") {\n return snapshotDoc.get(key, XmlFragment);\n }\n throw new Error(`Unknown root type: ${type} for key: ${key}`);\n }),\n {\n trackedOrigins: new Set([snapshotOrigin])\n }\n );\n\n applyUpdate(snapshotDoc, changesSinceSnapshotUpdate, snapshotOrigin);\n undoManager.undo();\n\n const documentChangesSinceSnapshotUpdate = encodeStateAsUpdate(\n snapshotDoc,\n currentStateVector\n );\n\n applyUpdate(this.document, documentChangesSinceSnapshotUpdate);\n } catch (error) {\n throw new Error(\n `Failed to replace document: ${error instanceof Error ? error.message : \"Unknown error\"}`\n );\n }\n }\n\n async onStart(): Promise<void> {\n const src = await this.onLoad();\n if (src != null) {\n const state = encodeStateAsUpdate(src);\n applyUpdate(this.document, state);\n }\n\n this.document.on(\n \"update\",\n debounce(\n (_update: Uint8Array, _origin: Connection, _doc: YDoc) => {\n try {\n this.onSave().catch((err) => {\n console.error(\"failed to persist:\", err);\n });\n } catch (err) {\n console.error(\"failed to persist:\", err);\n }\n },\n this.#ParentClass.callbackOptions.debounceWait ||\n CALLBACK_DEFAULTS.debounceWait,\n {\n maxWait:\n this.#ParentClass.callbackOptions.debounceMaxWait ||\n CALLBACK_DEFAULTS.debounceMaxWait\n }\n )\n );\n }\n\n // biome-ignore lint/correctness/noUnusedFunctionParameters: so autocomplete works\n isReadOnly(connection: Connection): boolean {\n // to be implemented by the user\n return false;\n }\n\n /**\n * Handle custom string messages from the client.\n * Override this method to implement custom message handling.\n * @param connection - The connection that sent the message\n * @param message - The custom message string (without the __YPS: prefix)\n */\n // biome-ignore lint/correctness/noUnusedFunctionParameters: so autocomplete works\n onCustomMessage(connection: Connection, message: string): void {\n // to be implemented by the user\n console.warn(\n `Received custom message but onCustomMessage is not implemented in ${this.#ParentClass.name}:`,\n message\n );\n }\n\n /**\n * Send a custom string message to a specific connection.\n * @param connection - The connection to send the message to\n * @param message - The custom message string to send\n */\n sendCustomMessage(connection: Connection, message: string): void {\n if (\n connection.readyState !== undefined &&\n connection.readyState !== wsReadyStateConnecting &&\n connection.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n connection.send(`__YPS:${message}`);\n } catch (e) {\n console.warn(\"Failed to send custom message\", e);\n }\n }\n\n /**\n * Broadcast a custom string message to all connected clients.\n * @param message - The custom message string to broadcast\n * @param excludeConnection - Optional connection to exclude from the broadcast\n */\n broadcastCustomMessage(\n message: string,\n excludeConnection?: Connection\n ): void {\n const formattedMessage = `__YPS:${message}`;\n this.document.conns.forEach((_, conn) => {\n if (excludeConnection && conn === excludeConnection) {\n return;\n }\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n conn.send(formattedMessage);\n } catch (e) {\n console.warn(\"Failed to broadcast custom message\", e);\n }\n });\n }\n\n handleMessage(connection: Connection, message: WSMessage) {\n if (typeof message === \"string\") {\n // Handle custom messages with __YPS: prefix\n if (message.startsWith(\"__YPS:\")) {\n const customMessage = message.slice(6); // Remove __YPS: prefix\n this.onCustomMessage(connection, customMessage);\n return;\n }\n console.warn(\n `Received non-prefixed string message. Custom messages should be sent using sendMessage() on the provider.`\n );\n return;\n }\n try {\n const encoder = encoding.createEncoder();\n // TODO: this type seems odd\n const decoder = decoding.createDecoder(message as unknown as Uint8Array);\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case messageSync:\n encoding.writeVarUint(encoder, messageSync);\n readSyncMessage(\n decoder,\n encoder,\n this.document,\n connection,\n this.isReadOnly(connection)\n );\n\n // If the `encoder` only contains the type of reply message and no\n // message, there is no need to send the message. When `encoder` only\n // contains the type of reply, its length is 1.\n if (encoding.length(encoder) > 1) {\n send(this.document, connection, encoding.toUint8Array(encoder));\n }\n break;\n case messageAwareness: {\n awarenessProtocol.applyAwarenessUpdate(\n this.document.awareness,\n decoding.readVarUint8Array(decoder),\n connection\n );\n break;\n }\n }\n } catch (err) {\n console.error(err);\n // @ts-expect-error - TODO: fix this\n this.document.emit(\"error\", [err]);\n }\n }\n\n onMessage = handleChunked((conn, message) =>\n this.handleMessage(conn, message)\n );\n\n onClose(\n connection: Connection<unknown>,\n _code: number,\n _reason: string,\n _wasClean: boolean\n ): void | Promise<void> {\n closeConn(this.document, connection);\n }\n\n // TODO: explore why onError gets triggered when a connection closes\n\n onConnect(\n conn: Connection<unknown>,\n _ctx: ConnectionContext\n ): void | Promise<void> {\n // conn.binaryType = \"arraybuffer\"; // from y-websocket, breaks in our runtime\n\n this.document.conns.set(conn, new Set());\n\n // send sync step 1\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, this.document);\n send(this.document, conn, encoding.toUint8Array(encoder));\n const awarenessStates = this.document.awareness.getStates();\n if (awarenessStates.size > 0) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.document.awareness,\n Array.from(awarenessStates.keys())\n )\n );\n send(this.document, conn, encoding.toUint8Array(encoder));\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["#cache","#connections","#ParentClass","#_props","#_name","#connectionManager","#attachSocketEventHandlers","#status","#initialize","#_longErrorAboutNameThrown","#sendMessageToConnection","YDoc","controlledIds: Set<number>","#ParentClass","encoder"],"sources":["../../../partyserver/dist/index.js","../../src/server/index.ts"],"sourcesContent":["import { DurableObject } from \"cloudflare:workers\";\nimport { nanoid } from \"nanoid\";\n\n//#region src/connection.ts\nif (!(\"OPEN\" in WebSocket)) {\n\tconst WebSocketStatus = {\n\t\tCONNECTING: WebSocket.READY_STATE_CONNECTING,\n\t\tOPEN: WebSocket.READY_STATE_OPEN,\n\t\tCLOSING: WebSocket.READY_STATE_CLOSING,\n\t\tCLOSED: WebSocket.READY_STATE_CLOSED\n\t};\n\tObject.assign(WebSocket, WebSocketStatus);\n\tObject.assign(WebSocket.prototype, WebSocketStatus);\n}\n/**\n* Cache websocket attachments to avoid having to rehydrate them on every property access.\n*/\nvar AttachmentCache = class {\n\t#cache = /* @__PURE__ */ new WeakMap();\n\tget(ws) {\n\t\tlet attachment = this.#cache.get(ws);\n\t\tif (!attachment) {\n\t\t\tattachment = WebSocket.prototype.deserializeAttachment.call(ws);\n\t\t\tif (attachment !== void 0) this.#cache.set(ws, attachment);\n\t\t\telse throw new Error(\"Missing websocket attachment. This is most likely an issue in PartyServer, please open an issue at https://github.com/cloudflare/partykit/issues\");\n\t\t}\n\t\treturn attachment;\n\t}\n\tset(ws, attachment) {\n\t\tthis.#cache.set(ws, attachment);\n\t\tWebSocket.prototype.serializeAttachment.call(ws, attachment);\n\t}\n};\nconst attachments = new AttachmentCache();\nconst connections = /* @__PURE__ */ new WeakSet();\nconst isWrapped = (ws) => {\n\treturn connections.has(ws);\n};\n/**\n* Wraps a WebSocket with Connection fields that rehydrate the\n* socket attachments lazily only when requested.\n*/\nconst createLazyConnection = (ws) => {\n\tif (isWrapped(ws)) return ws;\n\tlet initialState;\n\tif (\"state\" in ws) {\n\t\tinitialState = ws.state;\n\t\tdelete ws.state;\n\t}\n\tconst connection = Object.defineProperties(ws, {\n\t\tid: { get() {\n\t\t\treturn attachments.get(ws).__pk.id;\n\t\t} },\n\t\tserver: { get() {\n\t\t\treturn attachments.get(ws).__pk.server;\n\t\t} },\n\t\tsocket: { get() {\n\t\t\treturn ws;\n\t\t} },\n\t\tstate: { get() {\n\t\t\treturn ws.deserializeAttachment();\n\t\t} },\n\t\tsetState: { value: function setState(setState$1) {\n\t\t\tlet state;\n\t\t\tif (setState$1 instanceof Function) state = setState$1(this.state);\n\t\t\telse state = setState$1;\n\t\t\tws.serializeAttachment(state);\n\t\t\treturn state;\n\t\t} },\n\t\tdeserializeAttachment: { value: function deserializeAttachment() {\n\t\t\treturn attachments.get(ws).__user ?? null;\n\t\t} },\n\t\tserializeAttachment: { value: function serializeAttachment(attachment) {\n\t\t\tconst setting = {\n\t\t\t\t...attachments.get(ws),\n\t\t\t\t__user: attachment ?? null\n\t\t\t};\n\t\t\tattachments.set(ws, setting);\n\t\t} }\n\t});\n\tif (initialState) connection.setState(initialState);\n\tconnections.add(connection);\n\treturn connection;\n};\nvar HibernatingConnectionIterator = class {\n\tindex = 0;\n\tsockets;\n\tconstructor(state, tag) {\n\t\tthis.state = state;\n\t\tthis.tag = tag;\n\t}\n\t[Symbol.iterator]() {\n\t\treturn this;\n\t}\n\tnext() {\n\t\tconst sockets = this.sockets ?? (this.sockets = this.state.getWebSockets(this.tag));\n\t\tlet socket;\n\t\twhile (socket = sockets[this.index++]) if (socket.readyState === WebSocket.READY_STATE_OPEN) return {\n\t\t\tdone: false,\n\t\t\tvalue: createLazyConnection(socket)\n\t\t};\n\t\treturn {\n\t\t\tdone: true,\n\t\t\tvalue: void 0\n\t\t};\n\t}\n};\n/**\n* When not using hibernation, we track active connections manually.\n*/\nvar InMemoryConnectionManager = class {\n\t#connections = /* @__PURE__ */ new Map();\n\ttags = /* @__PURE__ */ new WeakMap();\n\tgetCount() {\n\t\treturn this.#connections.size;\n\t}\n\tgetConnection(id) {\n\t\treturn this.#connections.get(id);\n\t}\n\t*getConnections(tag) {\n\t\tif (!tag) {\n\t\t\tyield* this.#connections.values().filter((c) => c.readyState === WebSocket.READY_STATE_OPEN);\n\t\t\treturn;\n\t\t}\n\t\tfor (const connection of this.#connections.values()) if ((this.tags.get(connection) ?? []).includes(tag)) yield connection;\n\t}\n\taccept(connection, options) {\n\t\tconnection.accept();\n\t\tthis.#connections.set(connection.id, connection);\n\t\tthis.tags.set(connection, [connection.id, ...options.tags.filter((t) => t !== connection.id)]);\n\t\tconst removeConnection = () => {\n\t\t\tthis.#connections.delete(connection.id);\n\t\t\tconnection.removeEventListener(\"close\", removeConnection);\n\t\t\tconnection.removeEventListener(\"error\", removeConnection);\n\t\t};\n\t\tconnection.addEventListener(\"close\", removeConnection);\n\t\tconnection.addEventListener(\"error\", removeConnection);\n\t\treturn connection;\n\t}\n};\n/**\n* When opting into hibernation, the platform tracks connections for us.\n*/\nvar HibernatingConnectionManager = class {\n\tconstructor(controller) {\n\t\tthis.controller = controller;\n\t}\n\tgetCount() {\n\t\treturn Number(this.controller.getWebSockets().length);\n\t}\n\tgetConnection(id) {\n\t\tconst sockets = this.controller.getWebSockets(id);\n\t\tif (sockets.length === 0) return void 0;\n\t\tif (sockets.length === 1) return createLazyConnection(sockets[0]);\n\t\tthrow new Error(`More than one connection found for id ${id}. Did you mean to use getConnections(tag) instead?`);\n\t}\n\tgetConnections(tag) {\n\t\treturn new HibernatingConnectionIterator(this.controller, tag);\n\t}\n\taccept(connection, options) {\n\t\tconst tags = [connection.id, ...options.tags.filter((t) => t !== connection.id)];\n\t\tif (tags.length > 10) throw new Error(\"A connection can only have 10 tags, including the default id tag.\");\n\t\tfor (const tag of tags) {\n\t\t\tif (typeof tag !== \"string\") throw new Error(`A connection tag must be a string. Received: ${tag}`);\n\t\t\tif (tag === \"\") throw new Error(\"A connection tag must not be an empty string.\");\n\t\t\tif (tag.length > 256) throw new Error(\"A connection tag must not exceed 256 characters\");\n\t\t}\n\t\tthis.controller.acceptWebSocket(connection, tags);\n\t\tconnection.serializeAttachment({\n\t\t\t__pk: {\n\t\t\t\tid: connection.id,\n\t\t\t\tserver: options.server\n\t\t\t},\n\t\t\t__user: null\n\t\t});\n\t\treturn createLazyConnection(connection);\n\t}\n};\n\n//#endregion\n//#region src/index.ts\nconst serverMapCache = /* @__PURE__ */ new WeakMap();\n/**\n* For a given server namespace, create a server with a name.\n*/\nasync function getServerByName(serverNamespace, name, options) {\n\tif (options?.jurisdiction) serverNamespace = serverNamespace.jurisdiction(options.jurisdiction);\n\tconst id = serverNamespace.idFromName(name);\n\tconst stub = serverNamespace.get(id, options);\n\tconst req = new Request(\"http://dummy-example.cloudflare.com/cdn-cgi/partyserver/set-name/\");\n\treq.headers.set(\"x-partykit-room\", name);\n\tif (options?.props) req.headers.set(\"x-partykit-props\", JSON.stringify(options?.props));\n\tawait stub.fetch(req).then((res) => res.text()).catch((e) => {\n\t\tconsole.error(\"Could not set server name:\", e);\n\t});\n\treturn stub;\n}\nfunction camelCaseToKebabCase(str) {\n\tif (str === str.toUpperCase() && str !== str.toLowerCase()) return str.toLowerCase().replace(/_/g, \"-\");\n\tlet kebabified = str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n\tkebabified = kebabified.startsWith(\"-\") ? kebabified.slice(1) : kebabified;\n\treturn kebabified.replace(/_/g, \"-\").replace(/-$/, \"\");\n}\n/**\n* A utility function for PartyKit style routing.\n*/\nasync function routePartykitRequest(req, env, options) {\n\tif (!serverMapCache.has(env)) serverMapCache.set(env, Object.entries(env).reduce((acc, [k, v]) => {\n\t\tif (v && typeof v === \"object\" && \"idFromName\" in v && typeof v.idFromName === \"function\") {\n\t\t\tObject.assign(acc, { [camelCaseToKebabCase(k)]: v });\n\t\t\treturn acc;\n\t\t}\n\t\treturn acc;\n\t}, {}));\n\tconst map = serverMapCache.get(env);\n\tconst prefixParts = (options?.prefix || \"parties\").split(\"/\");\n\tconst parts = new URL(req.url).pathname.split(\"/\").filter(Boolean);\n\tif (!prefixParts.every((part, index) => parts[index] === part) || parts.length < prefixParts.length + 2) return null;\n\tconst namespace = parts[prefixParts.length];\n\tconst name = parts[prefixParts.length + 1];\n\tif (name && namespace) {\n\t\tif (!map[namespace]) if (namespace === \"main\") {\n\t\t\tconsole.warn(\"You appear to be migrating a PartyKit project to PartyServer.\");\n\t\t\tconsole.warn(`PartyServer doesn't have a \"main\" party by default. Try adding this to your PartySocket client:\\n \nparty: \"${camelCaseToKebabCase(Object.keys(map)[0])}\"`);\n\t\t} else console.error(`The url ${req.url} does not match any server namespace. \nDid you forget to add a durable object binding to the class in your wrangler.toml?`);\n\t\tlet doNamespace = map[namespace];\n\t\tif (options?.jurisdiction) doNamespace = doNamespace.jurisdiction(options.jurisdiction);\n\t\tconst id = doNamespace.idFromName(name);\n\t\tconst stub = doNamespace.get(id, options);\n\t\treq = new Request(req);\n\t\treq.headers.set(\"x-partykit-room\", name);\n\t\treq.headers.set(\"x-partykit-namespace\", namespace);\n\t\tif (options?.jurisdiction) req.headers.set(\"x-partykit-jurisdiction\", options.jurisdiction);\n\t\tif (options?.props) req.headers.set(\"x-partykit-props\", JSON.stringify(options?.props));\n\t\tif (req.headers.get(\"Upgrade\")?.toLowerCase() === \"websocket\") {\n\t\t\tif (options?.onBeforeConnect) {\n\t\t\t\tconst reqOrRes = await options.onBeforeConnect(req, {\n\t\t\t\t\tparty: namespace,\n\t\t\t\t\tname\n\t\t\t\t});\n\t\t\t\tif (reqOrRes instanceof Request) req = reqOrRes;\n\t\t\t\telse if (reqOrRes instanceof Response) return reqOrRes;\n\t\t\t}\n\t\t} else if (options?.onBeforeRequest) {\n\t\t\tconst reqOrRes = await options.onBeforeRequest(req, {\n\t\t\t\tparty: namespace,\n\t\t\t\tname\n\t\t\t});\n\t\t\tif (reqOrRes instanceof Request) req = reqOrRes;\n\t\t\telse if (reqOrRes instanceof Response) return reqOrRes;\n\t\t}\n\t\treturn stub.fetch(req);\n\t} else return null;\n}\nvar Server = class extends DurableObject {\n\tstatic options = { hibernate: false };\n\t#status = \"zero\";\n\t#ParentClass = Object.getPrototypeOf(this).constructor;\n\t#connectionManager = this.#ParentClass.options.hibernate ? new HibernatingConnectionManager(this.ctx) : new InMemoryConnectionManager();\n\t/**\n\t* Execute SQL queries against the Server's database\n\t* @template T Type of the returned rows\n\t* @param strings SQL query template strings\n\t* @param values Values to be inserted into the query\n\t* @returns Array of query results\n\t*/\n\tsql(strings, ...values) {\n\t\tlet query = \"\";\n\t\ttry {\n\t\t\tquery = strings.reduce((acc, str, i) => acc + str + (i < values.length ? \"?\" : \"\"), \"\");\n\t\t\treturn [...this.ctx.storage.sql.exec(query, ...values)];\n\t\t} catch (e) {\n\t\t\tconsole.error(`failed to execute sql query: ${query}`, e);\n\t\t\tthrow this.onException(e);\n\t\t}\n\t}\n\tconstructor(ctx, env) {\n\t\tsuper(ctx, env);\n\t}\n\t/**\n\t* Handle incoming requests to the server.\n\t*/\n\tasync fetch(request) {\n\t\tconst props = request.headers.get(\"x-partykit-props\");\n\t\tif (props) try {\n\t\t\tthis.#_props = JSON.parse(props);\n\t\t} catch {\n\t\t\tconsole.error(\"Internal error parsing context props.\");\n\t\t}\n\t\tif (!this.#_name) {\n\t\t\tconst room = request.headers.get(\"x-partykit-room\");\n\t\t\tif (!room) throw new Error(`Missing namespace or room headers when connecting to ${this.#ParentClass.name}.\nDid you try connecting directly to this Durable Object? Try using getServerByName(namespace, id) instead.`);\n\t\t\tawait this.setName(room);\n\t\t}\n\t\ttry {\n\t\t\tconst url = new URL(request.url);\n\t\t\tif (url.pathname === \"/cdn-cgi/partyserver/set-name/\") return Response.json({ ok: true });\n\t\t\tif (url.pathname === \"/cdn-cgi/partyserver/keep-alive/\") {\n\t\t\t\tif (request.headers.get(\"Upgrade\")?.toLowerCase() === \"websocket\") {\n\t\t\t\t\tconst { 0: client, 1: server } = new WebSocketPair();\n\t\t\t\t\tthis.ctx.acceptWebSocket(server, [\"partyserver-keepalive\"]);\n\t\t\t\t\treturn new Response(null, {\n\t\t\t\t\t\tstatus: 101,\n\t\t\t\t\t\twebSocket: client\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn new Response(\"WebSocket required\", { status: 426 });\n\t\t\t}\n\t\t\tif (request.headers.get(\"Upgrade\")?.toLowerCase() !== \"websocket\") return await this.onRequest(request);\n\t\t\telse {\n\t\t\t\tconst { 0: clientWebSocket, 1: serverWebSocket } = new WebSocketPair();\n\t\t\t\tlet connectionId = url.searchParams.get(\"_pk\");\n\t\t\t\tif (!connectionId) connectionId = nanoid();\n\t\t\t\tlet connection = Object.assign(serverWebSocket, {\n\t\t\t\t\tid: connectionId,\n\t\t\t\t\tserver: this.name,\n\t\t\t\t\tstate: null,\n\t\t\t\t\tsetState(setState) {\n\t\t\t\t\t\tlet state;\n\t\t\t\t\t\tif (setState instanceof Function) state = setState(this.state);\n\t\t\t\t\t\telse state = setState;\n\t\t\t\t\t\tthis.state = state;\n\t\t\t\t\t\treturn this.state;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tconst ctx = { request };\n\t\t\t\tconst tags = await this.getConnectionTags(connection, ctx);\n\t\t\t\tconnection = this.#connectionManager.accept(connection, {\n\t\t\t\t\ttags,\n\t\t\t\t\tserver: this.name\n\t\t\t\t});\n\t\t\t\tif (!this.#ParentClass.options.hibernate) this.#attachSocketEventHandlers(connection);\n\t\t\t\tawait this.onConnect(connection, ctx);\n\t\t\t\treturn new Response(null, {\n\t\t\t\t\tstatus: 101,\n\t\t\t\t\twebSocket: clientWebSocket\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (err) {\n\t\t\tconsole.error(`Error in ${this.#ParentClass.name}:${this.name} fetch:`, err);\n\t\t\tif (!(err instanceof Error)) throw err;\n\t\t\tif (request.headers.get(\"Upgrade\") === \"websocket\") {\n\t\t\t\tconst pair = new WebSocketPair();\n\t\t\t\tpair[1].accept();\n\t\t\t\tpair[1].send(JSON.stringify({ error: err.stack }));\n\t\t\t\tpair[1].close(1011, \"Uncaught exception during session setup\");\n\t\t\t\treturn new Response(null, {\n\t\t\t\t\tstatus: 101,\n\t\t\t\t\twebSocket: pair[0]\n\t\t\t\t});\n\t\t\t} else return new Response(err.stack, { status: 500 });\n\t\t}\n\t}\n\tasync webSocketMessage(ws, message) {\n\t\tif (this.ctx.getTags(ws).includes(\"partyserver-keepalive\")) {\n\t\t\tif (message === \"ping\") ws.send(\"pong\");\n\t\t\treturn;\n\t\t}\n\t\tconst connection = createLazyConnection(ws);\n\t\tawait this.setName(connection.server);\n\t\tif (this.#status !== \"started\") await this.#initialize();\n\t\treturn this.onMessage(connection, message);\n\t}\n\tasync webSocketClose(ws, code, reason, wasClean) {\n\t\tif (this.ctx.getTags(ws).includes(\"partyserver-keepalive\")) return;\n\t\tconst connection = createLazyConnection(ws);\n\t\tawait this.setName(connection.server);\n\t\tif (this.#status !== \"started\") await this.#initialize();\n\t\treturn this.onClose(connection, code, reason, wasClean);\n\t}\n\tasync webSocketError(ws, error) {\n\t\tif (this.ctx.getTags(ws).includes(\"partyserver-keepalive\")) return;\n\t\tconst connection = createLazyConnection(ws);\n\t\tawait this.setName(connection.server);\n\t\tif (this.#status !== \"started\") await this.#initialize();\n\t\treturn this.onError(connection, error);\n\t}\n\tasync #initialize() {\n\t\tawait this.ctx.blockConcurrencyWhile(async () => {\n\t\t\tthis.#status = \"starting\";\n\t\t\tawait this.onStart(this.#_props);\n\t\t\tthis.#status = \"started\";\n\t\t});\n\t}\n\t#attachSocketEventHandlers(connection) {\n\t\tconst handleMessageFromClient = (event) => {\n\t\t\tthis.onMessage(connection, event.data)?.catch((e) => {\n\t\t\t\tconsole.error(\"onMessage error:\", e);\n\t\t\t});\n\t\t};\n\t\tconst handleCloseFromClient = (event) => {\n\t\t\tconnection.removeEventListener(\"message\", handleMessageFromClient);\n\t\t\tconnection.removeEventListener(\"close\", handleCloseFromClient);\n\t\t\tthis.onClose(connection, event.code, event.reason, event.wasClean)?.catch((e) => {\n\t\t\t\tconsole.error(\"onClose error:\", e);\n\t\t\t});\n\t\t};\n\t\tconst handleErrorFromClient = (e) => {\n\t\t\tconnection.removeEventListener(\"message\", handleMessageFromClient);\n\t\t\tconnection.removeEventListener(\"error\", handleErrorFromClient);\n\t\t\tthis.onError(connection, e.error)?.catch((e$1) => {\n\t\t\t\tconsole.error(\"onError error:\", e$1);\n\t\t\t});\n\t\t};\n\t\tconnection.addEventListener(\"close\", handleCloseFromClient);\n\t\tconnection.addEventListener(\"error\", handleErrorFromClient);\n\t\tconnection.addEventListener(\"message\", handleMessageFromClient);\n\t}\n\t#_name;\n\t#_longErrorAboutNameThrown = false;\n\t/**\n\t* The name for this server. Write-once-only.\n\t*/\n\tget name() {\n\t\tif (!this.#_name) if (!this.#_longErrorAboutNameThrown) {\n\t\t\tthis.#_longErrorAboutNameThrown = true;\n\t\t\tthrow new Error(`Attempting to read .name on ${this.#ParentClass.name} before it was set. The name can be set by explicitly calling .setName(name) on the stub, or by using routePartyKitRequest(). This is a known issue and will be fixed soon. Follow https://github.com/cloudflare/workerd/issues/2240 for more updates.`);\n\t\t} else throw new Error(`Attempting to read .name on ${this.#ParentClass.name} before it was set.`);\n\t\treturn this.#_name;\n\t}\n\tasync setName(name) {\n\t\tif (!name) throw new Error(\"A name is required.\");\n\t\tif (this.#_name && this.#_name !== name) throw new Error(\"This server already has a name.\");\n\t\tthis.#_name = name;\n\t\tif (this.#status !== \"started\") await this.ctx.blockConcurrencyWhile(async () => {\n\t\t\tawait this.#initialize();\n\t\t});\n\t}\n\t#sendMessageToConnection(connection, message) {\n\t\ttry {\n\t\t\tconnection.send(message);\n\t\t} catch (_e) {\n\t\t\tconnection.close(1011, \"Unexpected error\");\n\t\t}\n\t}\n\t/** Send a message to all connected clients, except connection ids listed in `without` */\n\tbroadcast(msg, without) {\n\t\tfor (const connection of this.#connectionManager.getConnections()) if (!without || !without.includes(connection.id)) this.#sendMessageToConnection(connection, msg);\n\t}\n\t/** Get a connection by connection id */\n\tgetConnection(id) {\n\t\treturn this.#connectionManager.getConnection(id);\n\t}\n\t/**\n\t* Get all connections. Optionally, you can provide a tag to filter returned connections.\n\t* Use `Server#getConnectionTags` to tag the connection on connect.\n\t*/\n\tgetConnections(tag) {\n\t\treturn this.#connectionManager.getConnections(tag);\n\t}\n\t/**\n\t* You can tag a connection to filter them in Server#getConnections.\n\t* Each connection supports up to 9 tags, each tag max length is 256 characters.\n\t*/\n\tgetConnectionTags(connection, context) {\n\t\treturn [];\n\t}\n\t/**\n\t* Execute a long-running async function while keeping the Durable Object alive.\n\t*\n\t* Durable Objects normally terminate 70-140s after the last network request.\n\t* This method keeps the DO alive by establishing a WebSocket connection to itself\n\t* and sending periodic ping messages.\n\t*\n\t* @experimental This API is experimental and may change in future versions.\n\t*\n\t* @param fn - The async function to execute\n\t* @param timeoutMs - Maximum time to keep the DO alive (default: 30 minutes)\n\t* @returns The result of the async function\n\t*\n\t* @remarks\n\t* Requires the `enable_ctx_exports` compatibility flag in wrangler.jsonc:\n\t* ```json\n\t* {\n\t* \"compatibility_flags\": [\"enable_ctx_exports\"]\n\t* }\n\t* ```\n\t*\n\t* @example\n\t* ```typescript\n\t* const result = await this.experimental_waitUntil(async () => {\n\t* // Long-running operation\n\t* await processLargeDataset();\n\t* return { success: true };\n\t* }, 60 * 60 * 1000); // 1 hour timeout\n\t* ```\n\t*/\n\tasync experimental_waitUntil(fn, timeoutMs = 1800 * 1e3) {\n\t\tconst exports = this.ctx.exports;\n\t\tif (!exports) throw new Error(\"waitUntil requires the 'enable_ctx_exports' compatibility flag. Add it to your wrangler.jsonc: { \\\"compatibility_flags\\\": [\\\"enable_ctx_exports\\\"] }\");\n\t\tconst namespace = exports[this.#ParentClass.name];\n\t\tif (!namespace) throw new Error(`Could not find namespace for ${this.#ParentClass.name} in ctx.exports. Make sure the class name matches your Durable Object binding.`);\n\t\tconst ws = (await namespace.get(this.ctx.id).fetch(\"http://dummy-example.cloudflare.com/cdn-cgi/partyserver/keep-alive/\", { headers: {\n\t\t\tUpgrade: \"websocket\",\n\t\t\t\"x-partykit-room\": this.name\n\t\t} })).webSocket;\n\t\tif (!ws) throw new Error(\"Failed to establish keep-alive WebSocket connection\");\n\t\tws.accept();\n\t\tconst pingInterval = setInterval(() => {\n\t\t\ttry {\n\t\t\t\tws.send(\"ping\");\n\t\t\t} catch {}\n\t\t}, 1e4);\n\t\tlet timeoutId;\n\t\tconst timeoutPromise = new Promise((_, reject) => {\n\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\treject(/* @__PURE__ */ new Error(`experimental_waitUntil timed out after ${timeoutMs}ms`));\n\t\t\t}, timeoutMs);\n\t\t});\n\t\ttry {\n\t\t\treturn await Promise.race([fn(), timeoutPromise]);\n\t\t} finally {\n\t\t\tclearTimeout(timeoutId);\n\t\t\tclearInterval(pingInterval);\n\t\t\ttry {\n\t\t\t\tws.close(1e3, \"Complete\");\n\t\t\t} catch {}\n\t\t}\n\t}\n\t#_props;\n\t/**\n\t* Called when the server is started for the first time.\n\t*/\n\tonStart(props) {}\n\t/**\n\t* Called when a new connection is made to the server.\n\t*/\n\tonConnect(connection, ctx) {\n\t\tconsole.log(`Connection ${connection.id} connected to ${this.#ParentClass.name}:${this.name}`);\n\t}\n\t/**\n\t* Called when a message is received from a connection.\n\t*/\n\tonMessage(connection, message) {\n\t\tconsole.log(`Received message on connection ${this.#ParentClass.name}:${connection.id}`);\n\t\tconsole.info(`Implement onMessage on ${this.#ParentClass.name} to handle this message.`);\n\t}\n\t/**\n\t* Called when a connection is closed.\n\t*/\n\tonClose(connection, code, reason, wasClean) {}\n\t/**\n\t* Called when an error occurs on a connection.\n\t*/\n\tonError(connection, error) {\n\t\tconsole.error(`Error on connection ${connection.id} in ${this.#ParentClass.name}:${this.name}:`, error);\n\t\tconsole.info(`Implement onError on ${this.#ParentClass.name} to handle this error.`);\n\t}\n\t/**\n\t* Called when a request is made to the server.\n\t*/\n\tonRequest(request) {\n\t\tconsole.warn(`onRequest hasn't been implemented on ${this.#ParentClass.name}:${this.name} responding to ${request.url}`);\n\t\treturn new Response(\"Not implemented\", { status: 404 });\n\t}\n\t/**\n\t* Called when an exception occurs.\n\t* @param error - The error that occurred.\n\t*/\n\tonException(error) {\n\t\tconsole.error(`Exception in ${this.#ParentClass.name}:${this.name}:`, error);\n\t\tconsole.info(`Implement onException on ${this.#ParentClass.name} to handle this error.`);\n\t}\n\tonAlarm() {\n\t\tconsole.log(`Implement onAlarm on ${this.#ParentClass.name} to handle alarms.`);\n\t}\n\tasync alarm() {\n\t\tif (this.#status !== \"started\") await this.#initialize();\n\t\tawait this.onAlarm();\n\t}\n};\n\n//#endregion\nexport { Server, getServerByName, routePartykitRequest };\n//# sourceMappingURL=index.js.map","import * as decoding from \"lib0/decoding\";\nimport * as encoding from \"lib0/encoding\";\nimport debounce from \"lodash.debounce\";\nimport type { Connection, ConnectionContext, WSMessage } from \"partyserver\";\nimport { Server } from \"partyserver\";\nimport * as awarenessProtocol from \"y-protocols/awareness\";\nimport * as syncProtocol from \"y-protocols/sync\";\nimport {\n applyUpdate,\n Doc as YDoc,\n encodeStateAsUpdate,\n encodeStateVector,\n UndoManager,\n XmlText,\n XmlElement,\n XmlFragment\n} from \"yjs\";\n\nimport { handleChunked } from \"../shared/chunking\";\n\nconst snapshotOrigin = Symbol(\"snapshot-origin\");\ntype YjsRootType =\n | \"Text\"\n | \"Map\"\n | \"Array\"\n | \"XmlText\"\n | \"XmlElement\"\n | \"XmlFragment\";\n\nconst wsReadyStateConnecting = 0;\nconst wsReadyStateOpen = 1;\n// biome-ignore lint/correctness/noUnusedVariables: it's fine\nconst wsReadyStateClosing = 2;\n// biome-ignore lint/correctness/noUnusedVariables: it's fine\nconst wsReadyStateClosed = 3;\n\nconst messageSync = 0;\nconst messageAwareness = 1;\n// biome-ignore lint/correctness/noUnusedVariables: it's fine\nconst messageAuth = 2;\n\nfunction updateHandler(update: Uint8Array, _origin: unknown, doc: WSSharedDoc) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeUpdate(encoder, update);\n const message = encoding.toUint8Array(encoder);\n doc.conns.forEach((_, conn) => {\n send(doc, conn, message);\n });\n}\n\nclass WSSharedDoc extends YDoc {\n conns: Map<Connection, Set<number>>;\n awareness: awarenessProtocol.Awareness;\n\n constructor() {\n super({ gc: true });\n\n /**\n * Maps from conn to set of controlled user ids. Delete all user ids from awareness when this conn is closed\n */\n this.conns = new Map();\n\n this.awareness = new awarenessProtocol.Awareness(this);\n this.awareness.setLocalState(null);\n\n const awarenessChangeHandler = (\n {\n added,\n updated,\n removed\n }: {\n added: Array<number>;\n updated: Array<number>;\n removed: Array<number>;\n },\n conn: Connection | null // Origin is the connection that made the change\n ) => {\n const changedClients = added.concat(updated, removed);\n if (conn !== null) {\n const connControlledIDs =\n /** @type {Set<number>} */ this.conns.get(conn);\n if (connControlledIDs !== undefined) {\n added.forEach((clientID) => {\n connControlledIDs.add(clientID);\n });\n removed.forEach((clientID) => {\n connControlledIDs.delete(clientID);\n });\n }\n }\n // broadcast awareness update\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(this.awareness, changedClients)\n );\n const buff = encoding.toUint8Array(encoder);\n this.conns.forEach((_, c) => {\n send(this, c, buff);\n });\n };\n this.awareness.on(\"update\", awarenessChangeHandler);\n // @ts-expect-error - TODO: fix this\n this.on(\"update\", updateHandler);\n }\n}\n\nconst CALLBACK_DEFAULTS = {\n debounceWait: 2000,\n debounceMaxWait: 10000,\n timeout: 5000\n};\n\nfunction readSyncMessage(\n decoder: decoding.Decoder,\n encoder: encoding.Encoder,\n doc: YDoc,\n transactionOrigin: Connection,\n readOnly = false\n) {\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case syncProtocol.messageYjsSyncStep1:\n syncProtocol.readSyncStep1(decoder, encoder, doc);\n break;\n case syncProtocol.messageYjsSyncStep2:\n if (!readOnly)\n syncProtocol.readSyncStep2(decoder, doc, transactionOrigin);\n break;\n case syncProtocol.messageYjsUpdate:\n if (!readOnly) syncProtocol.readUpdate(decoder, doc, transactionOrigin);\n break;\n default:\n throw new Error(\"Unknown message type\");\n }\n return messageType;\n}\n\nfunction closeConn(doc: WSSharedDoc, conn: Connection): void {\n if (doc.conns.has(conn)) {\n const controlledIds: Set<number> = doc.conns.get(conn)!;\n doc.conns.delete(conn);\n awarenessProtocol.removeAwarenessStates(\n doc.awareness,\n Array.from(controlledIds),\n null\n );\n }\n try {\n conn.close();\n } catch (e) {\n console.warn(\"failed to close connection\", e);\n }\n}\n\nfunction send(doc: WSSharedDoc, conn: Connection, m: Uint8Array) {\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n closeConn(doc, conn);\n }\n try {\n conn.send(m);\n } catch (_e) {\n closeConn(doc, conn);\n }\n}\n\nexport interface CallbackOptions {\n debounceWait?: number;\n debounceMaxWait?: number;\n timeout?: number;\n}\n\nexport class YServer<Env = unknown> extends Server<Env> {\n static callbackOptions: CallbackOptions = {};\n\n #ParentClass: typeof YServer = Object.getPrototypeOf(this).constructor;\n readonly document: WSSharedDoc = new WSSharedDoc();\n\n async onLoad(): Promise<void> {\n // to be implemented by the user\n return;\n }\n\n async onSave(): Promise<void> {\n // to be implemented by the user\n }\n\n /**\n * Replaces the document with a different state using Yjs UndoManager key remapping.\n *\n * @param snapshotUpdate - The snapshot update to replace the document with.\n * @param getMetadata (optional) - A function that returns the type of the root for a given key.\n */\n unstable_replaceDocument(\n snapshotUpdate: Uint8Array,\n getMetadata: (key: string) => YjsRootType = () => \"Map\"\n ): void {\n try {\n const doc = this.document;\n const snapshotDoc = new YDoc();\n applyUpdate(snapshotDoc, snapshotUpdate, snapshotOrigin);\n\n const currentStateVector = encodeStateVector(doc);\n const snapshotStateVector = encodeStateVector(snapshotDoc);\n\n const changesSinceSnapshotUpdate = encodeStateAsUpdate(\n doc,\n snapshotStateVector\n );\n\n const undoManager = new UndoManager(\n [...snapshotDoc.share.keys()].map((key) => {\n const type = getMetadata(key);\n if (type === \"Text\") {\n return snapshotDoc.getText(key);\n } else if (type === \"Map\") {\n return snapshotDoc.getMap(key);\n } else if (type === \"Array\") {\n return snapshotDoc.getArray(key);\n } else if (type === \"XmlText\") {\n return snapshotDoc.get(key, XmlText);\n } else if (type === \"XmlElement\") {\n return snapshotDoc.get(key, XmlElement);\n } else if (type === \"XmlFragment\") {\n return snapshotDoc.get(key, XmlFragment);\n }\n throw new Error(`Unknown root type: ${type} for key: ${key}`);\n }),\n {\n trackedOrigins: new Set([snapshotOrigin])\n }\n );\n\n applyUpdate(snapshotDoc, changesSinceSnapshotUpdate, snapshotOrigin);\n undoManager.undo();\n\n const documentChangesSinceSnapshotUpdate = encodeStateAsUpdate(\n snapshotDoc,\n currentStateVector\n );\n\n applyUpdate(this.document, documentChangesSinceSnapshotUpdate);\n } catch (error) {\n throw new Error(\n `Failed to replace document: ${error instanceof Error ? error.message : \"Unknown error\"}`\n );\n }\n }\n\n async onStart(): Promise<void> {\n const src = await this.onLoad();\n if (src != null) {\n const state = encodeStateAsUpdate(src);\n applyUpdate(this.document, state);\n }\n\n this.document.on(\n \"update\",\n debounce(\n (_update: Uint8Array, _origin: Connection, _doc: YDoc) => {\n try {\n this.onSave().catch((err) => {\n console.error(\"failed to persist:\", err);\n });\n } catch (err) {\n console.error(\"failed to persist:\", err);\n }\n },\n this.#ParentClass.callbackOptions.debounceWait ||\n CALLBACK_DEFAULTS.debounceWait,\n {\n maxWait:\n this.#ParentClass.callbackOptions.debounceMaxWait ||\n CALLBACK_DEFAULTS.debounceMaxWait\n }\n )\n );\n }\n\n // biome-ignore lint/correctness/noUnusedFunctionParameters: so autocomplete works\n isReadOnly(connection: Connection): boolean {\n // to be implemented by the user\n return false;\n }\n\n /**\n * Handle custom string messages from the client.\n * Override this method to implement custom message handling.\n * @param connection - The connection that sent the message\n * @param message - The custom message string (without the __YPS: prefix)\n */\n // biome-ignore lint/correctness/noUnusedFunctionParameters: so autocomplete works\n onCustomMessage(connection: Connection, message: string): void {\n // to be implemented by the user\n console.warn(\n `Received custom message but onCustomMessage is not implemented in ${this.#ParentClass.name}:`,\n message\n );\n }\n\n /**\n * Send a custom string message to a specific connection.\n * @param connection - The connection to send the message to\n * @param message - The custom message string to send\n */\n sendCustomMessage(connection: Connection, message: string): void {\n if (\n connection.readyState !== undefined &&\n connection.readyState !== wsReadyStateConnecting &&\n connection.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n connection.send(`__YPS:${message}`);\n } catch (e) {\n console.warn(\"Failed to send custom message\", e);\n }\n }\n\n /**\n * Broadcast a custom string message to all connected clients.\n * @param message - The custom message string to broadcast\n * @param excludeConnection - Optional connection to exclude from the broadcast\n */\n broadcastCustomMessage(\n message: string,\n excludeConnection?: Connection\n ): void {\n const formattedMessage = `__YPS:${message}`;\n this.document.conns.forEach((_, conn) => {\n if (excludeConnection && conn === excludeConnection) {\n return;\n }\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n conn.send(formattedMessage);\n } catch (e) {\n console.warn(\"Failed to broadcast custom message\", e);\n }\n });\n }\n\n handleMessage(connection: Connection, message: WSMessage) {\n if (typeof message === \"string\") {\n // Handle custom messages with __YPS: prefix\n if (message.startsWith(\"__YPS:\")) {\n const customMessage = message.slice(6); // Remove __YPS: prefix\n this.onCustomMessage(connection, customMessage);\n return;\n }\n console.warn(\n `Received non-prefixed string message. Custom messages should be sent using sendMessage() on the provider.`\n );\n return;\n }\n try {\n const encoder = encoding.createEncoder();\n // TODO: this type seems odd\n const decoder = decoding.createDecoder(message as unknown as Uint8Array);\n const messageType = decoding.readVarUint(decoder);\n switch (messageType) {\n case messageSync:\n encoding.writeVarUint(encoder, messageSync);\n readSyncMessage(\n decoder,\n encoder,\n this.document,\n connection,\n this.isReadOnly(connection)\n );\n\n // If the `encoder` only contains the type of reply message and no\n // message, there is no need to send the message. When `encoder` only\n // contains the type of reply, its length is 1.\n if (encoding.length(encoder) > 1) {\n send(this.document, connection, encoding.toUint8Array(encoder));\n }\n break;\n case messageAwareness: {\n awarenessProtocol.applyAwarenessUpdate(\n this.document.awareness,\n decoding.readVarUint8Array(decoder),\n connection\n );\n break;\n }\n }\n } catch (err) {\n console.error(err);\n // @ts-expect-error - TODO: fix this\n this.document.emit(\"error\", [err]);\n }\n }\n\n onMessage = handleChunked((conn, message) =>\n this.handleMessage(conn, message)\n );\n\n onClose(\n connection: Connection<unknown>,\n _code: number,\n _reason: string,\n _wasClean: boolean\n ): void | Promise<void> {\n closeConn(this.document, connection);\n }\n\n // TODO: explore why onError gets triggered when a connection closes\n\n onConnect(\n conn: Connection<unknown>,\n _ctx: ConnectionContext\n ): void | Promise<void> {\n // conn.binaryType = \"arraybuffer\"; // from y-websocket, breaks in our runtime\n\n this.document.conns.set(conn, new Set());\n\n // send sync step 1\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, this.document);\n send(this.document, conn, encoding.toUint8Array(encoder));\n const awarenessStates = this.document.awareness.getStates();\n if (awarenessStates.size > 0) {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.document.awareness,\n Array.from(awarenessStates.keys())\n )\n );\n send(this.document, conn, encoding.toUint8Array(encoder));\n }\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "y-partyserver",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.54",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git://github.com/cloudflare/partykit.git"
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@cloudflare/workers-types": "^4.20240729.0",
|
|
50
|
-
"partyserver": "^0.0.
|
|
50
|
+
"partyserver": "^0.0.78",
|
|
51
51
|
"yjs": "^13.6.14"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@cloudflare/workers-types": "^4.20251218.0",
|
|
55
55
|
"@types/lodash.debounce": "^4.0.9",
|
|
56
|
-
"partyserver": "^0.0.
|
|
56
|
+
"partyserver": "^0.0.78",
|
|
57
57
|
"ws": "^8.18.3",
|
|
58
58
|
"yjs": "^13.6.28"
|
|
59
59
|
}
|