diff --git a/.changeset/fix-basepath-reconnect.md b/.changeset/fix-basepath-reconnect.md new file mode 100644 index 0000000..d66cf00 --- /dev/null +++ b/.changeset/fix-basepath-reconnect.md @@ -0,0 +1,5 @@ +--- +"partysocket": patch +--- + +Fix `PartySocket.reconnect()` crashing when using `basePath` without `room`. The reconnect guard now accepts either `room` or `basePath` as sufficient context to construct a connection URL. diff --git a/package-lock.json b/package-lock.json index 2683112..1a820b9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12235,7 +12235,7 @@ "devDependencies": { "@cloudflare/workers-types": "^4.20251218.0", "hono": "^4.11.1", - "partyserver": "^0.1.1" + "partyserver": "^0.1.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20240729.0", @@ -12327,7 +12327,7 @@ "license": "ISC", "devDependencies": { "@cloudflare/workers-types": "^4.20251218.0", - "partyserver": "^0.1.1", + "partyserver": "^0.1.2", "partysocket": "^1.1.11" }, "peerDependencies": { @@ -12345,7 +12345,7 @@ }, "devDependencies": { "@cloudflare/workers-types": "^4.20251218.0", - "partyserver": "^0.1.1" + "partyserver": "^0.1.2" }, "peerDependencies": { "@cloudflare/workers-types": "^4.20240729.0", @@ -12367,7 +12367,7 @@ "license": "ISC", "dependencies": { "cron-parser": "^5.4.0", - "partyserver": "^0.1.1" + "partyserver": "^0.1.2" } }, "packages/y-partyserver": { @@ -12382,7 +12382,7 @@ "devDependencies": { "@cloudflare/workers-types": "^4.20251218.0", "@types/lodash.debounce": "^4.0.9", - "partyserver": "^0.1.1", + "partyserver": "^0.1.2", "ws": "^8.18.3", "yjs": "^13.6.28" }, diff --git a/packages/hono-party/package.json b/packages/hono-party/package.json index 470ca5f..9364a9a 100644 --- a/packages/hono-party/package.json +++ b/packages/hono-party/package.json @@ -37,6 +37,6 @@ "devDependencies": { "@cloudflare/workers-types": "^4.20251218.0", "hono": "^4.11.1", - "partyserver": "^0.1.1" + "partyserver": "^0.1.2" } } diff --git a/packages/partysocket/src/index.ts b/packages/partysocket/src/index.ts index db01f3e..66310e2 100644 --- a/packages/partysocket/src/index.ts +++ b/packages/partysocket/src/index.ts @@ -141,6 +141,7 @@ export default class PartySocket extends ReconnectingWebSocket { room?: string; host!: string; path!: string; + basePath?: string; constructor(readonly partySocketOptions: PartySocketOptions) { const wsOptions = getWSOptions(partySocketOptions); @@ -169,7 +170,8 @@ export default class PartySocket extends ReconnectingWebSocket { ...partySocketOptions, host: partySocketOptions.host ?? this.host, room: partySocketOptions.room ?? this.room, - path: partySocketOptions.path ?? this.path + path: partySocketOptions.path ?? this.path, + basePath: partySocketOptions.basePath ?? this.basePath }); this._url = wsOptions.urlProvider; @@ -180,7 +182,7 @@ export default class PartySocket extends ReconnectingWebSocket { } private setWSProperties(wsOptions: ReturnType) { - const { _pk, _pkurl, name, room, host, path } = wsOptions; + const { _pk, _pkurl, name, room, host, path, basePath } = wsOptions; this._pk = _pk; this._pkurl = _pkurl; @@ -188,15 +190,21 @@ export default class PartySocket extends ReconnectingWebSocket { this.room = room; this.host = host; this.path = path; + this.basePath = basePath; } public reconnect( code?: number | undefined, reason?: string | undefined ): void { - if (!this.room || !this.host) { + if (!this.host) { throw new Error( - "The room and host must be set before connecting, use `updateProperties` method to set them or pass them to the constructor." + "The host must be set before connecting, use `updateProperties` method to set it or pass it to the constructor." + ); + } + if (!this.room && !this.basePath) { + throw new Error( + "The room (or basePath) must be set before connecting, use `updateProperties` method to set it or pass it to the constructor." ); } super.reconnect(code, reason); @@ -256,6 +264,7 @@ function getWSOptions(partySocketOptions: PartySocketOptions) { room: party.room, host: party.host, path: party.path, + basePath: partySocketOptions.basePath, protocols: protocols, socketOptions: socketOptions, urlProvider: party.urlProvider diff --git a/packages/partysocket/src/tests/error-handling.test.ts b/packages/partysocket/src/tests/error-handling.test.ts index a73668c..985a185 100644 --- a/packages/partysocket/src/tests/error-handling.test.ts +++ b/packages/partysocket/src/tests/error-handling.test.ts @@ -126,7 +126,7 @@ describe.skip("Error Handling - PartySocket Validation", () => { expect(() => { ps.reconnect(); - }).toThrow("The room and host must be set"); + }).toThrow("The host must be set"); }); test("throws when reconnecting without room", () => { @@ -140,7 +140,19 @@ describe.skip("Error Handling - PartySocket Validation", () => { expect(() => { ps.reconnect(); - }).toThrow("The room and host must be set"); + }).toThrow("The room (or basePath) must be set"); + }); + + test("does not throw when reconnecting with basePath and no room", () => { + const ps = new PartySocket({ + host: "example.com", + basePath: "custom/path", + startClosed: true + }); + + expect(() => { + ps.reconnect(); + }).not.toThrow(); }); test("handles missing WebSocket constructor gracefully", async () => { diff --git a/packages/partysocket/src/tests/partysocket-url.test.ts b/packages/partysocket/src/tests/partysocket-url.test.ts index 3bec785..8a979d0 100644 --- a/packages/partysocket/src/tests/partysocket-url.test.ts +++ b/packages/partysocket/src/tests/partysocket-url.test.ts @@ -432,7 +432,7 @@ describe.skip("PartySocket.updateProperties", () => { ps.updateProperties({ host: "", room: "" }); expect(() => { ps.reconnect(); - }).toThrow("The room and host must be set"); + }).toThrow("The host must be set"); }); }); diff --git a/packages/partysub/package.json b/packages/partysub/package.json index c375d14..df17dcf 100644 --- a/packages/partysub/package.json +++ b/packages/partysub/package.json @@ -46,7 +46,7 @@ }, "devDependencies": { "@cloudflare/workers-types": "^4.20251218.0", - "partyserver": "^0.1.1", + "partyserver": "^0.1.2", "partysocket": "^1.1.11" } } diff --git a/packages/partysync/package.json b/packages/partysync/package.json index 7064aa2..116aa90 100644 --- a/packages/partysync/package.json +++ b/packages/partysync/package.json @@ -54,6 +54,6 @@ }, "devDependencies": { "@cloudflare/workers-types": "^4.20251218.0", - "partyserver": "^0.1.1" + "partyserver": "^0.1.2" } } diff --git a/packages/partywhen/package.json b/packages/partywhen/package.json index 9b3f297..d50c21e 100644 --- a/packages/partywhen/package.json +++ b/packages/partywhen/package.json @@ -29,6 +29,6 @@ "description": "A library for scheduling and running tasks in Cloudflare Workers", "dependencies": { "cron-parser": "^5.4.0", - "partyserver": "^0.1.1" + "partyserver": "^0.1.2" } } diff --git a/packages/y-partyserver/package.json b/packages/y-partyserver/package.json index c331f91..2c50e6a 100644 --- a/packages/y-partyserver/package.json +++ b/packages/y-partyserver/package.json @@ -53,7 +53,7 @@ "devDependencies": { "@cloudflare/workers-types": "^4.20251218.0", "@types/lodash.debounce": "^4.0.9", - "partyserver": "^0.1.1", + "partyserver": "^0.1.2", "ws": "^8.18.3", "yjs": "^13.6.28" }