y-partyserver 2.1.0 → 2.1.2

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.
@@ -0,0 +1,34 @@
1
+ const require_chunk = require("../chunk-C0xms8kb.cjs");
2
+ const require_provider_index = require("./index.cjs");
3
+ let react = require("react");
4
+
5
+ //#region src/provider/react.tsx
6
+ function useYProvider(yProviderOptions) {
7
+ const { host, room, party, doc, options, prefix } = yProviderOptions;
8
+ const [provider] = (0, react.useState)(
9
+ () =>
10
+ new require_provider_index.default(
11
+ host ||
12
+ (typeof window !== "undefined"
13
+ ? window.location.host
14
+ : "dummy-domain.com"),
15
+ room,
16
+ doc,
17
+ {
18
+ connect: false,
19
+ party,
20
+ prefix,
21
+ ...options
22
+ }
23
+ )
24
+ );
25
+ (0, react.useEffect)(() => {
26
+ provider.connect();
27
+ return () => provider.disconnect();
28
+ }, [provider]);
29
+ return provider;
30
+ }
31
+
32
+ //#endregion
33
+ module.exports = useYProvider;
34
+ //# sourceMappingURL=react.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.cjs","names":["YProvider"],"sources":["../../src/provider/react.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\n\nimport YProvider from \"./index\";\n\nimport type * as Y from \"yjs\";\n\ntype UseYProviderOptions = {\n host?: string | undefined;\n room: string;\n party?: string;\n doc?: Y.Doc;\n prefix?: string;\n options?: ConstructorParameters<typeof YProvider>[3];\n};\n\nexport default function useYProvider(yProviderOptions: UseYProviderOptions) {\n const { host, room, party, doc, options, prefix } = yProviderOptions;\n const [provider] = useState<YProvider>(\n () =>\n new YProvider(\n host ||\n (typeof window !== \"undefined\"\n ? window.location.host\n : \"dummy-domain.com\"),\n room,\n doc,\n {\n connect: false,\n party,\n prefix,\n ...options\n }\n )\n );\n\n useEffect(() => {\n void provider.connect();\n return () => provider.disconnect();\n }, [provider]);\n return provider;\n}\n"],"mappings":";;;;;AAeA,SAAwB,aAAa,kBAAuC;CAC1E,MAAM,EAAE,MAAM,MAAM,OAAO,KAAK,SAAS,WAAW;CACpD,MAAM,CAAC,sCAEH,IAAIA,+BACF,SACG,OAAO,WAAW,cACf,OAAO,SAAS,OAChB,qBACN,MACA,KACA;EACE,SAAS;EACT;EACA;EACA,GAAG;EACJ,CACF,CACJ;AAED,4BAAgB;AACd,EAAK,SAAS,SAAS;AACvB,eAAa,SAAS,YAAY;IACjC,CAAC,SAAS,CAAC;AACd,QAAO"}
@@ -0,0 +1,15 @@
1
+ import YProvider from "./index.cjs";
2
+ import * as Y from "yjs";
3
+
4
+ //#region src/provider/react.d.ts
5
+ type UseYProviderOptions = {
6
+ host?: string | undefined;
7
+ room: string;
8
+ party?: string;
9
+ doc?: Y.Doc;
10
+ prefix?: string;
11
+ options?: ConstructorParameters<typeof YProvider>[3];
12
+ };
13
+ declare function useYProvider(yProviderOptions: UseYProviderOptions): YProvider;
14
+ export = useYProvider;
15
+ //# sourceMappingURL=react.d.cts.map
@@ -3,20 +3,31 @@ import { useEffect, useState } from "react";
3
3
 
4
4
  //#region src/provider/react.tsx
5
5
  function useYProvider(yProviderOptions) {
6
- const { host, room, party, doc, options, prefix } = yProviderOptions;
7
- const [provider] = useState(() => new YProvider(host || (typeof window !== "undefined" ? window.location.host : "dummy-domain.com"), room, doc, {
8
- connect: false,
9
- party,
10
- prefix,
11
- ...options
12
- }));
13
- useEffect(() => {
14
- provider.connect();
15
- return () => provider.disconnect();
16
- }, [provider]);
17
- return provider;
6
+ const { host, room, party, doc, options, prefix } = yProviderOptions;
7
+ const [provider] = useState(
8
+ () =>
9
+ new YProvider(
10
+ host ||
11
+ (typeof window !== "undefined"
12
+ ? window.location.host
13
+ : "dummy-domain.com"),
14
+ room,
15
+ doc,
16
+ {
17
+ connect: false,
18
+ party,
19
+ prefix,
20
+ ...options
21
+ }
22
+ )
23
+ );
24
+ useEffect(() => {
25
+ provider.connect();
26
+ return () => provider.disconnect();
27
+ }, [provider]);
28
+ return provider;
18
29
  }
19
30
 
20
31
  //#endregion
21
32
  export { useYProvider as default };
22
- //# sourceMappingURL=react.js.map
33
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1,366 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_chunk = require("../chunk-C0xms8kb.cjs");
3
+ let lib0_decoding = require("lib0/decoding");
4
+ lib0_decoding = require_chunk.__toESM(lib0_decoding);
5
+ let lib0_encoding = require("lib0/encoding");
6
+ lib0_encoding = require_chunk.__toESM(lib0_encoding);
7
+ let lodash_debounce = require("lodash.debounce");
8
+ lodash_debounce = require_chunk.__toESM(lodash_debounce);
9
+ let partyserver = require("partyserver");
10
+ let y_protocols_awareness = require("y-protocols/awareness");
11
+ y_protocols_awareness = require_chunk.__toESM(y_protocols_awareness);
12
+ let y_protocols_sync = require("y-protocols/sync");
13
+ y_protocols_sync = require_chunk.__toESM(y_protocols_sync);
14
+ let yjs = require("yjs");
15
+
16
+ //#region src/server/index.ts
17
+ const snapshotOrigin = Symbol("snapshot-origin");
18
+ const wsReadyStateConnecting = 0;
19
+ const wsReadyStateOpen = 1;
20
+ const messageSync = 0;
21
+ const messageAwareness = 1;
22
+ /**
23
+ * Internal key used in connection.setState() to track which awareness
24
+ * client IDs are controlled by each connection. This survives hibernation
25
+ * because connection state is persisted to WebSocket attachments.
26
+ */
27
+ const AWARENESS_IDS_KEY = "__ypsAwarenessIds";
28
+ function getAwarenessIds(conn) {
29
+ try {
30
+ return conn.state?.[AWARENESS_IDS_KEY] ?? [];
31
+ } catch {
32
+ return [];
33
+ }
34
+ }
35
+ function setAwarenessIds(conn, ids) {
36
+ try {
37
+ conn.setState((prev) => ({
38
+ ...prev,
39
+ [AWARENESS_IDS_KEY]: ids
40
+ }));
41
+ } catch {}
42
+ }
43
+ var WSSharedDoc = class extends yjs.Doc {
44
+ awareness;
45
+ constructor() {
46
+ super({ gc: true });
47
+ this.awareness = new y_protocols_awareness.Awareness(this);
48
+ this.awareness.setLocalState(null);
49
+ clearInterval(this.awareness._checkInterval);
50
+ }
51
+ };
52
+ const CALLBACK_DEFAULTS = {
53
+ debounceWait: 2e3,
54
+ debounceMaxWait: 1e4,
55
+ timeout: 5e3
56
+ };
57
+ function readSyncMessage(
58
+ decoder,
59
+ encoder,
60
+ doc,
61
+ transactionOrigin,
62
+ readOnly = false
63
+ ) {
64
+ const messageType = lib0_decoding.readVarUint(decoder);
65
+ switch (messageType) {
66
+ case y_protocols_sync.messageYjsSyncStep1:
67
+ y_protocols_sync.readSyncStep1(decoder, encoder, doc);
68
+ break;
69
+ case y_protocols_sync.messageYjsSyncStep2:
70
+ if (!readOnly)
71
+ y_protocols_sync.readSyncStep2(decoder, doc, transactionOrigin);
72
+ break;
73
+ case y_protocols_sync.messageYjsUpdate:
74
+ if (!readOnly)
75
+ y_protocols_sync.readUpdate(decoder, doc, transactionOrigin);
76
+ break;
77
+ default:
78
+ throw new Error("Unknown message type");
79
+ }
80
+ return messageType;
81
+ }
82
+ function send(conn, m) {
83
+ if (
84
+ conn.readyState !== void 0 &&
85
+ conn.readyState !== wsReadyStateConnecting &&
86
+ conn.readyState !== wsReadyStateOpen
87
+ )
88
+ return;
89
+ try {
90
+ conn.send(m);
91
+ } catch {}
92
+ }
93
+ function withYjs(Base) {
94
+ class YjsMixin extends Base {
95
+ static callbackOptions = {};
96
+ document = new WSSharedDoc();
97
+ async onLoad() {}
98
+ async onSave() {}
99
+ /**
100
+ * Replaces the document with a different state using Yjs UndoManager key remapping.
101
+ *
102
+ * @param snapshotUpdate - The snapshot update to replace the document with.
103
+ * @param getMetadata (optional) - A function that returns the type of the root for a given key.
104
+ */
105
+ unstable_replaceDocument(snapshotUpdate, getMetadata = () => "Map") {
106
+ try {
107
+ const doc = this.document;
108
+ const snapshotDoc = new yjs.Doc();
109
+ (0, yjs.applyUpdate)(snapshotDoc, snapshotUpdate, snapshotOrigin);
110
+ const currentStateVector = (0, yjs.encodeStateVector)(doc);
111
+ const changesSinceSnapshotUpdate = (0, yjs.encodeStateAsUpdate)(
112
+ doc,
113
+ (0, yjs.encodeStateVector)(snapshotDoc)
114
+ );
115
+ const undoManager = new yjs.UndoManager(
116
+ [...snapshotDoc.share.keys()].map((key) => {
117
+ const type = getMetadata(key);
118
+ if (type === "Text") return snapshotDoc.getText(key);
119
+ else if (type === "Map") return snapshotDoc.getMap(key);
120
+ else if (type === "Array") return snapshotDoc.getArray(key);
121
+ else if (type === "XmlText")
122
+ return snapshotDoc.get(key, yjs.XmlText);
123
+ else if (type === "XmlElement")
124
+ return snapshotDoc.get(key, yjs.XmlElement);
125
+ else if (type === "XmlFragment")
126
+ return snapshotDoc.get(key, yjs.XmlFragment);
127
+ throw new Error(`Unknown root type: ${type} for key: ${key}`);
128
+ }),
129
+ { trackedOrigins: new Set([snapshotOrigin]) }
130
+ );
131
+ (0, yjs.applyUpdate)(
132
+ snapshotDoc,
133
+ changesSinceSnapshotUpdate,
134
+ snapshotOrigin
135
+ );
136
+ undoManager.undo();
137
+ const documentChangesSinceSnapshotUpdate = (0, yjs.encodeStateAsUpdate)(
138
+ snapshotDoc,
139
+ currentStateVector
140
+ );
141
+ (0, yjs.applyUpdate)(this.document, documentChangesSinceSnapshotUpdate);
142
+ } catch (error) {
143
+ throw new Error(
144
+ `Failed to replace document: ${error instanceof Error ? error.message : "Unknown error"}`
145
+ );
146
+ }
147
+ }
148
+ async onStart() {
149
+ const src = await this.onLoad();
150
+ if (src != null) {
151
+ const state = (0, yjs.encodeStateAsUpdate)(src);
152
+ (0, yjs.applyUpdate)(this.document, state);
153
+ }
154
+ this.document.on("update", (update) => {
155
+ const encoder = lib0_encoding.createEncoder();
156
+ lib0_encoding.writeVarUint(encoder, messageSync);
157
+ y_protocols_sync.writeUpdate(encoder, update);
158
+ const message = lib0_encoding.toUint8Array(encoder);
159
+ for (const conn of this.getConnections()) send(conn, message);
160
+ });
161
+ this.document.awareness.on(
162
+ "update",
163
+ ({ added, updated, removed }, conn) => {
164
+ if (conn !== null)
165
+ try {
166
+ const currentIds = new Set(getAwarenessIds(conn));
167
+ for (const clientID of added) currentIds.add(clientID);
168
+ for (const clientID of removed) currentIds.delete(clientID);
169
+ setAwarenessIds(conn, [...currentIds]);
170
+ } catch (_e) {}
171
+ else {
172
+ const changedClients = added.concat(updated, removed);
173
+ const encoder = lib0_encoding.createEncoder();
174
+ lib0_encoding.writeVarUint(encoder, messageAwareness);
175
+ lib0_encoding.writeVarUint8Array(
176
+ encoder,
177
+ y_protocols_awareness.encodeAwarenessUpdate(
178
+ this.document.awareness,
179
+ changedClients
180
+ )
181
+ );
182
+ const buff = lib0_encoding.toUint8Array(encoder);
183
+ for (const c of this.getConnections()) send(c, buff);
184
+ }
185
+ }
186
+ );
187
+ const ctor = this.constructor;
188
+ this.document.on(
189
+ "update",
190
+ (0, lodash_debounce.default)(
191
+ (_update, _origin, _doc) => {
192
+ try {
193
+ this.onSave().catch((err) => {
194
+ console.error("failed to persist:", err);
195
+ });
196
+ } catch (err) {
197
+ console.error("failed to persist:", err);
198
+ }
199
+ },
200
+ ctor.callbackOptions.debounceWait || CALLBACK_DEFAULTS.debounceWait,
201
+ {
202
+ maxWait:
203
+ ctor.callbackOptions.debounceMaxWait ||
204
+ CALLBACK_DEFAULTS.debounceMaxWait
205
+ }
206
+ )
207
+ );
208
+ const syncEncoder = lib0_encoding.createEncoder();
209
+ lib0_encoding.writeVarUint(syncEncoder, messageSync);
210
+ y_protocols_sync.writeSyncStep1(syncEncoder, this.document);
211
+ const syncMessage = lib0_encoding.toUint8Array(syncEncoder);
212
+ for (const conn of this.getConnections()) send(conn, syncMessage);
213
+ }
214
+ isReadOnly(connection) {
215
+ return false;
216
+ }
217
+ /**
218
+ * Handle custom string messages from the client.
219
+ * Override this method to implement custom message handling.
220
+ * @param connection - The connection that sent the message
221
+ * @param message - The custom message string (without the __YPS: prefix)
222
+ */
223
+ onCustomMessage(connection, message) {
224
+ console.warn(
225
+ `Received custom message but onCustomMessage is not implemented in ${this.constructor.name}:`,
226
+ message
227
+ );
228
+ }
229
+ /**
230
+ * Send a custom string message to a specific connection.
231
+ * @param connection - The connection to send the message to
232
+ * @param message - The custom message string to send
233
+ */
234
+ sendCustomMessage(connection, message) {
235
+ if (
236
+ connection.readyState !== void 0 &&
237
+ connection.readyState !== wsReadyStateConnecting &&
238
+ connection.readyState !== wsReadyStateOpen
239
+ )
240
+ return;
241
+ try {
242
+ connection.send(`__YPS:${message}`);
243
+ } catch (e) {
244
+ console.warn("Failed to send custom message", e);
245
+ }
246
+ }
247
+ /**
248
+ * Broadcast a custom string message to all connected clients.
249
+ * @param message - The custom message string to broadcast
250
+ * @param excludeConnection - Optional connection to exclude from the broadcast
251
+ */
252
+ broadcastCustomMessage(message, excludeConnection) {
253
+ const formattedMessage = `__YPS:${message}`;
254
+ for (const conn of this.getConnections()) {
255
+ if (excludeConnection && conn === excludeConnection) continue;
256
+ if (
257
+ conn.readyState !== void 0 &&
258
+ conn.readyState !== wsReadyStateConnecting &&
259
+ conn.readyState !== wsReadyStateOpen
260
+ )
261
+ continue;
262
+ try {
263
+ conn.send(formattedMessage);
264
+ } catch (e) {
265
+ console.warn("Failed to broadcast custom message", e);
266
+ }
267
+ }
268
+ }
269
+ handleMessage(connection, message) {
270
+ if (typeof message === "string") {
271
+ if (message.startsWith("__YPS:")) {
272
+ const customMessage = message.slice(6);
273
+ this.onCustomMessage(connection, customMessage);
274
+ return;
275
+ }
276
+ console.warn(
277
+ `Received non-prefixed string message. Custom messages should be sent using sendMessage() on the provider.`
278
+ );
279
+ return;
280
+ }
281
+ try {
282
+ const encoder = lib0_encoding.createEncoder();
283
+ const uint8Array =
284
+ message instanceof Uint8Array
285
+ ? message
286
+ : message instanceof ArrayBuffer
287
+ ? new Uint8Array(message)
288
+ : new Uint8Array(
289
+ message.buffer,
290
+ message.byteOffset,
291
+ message.byteLength
292
+ );
293
+ const decoder = lib0_decoding.createDecoder(uint8Array);
294
+ switch (lib0_decoding.readVarUint(decoder)) {
295
+ case messageSync:
296
+ lib0_encoding.writeVarUint(encoder, messageSync);
297
+ readSyncMessage(
298
+ decoder,
299
+ encoder,
300
+ this.document,
301
+ connection,
302
+ this.isReadOnly(connection)
303
+ );
304
+ if (lib0_encoding.length(encoder) > 1)
305
+ send(connection, lib0_encoding.toUint8Array(encoder));
306
+ break;
307
+ case messageAwareness: {
308
+ const awarenessData = lib0_decoding.readVarUint8Array(decoder);
309
+ y_protocols_awareness.applyAwarenessUpdate(
310
+ this.document.awareness,
311
+ awarenessData,
312
+ connection
313
+ );
314
+ const awarenessEncoder = lib0_encoding.createEncoder();
315
+ lib0_encoding.writeVarUint(awarenessEncoder, messageAwareness);
316
+ lib0_encoding.writeVarUint8Array(awarenessEncoder, awarenessData);
317
+ const awarenessBuff = lib0_encoding.toUint8Array(awarenessEncoder);
318
+ for (const c of this.getConnections()) send(c, awarenessBuff);
319
+ break;
320
+ }
321
+ }
322
+ } catch (err) {
323
+ console.error(err);
324
+ this.document.emit("error", [err]);
325
+ }
326
+ }
327
+ onMessage(conn, message) {
328
+ this.handleMessage(conn, message);
329
+ }
330
+ onClose(connection, _code, _reason, _wasClean) {
331
+ const controlledIds = getAwarenessIds(connection);
332
+ if (controlledIds.length > 0)
333
+ y_protocols_awareness.removeAwarenessStates(
334
+ this.document.awareness,
335
+ controlledIds,
336
+ null
337
+ );
338
+ }
339
+ onConnect(conn, _ctx) {
340
+ const encoder = lib0_encoding.createEncoder();
341
+ lib0_encoding.writeVarUint(encoder, messageSync);
342
+ y_protocols_sync.writeSyncStep1(encoder, this.document);
343
+ send(conn, lib0_encoding.toUint8Array(encoder));
344
+ const awarenessStates = this.document.awareness.getStates();
345
+ if (awarenessStates.size > 0) {
346
+ const encoder = lib0_encoding.createEncoder();
347
+ lib0_encoding.writeVarUint(encoder, messageAwareness);
348
+ lib0_encoding.writeVarUint8Array(
349
+ encoder,
350
+ y_protocols_awareness.encodeAwarenessUpdate(
351
+ this.document.awareness,
352
+ Array.from(awarenessStates.keys())
353
+ )
354
+ );
355
+ send(conn, lib0_encoding.toUint8Array(encoder));
356
+ }
357
+ }
358
+ }
359
+ return YjsMixin;
360
+ }
361
+ const YServer = withYjs(partyserver.Server);
362
+
363
+ //#endregion
364
+ exports.YServer = YServer;
365
+ exports.withYjs = withYjs;
366
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["YDoc","awarenessProtocol","decoding","syncProtocol","UndoManager","XmlText","XmlElement","XmlFragment","encoding","Server"],"sources":["../../src/server/index.ts"],"sourcesContent":["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\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// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosing = 2;\n// oxlint-disable-next-line no-unused-vars\nconst wsReadyStateClosed = 3;\n\nconst messageSync = 0;\nconst messageAwareness = 1;\n// oxlint-disable-next-line no-unused-vars\nconst messageAuth = 2;\n\n/**\n * Internal key used in connection.setState() to track which awareness\n * client IDs are controlled by each connection. This survives hibernation\n * because connection state is persisted to WebSocket attachments.\n */\nconst AWARENESS_IDS_KEY = \"__ypsAwarenessIds\";\n\ntype YServerConnectionState = {\n [AWARENESS_IDS_KEY]?: number[];\n [key: string]: unknown;\n};\n\nfunction getAwarenessIds(conn: Connection): number[] {\n try {\n const state = conn.state as YServerConnectionState | null;\n return state?.[AWARENESS_IDS_KEY] ?? [];\n } catch {\n return [];\n }\n}\n\nfunction setAwarenessIds(conn: Connection, ids: number[]): void {\n try {\n conn.setState((prev: YServerConnectionState | null) => ({\n ...prev,\n [AWARENESS_IDS_KEY]: ids\n }));\n } catch {\n // ignore — may fail if connection is already closed\n }\n}\n\nclass WSSharedDoc extends YDoc {\n awareness: awarenessProtocol.Awareness;\n\n constructor() {\n super({ gc: true });\n this.awareness = new awarenessProtocol.Awareness(this);\n this.awareness.setLocalState(null);\n\n // Disable the awareness protocol's built-in check interval.\n // It renews the local clock every 15s and removes peers after 30s,\n // but we handle peer cleanup via onClose instead. Clearing it here\n // prevents it from defeating Durable Object hibernation.\n clearInterval(\n (\n this.awareness as unknown as {\n _checkInterval: ReturnType<typeof setInterval>;\n }\n )._checkInterval\n );\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 send(conn: Connection, m: Uint8Array): void {\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n return;\n }\n try {\n conn.send(m);\n } catch {\n // connection is broken, ignore\n }\n}\n\nexport interface CallbackOptions {\n debounceWait?: number;\n debounceMaxWait?: number;\n timeout?: number;\n}\n\ntype ServerClass = new (...args: any[]) => Server;\n\nexport interface YjsInstance {\n readonly document: WSSharedDoc;\n onLoad(): Promise<YDoc | void>;\n onSave(): Promise<void>;\n unstable_replaceDocument(\n snapshotUpdate: Uint8Array,\n getMetadata?: (key: string) => YjsRootType\n ): void;\n isReadOnly(connection: Connection): boolean;\n onCustomMessage(connection: Connection, message: string): void;\n sendCustomMessage(connection: Connection, message: string): void;\n broadcastCustomMessage(message: string, excludeConnection?: Connection): void;\n handleMessage(connection: Connection, message: WSMessage): void;\n}\n\nexport interface YjsStatic {\n callbackOptions: CallbackOptions;\n}\n\nexport function withYjs<TBase extends ServerClass>(\n Base: TBase\n): TBase & YjsStatic & (new (...args: any[]) => YjsInstance) {\n class YjsMixin extends Base {\n static callbackOptions: CallbackOptions = {};\n\n readonly document: WSSharedDoc = new WSSharedDoc();\n\n async onLoad(): Promise<YDoc | 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 // Broadcast doc updates to all connections.\n // Uses this.getConnections() which works for both hibernate and non-hibernate\n // modes and survives DO hibernation (unlike an in-memory Map).\n this.document.on(\"update\", (update: Uint8Array) => {\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeUpdate(encoder, update);\n const message = encoding.toUint8Array(encoder);\n for (const conn of this.getConnections()) {\n send(conn, message);\n }\n });\n\n // Track which awareness clientIDs each connection controls.\n // Stored in connection.setState() so it survives hibernation.\n // When conn is null (internal changes like removeAwarenessStates on close),\n // broadcast the update to remaining connections.\n // When conn is non-null (client message), handleMessage broadcasts directly.\n this.document.awareness.on(\n \"update\",\n (\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\n ) => {\n if (conn !== null) {\n // Track which clientIDs this connection controls\n try {\n const currentIds = new Set(getAwarenessIds(conn));\n for (const clientID of added) currentIds.add(clientID);\n for (const clientID of removed) currentIds.delete(clientID);\n setAwarenessIds(conn, [...currentIds]);\n } catch (_e) {\n // ignore — best-effort tracking\n }\n } else {\n // Internal awareness change (e.g. removeAwarenessStates on close)\n // — broadcast to all remaining connections\n const changedClients = added.concat(updated, removed);\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageAwareness);\n encoding.writeVarUint8Array(\n encoder,\n awarenessProtocol.encodeAwarenessUpdate(\n this.document.awareness,\n changedClients\n )\n );\n const buff = encoding.toUint8Array(encoder);\n for (const c of this.getConnections()) {\n send(c, buff);\n }\n }\n }\n );\n\n // Debounced persistence handler\n const ctor = this.constructor as typeof YjsMixin;\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 ctor.callbackOptions.debounceWait || CALLBACK_DEFAULTS.debounceWait,\n {\n maxWait:\n ctor.callbackOptions.debounceMaxWait ||\n CALLBACK_DEFAULTS.debounceMaxWait\n }\n )\n );\n\n // After hibernation wake-up, the doc is empty but existing connections\n // survive. Re-sync by sending sync step 1 to all connections — they'll\n // respond with sync step 2 containing their full state.\n // On first start there are no connections, so this is a no-op.\n const syncEncoder = encoding.createEncoder();\n encoding.writeVarUint(syncEncoder, messageSync);\n syncProtocol.writeSyncStep1(syncEncoder, this.document);\n const syncMessage = encoding.toUint8Array(syncEncoder);\n for (const conn of this.getConnections()) {\n send(conn, syncMessage);\n }\n }\n\n // oxlint-disable-next-line no-unused-vars\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 // oxlint-disable-next-line no-unused-vars\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.constructor.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 for (const conn of this.getConnections()) {\n if (excludeConnection && conn === excludeConnection) {\n continue;\n }\n if (\n conn.readyState !== undefined &&\n conn.readyState !== wsReadyStateConnecting &&\n conn.readyState !== wsReadyStateOpen\n ) {\n continue;\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 // Convert ArrayBuffer to Uint8Array if needed (ArrayBufferView like Uint8Array can be used directly)\n const uint8Array =\n message instanceof Uint8Array\n ? message\n : message instanceof ArrayBuffer\n ? new Uint8Array(message)\n : new Uint8Array(\n message.buffer,\n message.byteOffset,\n message.byteLength\n );\n const decoder = decoding.createDecoder(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(connection, encoding.toUint8Array(encoder));\n }\n break;\n case messageAwareness: {\n const awarenessData = decoding.readVarUint8Array(decoder);\n awarenessProtocol.applyAwarenessUpdate(\n this.document.awareness,\n awarenessData,\n connection\n );\n // Forward raw awareness bytes to all connections\n const awarenessEncoder = encoding.createEncoder();\n encoding.writeVarUint(awarenessEncoder, messageAwareness);\n encoding.writeVarUint8Array(awarenessEncoder, awarenessData);\n const awarenessBuff = encoding.toUint8Array(awarenessEncoder);\n for (const c of this.getConnections()) {\n send(c, awarenessBuff);\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(conn: Connection, message: WSMessage) {\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 // Read controlled awareness clientIDs from connection state\n // (survives hibernation unlike an in-memory Map)\n const controlledIds = getAwarenessIds(connection);\n if (controlledIds.length > 0) {\n awarenessProtocol.removeAwarenessStates(\n this.document.awareness,\n controlledIds,\n null\n );\n }\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 // Note: awareness IDs are lazily initialized when the first awareness\n // message is received — no need to call setAwarenessIds(conn, []) here\n\n // send sync step 1\n const encoder = encoding.createEncoder();\n encoding.writeVarUint(encoder, messageSync);\n syncProtocol.writeSyncStep1(encoder, this.document);\n send(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(conn, encoding.toUint8Array(encoder));\n }\n }\n }\n\n return YjsMixin as unknown as TBase &\n YjsStatic &\n (new (...args: any[]) => YjsInstance);\n}\n\nexport const YServer = withYjs(Server);\n"],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ import * as awarenessProtocol from "y-protocols/awareness";
2
+ import { Doc } from "yjs";
3
+ import { Connection, Server, WSMessage } from "partyserver";
4
+
5
+ //#region src/server/index.d.ts
6
+ type YjsRootType =
7
+ | "Text"
8
+ | "Map"
9
+ | "Array"
10
+ | "XmlText"
11
+ | "XmlElement"
12
+ | "XmlFragment";
13
+ declare class WSSharedDoc extends Doc {
14
+ awareness: awarenessProtocol.Awareness;
15
+ constructor();
16
+ }
17
+ interface CallbackOptions {
18
+ debounceWait?: number;
19
+ debounceMaxWait?: number;
20
+ timeout?: number;
21
+ }
22
+ type ServerClass = new (...args: any[]) => Server;
23
+ interface YjsInstance {
24
+ readonly document: WSSharedDoc;
25
+ onLoad(): Promise<Doc | void>;
26
+ onSave(): Promise<void>;
27
+ unstable_replaceDocument(
28
+ snapshotUpdate: Uint8Array,
29
+ getMetadata?: (key: string) => YjsRootType
30
+ ): void;
31
+ isReadOnly(connection: Connection): boolean;
32
+ onCustomMessage(connection: Connection, message: string): void;
33
+ sendCustomMessage(connection: Connection, message: string): void;
34
+ broadcastCustomMessage(message: string, excludeConnection?: Connection): void;
35
+ handleMessage(connection: Connection, message: WSMessage): void;
36
+ }
37
+ interface YjsStatic {
38
+ callbackOptions: CallbackOptions;
39
+ }
40
+ declare function withYjs<TBase extends ServerClass>(
41
+ Base: TBase
42
+ ): TBase & YjsStatic & (new (...args: any[]) => YjsInstance);
43
+ declare const YServer: typeof Server &
44
+ YjsStatic &
45
+ (new (...args: any[]) => YjsInstance);
46
+ //#endregion
47
+ export { CallbackOptions, YServer, YjsInstance, YjsStatic, withYjs };
48
+ //# sourceMappingURL=index.d.cts.map
@@ -1,4 +1,4 @@
1
- import { Connection, ConnectionContext, Server, WSMessage } from "partyserver";
1
+ import { Connection, Server, WSMessage } from "partyserver";
2
2
  import * as awarenessProtocol from "y-protocols/awareness";
3
3
  import { Doc } from "yjs";
4
4
 
@@ -19,58 +19,30 @@ interface CallbackOptions {
19
19
  debounceMaxWait?: number;
20
20
  timeout?: number;
21
21
  }
22
- declare class YServer<
23
- Env extends Cloudflare.Env = Cloudflare.Env
24
- > extends Server<Env> {
25
- #private;
26
- static callbackOptions: CallbackOptions;
22
+ type ServerClass = new (...args: any[]) => Server;
23
+ interface YjsInstance {
27
24
  readonly document: WSSharedDoc;
28
25
  onLoad(): Promise<Doc | void>;
29
26
  onSave(): Promise<void>;
30
- /**
31
- * Replaces the document with a different state using Yjs UndoManager key remapping.
32
- *
33
- * @param snapshotUpdate - The snapshot update to replace the document with.
34
- * @param getMetadata (optional) - A function that returns the type of the root for a given key.
35
- */
36
27
  unstable_replaceDocument(
37
28
  snapshotUpdate: Uint8Array,
38
29
  getMetadata?: (key: string) => YjsRootType
39
30
  ): void;
40
- onStart(): Promise<void>;
41
31
  isReadOnly(connection: Connection): boolean;
42
- /**
43
- * Handle custom string messages from the client.
44
- * Override this method to implement custom message handling.
45
- * @param connection - The connection that sent the message
46
- * @param message - The custom message string (without the __YPS: prefix)
47
- */
48
32
  onCustomMessage(connection: Connection, message: string): void;
49
- /**
50
- * Send a custom string message to a specific connection.
51
- * @param connection - The connection to send the message to
52
- * @param message - The custom message string to send
53
- */
54
33
  sendCustomMessage(connection: Connection, message: string): void;
55
- /**
56
- * Broadcast a custom string message to all connected clients.
57
- * @param message - The custom message string to broadcast
58
- * @param excludeConnection - Optional connection to exclude from the broadcast
59
- */
60
34
  broadcastCustomMessage(message: string, excludeConnection?: Connection): void;
61
35
  handleMessage(connection: Connection, message: WSMessage): void;
62
- onMessage(conn: Connection, message: WSMessage): void;
63
- onClose(
64
- connection: Connection<unknown>,
65
- _code: number,
66
- _reason: string,
67
- _wasClean: boolean
68
- ): void | Promise<void>;
69
- onConnect(
70
- conn: Connection<unknown>,
71
- _ctx: ConnectionContext
72
- ): void | Promise<void>;
73
36
  }
37
+ interface YjsStatic {
38
+ callbackOptions: CallbackOptions;
39
+ }
40
+ declare function withYjs<TBase extends ServerClass>(
41
+ Base: TBase
42
+ ): TBase & YjsStatic & (new (...args: any[]) => YjsInstance);
43
+ declare const YServer: typeof Server &
44
+ YjsStatic &
45
+ (new (...args: any[]) => YjsInstance);
74
46
  //#endregion
75
- export { CallbackOptions, YServer };
47
+ export { CallbackOptions, YServer, YjsInstance, YjsStatic, withYjs };
76
48
  //# sourceMappingURL=index.d.ts.map