@coaction/yjs 1.4.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,590 +1,760 @@
1
- "use strict";
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
4
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
7
  var __getProtoOf = Object.getPrototypeOf;
7
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
9
  var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
19
18
  };
20
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
21
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
- // If the importer is in node compatibility mode or this is not an ESM
23
- // file that has been converted to a CommonJS file using a Babel-
24
- // compatible transform (i.e. "__esModule" has not been set), then set
25
- // "default" to the CommonJS "module.exports" for node compatibility.
26
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
- mod
28
- ));
29
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
-
31
- // index.ts
32
- var index_exports = {};
33
- __export(index_exports, {
34
- __unsafeTestOnly__: () => __unsafeTestOnly__,
35
- bindYjs: () => bindYjs,
36
- yjs: () => yjs
37
- });
38
- module.exports = __toCommonJS(index_exports);
39
-
40
- // src/index.ts
41
- var src_exports = {};
42
- __export(src_exports, {
43
- __unsafeTestOnly__: () => __unsafeTestOnly__,
44
- bindYjs: () => bindYjs,
45
- yjs: () => yjs
46
- });
47
- var Y = __toESM(require("yjs"));
48
- __reExport(src_exports, require("yjs"));
49
- var STATE_KEY = "state";
50
- var scheduleMicrotask = (callback) => {
51
- if (typeof queueMicrotask === "function") {
52
- queueMicrotask(callback);
53
- return;
54
- }
55
- Promise.resolve().then(callback);
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let coaction = require("coaction");
25
+ let yjs = require("yjs");
26
+ yjs = __toESM(yjs);
27
+ //#region packages/coaction-yjs/src/shared.ts
28
+ const scheduleMicrotask = (callback) => {
29
+ if (typeof queueMicrotask === "function") {
30
+ queueMicrotask(callback);
31
+ return;
32
+ }
33
+ Promise.resolve().then(callback);
34
+ };
35
+ const isUnsafeKey = (key) => key === "__proto__" || key === "prototype" || key === "constructor";
36
+ const isUnsafePathSegment = (segment) => typeof segment === "string" && isUnsafeKey(segment);
37
+ const cloneFallback = (value, seen = /* @__PURE__ */ new WeakMap()) => {
38
+ if (typeof value !== "object" || value === null) return value;
39
+ const cached = seen.get(value);
40
+ if (cached) return cached;
41
+ if (Array.isArray(value)) {
42
+ const next = [];
43
+ seen.set(value, next);
44
+ for (let index = 0; index < value.length; index += 1) if (Object.prototype.hasOwnProperty.call(value, index)) next[index] = cloneFallback(value[index], seen);
45
+ return next;
46
+ }
47
+ if (isPlainObject(value)) {
48
+ const next = Object.create(Object.getPrototypeOf(value));
49
+ seen.set(value, next);
50
+ for (const key of Reflect.ownKeys(value)) if (Object.prototype.propertyIsEnumerable.call(value, key)) {
51
+ if (typeof key === "string" && isUnsafeKey(key)) continue;
52
+ next[key] = cloneFallback(value[key], seen);
53
+ }
54
+ return next;
55
+ }
56
+ return JSON.parse(JSON.stringify(value));
56
57
  };
57
58
  function clone(value) {
58
- if (typeof structuredClone === "function") {
59
- return structuredClone(value);
60
- }
61
- return JSON.parse(JSON.stringify(value));
59
+ if (Array.isArray(value) || isPlainObject(value)) return cloneFallback(value);
60
+ if (typeof structuredClone === "function") try {
61
+ return structuredClone(value);
62
+ } catch {
63
+ return cloneFallback(value);
64
+ }
65
+ return cloneFallback(value);
62
66
  }
63
67
  function isPlainObject(value) {
64
- if (typeof value !== "object" || value === null) {
65
- return false;
66
- }
67
- const prototype = Object.getPrototypeOf(value);
68
- return prototype === Object.prototype || prototype === null;
68
+ if (typeof value !== "object" || value === null) return false;
69
+ const prototype = Object.getPrototypeOf(value);
70
+ return prototype === Object.prototype || prototype === null;
71
+ }
72
+ function sanitizePlainValue(value, seen = /* @__PURE__ */ new WeakMap()) {
73
+ if (typeof value !== "object" || value === null) return value;
74
+ const cached = seen.get(value);
75
+ if (cached) return cached;
76
+ if (Array.isArray(value)) {
77
+ const next = [];
78
+ seen.set(value, next);
79
+ for (let index = 0; index < value.length; index += 1) if (Object.prototype.hasOwnProperty.call(value, index)) next[index] = sanitizePlainValue(value[index], seen);
80
+ return next;
81
+ }
82
+ if (!isPlainObject(value)) return clone(value);
83
+ const next = {};
84
+ seen.set(value, next);
85
+ for (const key of Object.keys(value)) {
86
+ if (isUnsafeKey(key)) continue;
87
+ next[key] = sanitizePlainValue(value[key], seen);
88
+ }
89
+ return next;
69
90
  }
91
+ //#endregion
92
+ //#region packages/coaction-yjs/src/yjsValue.ts
70
93
  function toPlainObject(value) {
71
- const next = {};
72
- value.forEach((item, key) => {
73
- next[key] = toPlainValue(item);
74
- });
75
- return next;
94
+ const next = {};
95
+ value.forEach((item, key) => {
96
+ if (isUnsafeKey(key)) return;
97
+ next[key] = toPlainValue(item);
98
+ });
99
+ return next;
76
100
  }
77
101
  function toPlainArray(value) {
78
- return value.toArray().map((item) => toPlainValue(item));
102
+ return value.toArray().map((item) => toPlainValue(item));
79
103
  }
80
104
  function toPlainValue(value) {
81
- if (value instanceof Y.Map) {
82
- return toPlainObject(value);
83
- }
84
- if (value instanceof Y.Array) {
85
- return toPlainArray(value);
86
- }
87
- return value;
105
+ if (value instanceof yjs.Map) return toPlainObject(value);
106
+ if (value instanceof yjs.Array) return toPlainArray(value);
107
+ if (value instanceof yjs.AbstractType) return toPlainValue(value.toJSON());
108
+ if (Array.isArray(value) || isPlainObject(value)) return sanitizePlainValue(value);
109
+ return value;
88
110
  }
89
111
  function createYMap(value) {
90
- const next = new Y.Map();
91
- for (const [key, item] of Object.entries(value)) {
92
- next.set(key, toYValue(item));
93
- }
94
- return next;
112
+ const next = new yjs.Map();
113
+ for (const [key, item] of Object.entries(value)) {
114
+ if (isUnsafeKey(key)) continue;
115
+ next.set(key, toYValue(item));
116
+ }
117
+ return next;
95
118
  }
96
119
  function createYArray(value) {
97
- const next = new Y.Array();
98
- if (value.length > 0) {
99
- next.insert(
100
- 0,
101
- value.map((item) => toYValue(item))
102
- );
103
- }
104
- return next;
120
+ const next = new yjs.Array();
121
+ if (value.length > 0) next.insert(0, value.map((item) => toYValue(item)));
122
+ return next;
105
123
  }
106
124
  function toYValue(value) {
107
- if (Array.isArray(value)) {
108
- return createYArray(value);
109
- }
110
- if (isPlainObject(value)) {
111
- return createYMap(value);
112
- }
113
- if (typeof value === "object" && value !== null) {
114
- return clone(value);
115
- }
116
- return value;
117
- }
118
- function isEqualValue(left, right) {
119
- if (Object.is(left, right)) {
120
- return true;
121
- }
122
- if (Array.isArray(left) && Array.isArray(right)) {
123
- if (left.length !== right.length) {
124
- return false;
125
- }
126
- for (let index = 0; index < left.length; index += 1) {
127
- if (!isEqualValue(left[index], right[index])) {
128
- return false;
129
- }
130
- }
131
- return true;
132
- }
133
- if (isPlainObject(left) && isPlainObject(right)) {
134
- const leftKeys = Object.keys(left);
135
- const rightKeys = Object.keys(right);
136
- if (leftKeys.length !== rightKeys.length) {
137
- return false;
138
- }
139
- for (const key of leftKeys) {
140
- if (!Object.prototype.hasOwnProperty.call(right, key)) {
141
- return false;
142
- }
143
- if (!isEqualValue(left[key], right[key])) {
144
- return false;
145
- }
146
- }
147
- return true;
148
- }
149
- return false;
150
- }
151
- function syncObjectToYMap(target, previous, source) {
152
- const keys = /* @__PURE__ */ new Set([...Object.keys(previous), ...Object.keys(source)]);
153
- for (const key of keys) {
154
- const hasPrevious = Object.prototype.hasOwnProperty.call(previous, key);
155
- const hasNext = Object.prototype.hasOwnProperty.call(source, key);
156
- if (!hasNext) {
157
- target.delete(key);
158
- continue;
159
- }
160
- const previousValue = hasPrevious ? previous[key] : void 0;
161
- const nextValue = source[key];
162
- if (hasPrevious && isEqualValue(previousValue, nextValue)) {
163
- continue;
164
- }
165
- const current = target.get(key);
166
- if (Array.isArray(nextValue)) {
167
- if (Array.isArray(previousValue) && current instanceof Y.Array) {
168
- syncArrayToYArray(current, previousValue, nextValue);
169
- } else {
170
- target.set(key, createYArray(nextValue));
171
- }
172
- continue;
173
- }
174
- if (isPlainObject(nextValue)) {
175
- if (isPlainObject(previousValue) && current instanceof Y.Map) {
176
- syncObjectToYMap(current, previousValue, nextValue);
177
- } else {
178
- target.set(key, createYMap(nextValue));
179
- }
180
- continue;
181
- }
182
- const normalized = typeof nextValue === "object" && nextValue !== null ? clone(nextValue) : nextValue;
183
- if (!Object.is(current, normalized)) {
184
- target.set(key, normalized);
185
- }
186
- }
187
- }
188
- function syncArrayToYArray(target, previous, source) {
189
- if (target.length > source.length) {
190
- target.delete(source.length, target.length - source.length);
191
- }
192
- const maxLength = Math.max(previous.length, source.length);
193
- for (let index = 0; index < maxLength; index += 1) {
194
- const hasPrevious = index < previous.length;
195
- const hasNext = index < source.length;
196
- if (!hasNext) {
197
- continue;
198
- }
199
- const previousValue = hasPrevious ? previous[index] : void 0;
200
- const nextValue = source[index];
201
- if (hasPrevious && isEqualValue(previousValue, nextValue)) {
202
- continue;
203
- }
204
- if (index >= target.length) {
205
- target.insert(index, [toYValue(nextValue)]);
206
- continue;
207
- }
208
- const current = target.get(index);
209
- if (Array.isArray(nextValue)) {
210
- if (Array.isArray(previousValue) && current instanceof Y.Array) {
211
- syncArrayToYArray(current, previousValue, nextValue);
212
- } else {
213
- target.delete(index, 1);
214
- target.insert(index, [createYArray(nextValue)]);
215
- }
216
- continue;
217
- }
218
- if (isPlainObject(nextValue)) {
219
- if (isPlainObject(previousValue) && current instanceof Y.Map) {
220
- syncObjectToYMap(current, previousValue, nextValue);
221
- } else {
222
- target.delete(index, 1);
223
- target.insert(index, [createYMap(nextValue)]);
224
- }
225
- continue;
226
- }
227
- const normalized = typeof nextValue === "object" && nextValue !== null ? clone(nextValue) : nextValue;
228
- if (!Object.is(current, normalized)) {
229
- target.delete(index, 1);
230
- target.insert(index, [normalized]);
231
- }
232
- }
125
+ if (Array.isArray(value)) return createYArray(value);
126
+ if (isPlainObject(value)) return createYMap(value);
127
+ if (typeof value === "object" && value !== null) return clone(value);
128
+ return value;
233
129
  }
130
+ //#endregion
131
+ //#region packages/coaction-yjs/src/remoteOperations.ts
234
132
  function isSetStateReentryError(error) {
235
- return error instanceof Error && error.message === "setState cannot be called within the updater";
133
+ return error instanceof Error && error.message === "setState cannot be called within the updater";
236
134
  }
237
135
  function cloneForStore(value) {
238
- if (typeof value === "object" && value !== null) {
239
- return clone(value);
240
- }
241
- return value;
136
+ if (typeof value === "object" && value !== null) return sanitizePlainValue(value);
137
+ return value;
242
138
  }
243
139
  function toPathKey(path) {
244
- return path.map((segment) => `${typeof segment}:${String(segment)}`).join("|");
140
+ return path.map((segment) => `${typeof segment}:${String(segment)}`).join("|");
141
+ }
142
+ function toArrayIndex(segment) {
143
+ const index = typeof segment === "number" ? segment : Number.parseInt(segment, 10);
144
+ if (!Number.isInteger(index) || index < 0) return;
145
+ if (typeof segment === "string" && String(index) !== segment) return;
146
+ return index;
245
147
  }
246
148
  function compactOperations(operations) {
247
- const deduplicated = /* @__PURE__ */ new Map();
248
- for (const operation of operations) {
249
- const key = toPathKey(operation.path);
250
- if (deduplicated.has(key)) {
251
- deduplicated.delete(key);
252
- }
253
- deduplicated.set(key, operation);
254
- }
255
- return Array.from(deduplicated.values()).sort(
256
- (left, right) => left.path.length - right.path.length
257
- );
149
+ const deduplicated = /* @__PURE__ */ new Map();
150
+ for (const operation of operations) {
151
+ const key = toPathKey(operation.path);
152
+ if (deduplicated.has(key)) deduplicated.delete(key);
153
+ deduplicated.set(key, operation);
154
+ }
155
+ return Array.from(deduplicated.values()).sort((left, right) => left.path.length - right.path.length);
258
156
  }
259
157
  function getYValueAtPath(root, path) {
260
- let current = root;
261
- for (const segment of path) {
262
- if (current instanceof Y.Map) {
263
- current = current.get(String(segment));
264
- continue;
265
- }
266
- if (current instanceof Y.Array) {
267
- const index = typeof segment === "number" ? segment : Number.parseInt(segment, 10);
268
- if (!Number.isInteger(index)) {
269
- return void 0;
270
- }
271
- current = current.get(index);
272
- continue;
273
- }
274
- return void 0;
275
- }
276
- return current;
158
+ let current = root;
159
+ for (const segment of path) {
160
+ if (current instanceof yjs.Map) {
161
+ current = current.get(String(segment));
162
+ continue;
163
+ }
164
+ if (current instanceof yjs.Array) {
165
+ const index = toArrayIndex(segment);
166
+ if (typeof index === "undefined") return;
167
+ current = current.get(index);
168
+ continue;
169
+ }
170
+ return;
171
+ }
172
+ return current;
277
173
  }
278
174
  function setAtPath(target, path, value) {
279
- if (path.length === 0) {
280
- return;
281
- }
282
- let current = target;
283
- for (let index = 0; index < path.length - 1; index += 1) {
284
- const segment = path[index];
285
- const nextSegment = path[index + 1];
286
- const nextValue = current[segment];
287
- if (typeof nextValue !== "object" || nextValue === null) {
288
- current[segment] = typeof nextSegment === "number" ? [] : {};
289
- }
290
- current = current[segment];
291
- }
292
- const leaf = path[path.length - 1];
293
- current[leaf] = cloneForStore(value);
175
+ if (path.length === 0) return;
176
+ if (path.some(isUnsafePathSegment)) return;
177
+ let current = target;
178
+ for (let index = 0; index < path.length - 1; index += 1) {
179
+ const segment = path[index];
180
+ const nextSegment = path[index + 1];
181
+ const segmentIndex = Array.isArray(current) ? toArrayIndex(segment) : void 0;
182
+ const targetKey = typeof segmentIndex === "undefined" ? segment : segmentIndex;
183
+ const nextValue = current[targetKey];
184
+ const needsArray = typeof nextSegment === "number" || Array.isArray(nextValue) && typeof toArrayIndex(nextSegment) !== "undefined";
185
+ if (typeof nextValue !== "object" || nextValue === null || (needsArray ? !Array.isArray(nextValue) : Array.isArray(nextValue))) current[targetKey] = typeof nextSegment === "number" ? [] : {};
186
+ current = current[targetKey];
187
+ }
188
+ const leaf = path[path.length - 1];
189
+ const leafIndex = Array.isArray(current) ? toArrayIndex(leaf) : void 0;
190
+ current[typeof leafIndex === "undefined" ? leaf : leafIndex] = cloneForStore(value);
294
191
  }
295
192
  function deleteAtPath(target, path) {
296
- if (path.length === 0) {
297
- return;
298
- }
299
- let current = target;
300
- for (let index = 0; index < path.length - 1; index += 1) {
301
- current = current[path[index]];
302
- if (typeof current !== "object" || current === null) {
303
- return;
304
- }
305
- }
306
- const leaf = path[path.length - 1];
307
- if (Array.isArray(current) && typeof leaf === "number") {
308
- if (leaf >= 0 && leaf < current.length) {
309
- current.splice(leaf, 1);
310
- }
311
- return;
312
- }
313
- delete current[leaf];
193
+ if (path.length === 0) return;
194
+ if (path.some(isUnsafePathSegment)) return;
195
+ let current = target;
196
+ for (let index = 0; index < path.length - 1; index += 1) {
197
+ const segment = path[index];
198
+ const segmentIndex = Array.isArray(current) ? toArrayIndex(segment) : void 0;
199
+ current = current[typeof segmentIndex === "undefined" ? segment : segmentIndex];
200
+ if (typeof current !== "object" || current === null) return;
201
+ }
202
+ const leaf = path[path.length - 1];
203
+ if (Array.isArray(current)) {
204
+ const leafIndex = toArrayIndex(leaf);
205
+ if (typeof leafIndex !== "undefined" && leafIndex >= 0 && leafIndex < current.length) current.splice(leafIndex, 1);
206
+ return;
207
+ }
208
+ delete current[leaf];
314
209
  }
315
210
  function collectRemoteOperations(events, stateMap) {
316
- const operations = [];
317
- for (const event of events) {
318
- if (event instanceof Y.YMapEvent) {
319
- for (const changedKey of event.keysChanged) {
320
- const path = [...event.path, changedKey];
321
- const keyChange = event.changes.keys.get(changedKey);
322
- if (keyChange?.action === "delete") {
323
- operations.push({
324
- type: "delete",
325
- path
326
- });
327
- continue;
328
- }
329
- operations.push({
330
- type: "set",
331
- path,
332
- value: toPlainValue(getYValueAtPath(stateMap, path))
333
- });
334
- }
335
- continue;
336
- }
337
- if (event instanceof Y.YArrayEvent) {
338
- const path = [...event.path];
339
- operations.push({
340
- type: "set",
341
- path,
342
- value: toPlainValue(getYValueAtPath(stateMap, path))
343
- });
344
- }
345
- }
346
- return operations;
211
+ const operations = [];
212
+ for (const event of events) {
213
+ if (event instanceof yjs.YMapEvent) {
214
+ for (const changedKey of event.keysChanged) {
215
+ const path = [...event.path, changedKey];
216
+ if (path.some(isUnsafePathSegment)) continue;
217
+ if (event.changes.keys.get(changedKey)?.action === "delete") {
218
+ operations.push({
219
+ type: "delete",
220
+ path
221
+ });
222
+ continue;
223
+ }
224
+ operations.push({
225
+ type: "set",
226
+ path,
227
+ value: toPlainValue(getYValueAtPath(stateMap, path))
228
+ });
229
+ }
230
+ continue;
231
+ }
232
+ if (event instanceof yjs.YArrayEvent) {
233
+ const path = [...event.path];
234
+ operations.push({
235
+ type: "set",
236
+ path,
237
+ value: toPlainValue(getYValueAtPath(stateMap, path))
238
+ });
239
+ }
240
+ }
241
+ return operations;
347
242
  }
348
- var __unsafeTestOnly__ = {
349
- getYValueAtPath: (root, path) => getYValueAtPath(root, path),
350
- setAtPath: (target, path, value) => {
351
- setAtPath(target, path, value);
352
- },
353
- deleteAtPath: (target, path) => {
354
- deleteAtPath(target, path);
355
- }
243
+ //#endregion
244
+ //#region packages/coaction-yjs/src/sync.ts
245
+ function isEqualValue(left, right) {
246
+ if (Object.is(left, right)) return true;
247
+ if (Array.isArray(left) && Array.isArray(right)) {
248
+ if (left.length !== right.length) return false;
249
+ for (let index = 0; index < left.length; index += 1) if (!isEqualValue(left[index], right[index])) return false;
250
+ return true;
251
+ }
252
+ if (isPlainObject(left) && isPlainObject(right)) {
253
+ const leftKeys = Object.keys(left);
254
+ const rightKeys = Object.keys(right);
255
+ if (leftKeys.length !== rightKeys.length) return false;
256
+ for (const key of leftKeys) {
257
+ if (!Object.prototype.hasOwnProperty.call(right, key)) return false;
258
+ if (!isEqualValue(left[key], right[key])) return false;
259
+ }
260
+ return true;
261
+ }
262
+ return false;
263
+ }
264
+ function syncObjectToYMap(target, previous, source) {
265
+ target.forEach((_value, key) => {
266
+ if (isUnsafeKey(key)) target.delete(key);
267
+ });
268
+ const keys = /* @__PURE__ */ new Set([...Object.keys(previous), ...Object.keys(source)]);
269
+ for (const key of keys) {
270
+ if (isUnsafeKey(key)) {
271
+ target.delete(key);
272
+ continue;
273
+ }
274
+ const hasPrevious = Object.prototype.hasOwnProperty.call(previous, key);
275
+ if (!Object.prototype.hasOwnProperty.call(source, key)) {
276
+ target.delete(key);
277
+ continue;
278
+ }
279
+ const previousValue = hasPrevious ? previous[key] : void 0;
280
+ const nextValue = source[key];
281
+ if (hasPrevious && isEqualValue(previousValue, nextValue)) continue;
282
+ const current = target.get(key);
283
+ if (Array.isArray(nextValue)) {
284
+ if (Array.isArray(previousValue) && current instanceof yjs.Array) syncArrayToYArray(current, previousValue, nextValue);
285
+ else target.set(key, createYArray(nextValue));
286
+ continue;
287
+ }
288
+ if (isPlainObject(nextValue)) {
289
+ if (isPlainObject(previousValue) && current instanceof yjs.Map) syncObjectToYMap(current, previousValue, nextValue);
290
+ else target.set(key, createYMap(nextValue));
291
+ continue;
292
+ }
293
+ const normalized = typeof nextValue === "object" && nextValue !== null ? clone(nextValue) : nextValue;
294
+ if (!Object.is(current, normalized)) target.set(key, normalized);
295
+ }
296
+ }
297
+ function syncArrayToYArray(target, previous, source) {
298
+ if (target.length > source.length) target.delete(source.length, target.length - source.length);
299
+ const maxLength = Math.max(previous.length, source.length);
300
+ for (let index = 0; index < maxLength; index += 1) {
301
+ const hasPrevious = index < previous.length;
302
+ if (!(index < source.length)) continue;
303
+ const previousValue = hasPrevious ? previous[index] : void 0;
304
+ const nextValue = source[index];
305
+ if (hasPrevious && isEqualValue(previousValue, nextValue)) continue;
306
+ if (index >= target.length) {
307
+ target.insert(index, [toYValue(nextValue)]);
308
+ continue;
309
+ }
310
+ const current = target.get(index);
311
+ if (Array.isArray(nextValue)) {
312
+ if (Array.isArray(previousValue) && current instanceof yjs.Array) syncArrayToYArray(current, previousValue, nextValue);
313
+ else {
314
+ target.delete(index, 1);
315
+ target.insert(index, [createYArray(nextValue)]);
316
+ }
317
+ continue;
318
+ }
319
+ if (isPlainObject(nextValue)) {
320
+ if (isPlainObject(previousValue) && current instanceof yjs.Map) syncObjectToYMap(current, previousValue, nextValue);
321
+ else {
322
+ target.delete(index, 1);
323
+ target.insert(index, [createYMap(nextValue)]);
324
+ }
325
+ continue;
326
+ }
327
+ const normalized = typeof nextValue === "object" && nextValue !== null ? clone(nextValue) : nextValue;
328
+ if (!Object.is(current, normalized)) {
329
+ target.delete(index, 1);
330
+ target.insert(index, [normalized]);
331
+ }
332
+ }
333
+ }
334
+ //#endregion
335
+ //#region packages/coaction-yjs/src/index.ts
336
+ const STATE_KEY = "state";
337
+ const historySuppressionSymbol = Symbol.for("coaction.history.suppress");
338
+ const runWithoutHistoryRecording = (store, callback) => {
339
+ const runner = store[historySuppressionSymbol];
340
+ return typeof runner === "function" ? runner(callback) : callback();
341
+ };
342
+ const getOwnEnumerableKeys = (value) => Reflect.ownKeys(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key) && !(typeof key === "string" && isUnsafeKey(key)));
343
+ const formatPropertyPath = (path) => path.length ? path.map((key) => String(key)).join(".") : "<root>";
344
+ var YjsSerializableStateError = class extends Error {};
345
+ const isYjsSerializableStateError = (error) => error instanceof YjsSerializableStateError;
346
+ const isArrayIndexKey = (key, length) => {
347
+ if (key === "") return false;
348
+ const index = Number(key);
349
+ return Number.isInteger(index) && index >= 0 && index < length && String(index) === key;
350
+ };
351
+ const findYjsStateViolation = (value, path = [], ancestors = /* @__PURE__ */ new WeakSet()) => {
352
+ switch (typeof value) {
353
+ case "symbol": return {
354
+ type: "symbol-value",
355
+ path
356
+ };
357
+ case "function": return {
358
+ type: "function",
359
+ path
360
+ };
361
+ default: break;
362
+ }
363
+ if (typeof value !== "object" || value === null) return;
364
+ if (ancestors.has(value)) return {
365
+ type: "circular-reference",
366
+ path
367
+ };
368
+ if (Array.isArray(value)) {
369
+ ancestors.add(value);
370
+ for (let index = 0; index < value.length; index += 1) if (!Object.prototype.hasOwnProperty.call(value, index)) return {
371
+ type: "array-hole",
372
+ path: [...path, index]
373
+ };
374
+ for (const key of getOwnEnumerableKeys(value)) {
375
+ const nextPath = [...path, key];
376
+ if (typeof key === "symbol") return {
377
+ type: "symbol-key",
378
+ path: nextPath
379
+ };
380
+ if (!isArrayIndexKey(key, value.length)) return {
381
+ type: "array-property",
382
+ path: nextPath
383
+ };
384
+ const violation = findYjsStateViolation(value[Number(key)], nextPath, ancestors);
385
+ if (violation) return violation;
386
+ }
387
+ ancestors.delete(value);
388
+ return;
389
+ }
390
+ if (!isPlainObject(value)) return {
391
+ type: "non-plain-object",
392
+ path
393
+ };
394
+ ancestors.add(value);
395
+ for (const key of getOwnEnumerableKeys(value)) {
396
+ const nextPath = [...path, key];
397
+ if (typeof key === "symbol") return {
398
+ type: "symbol-key",
399
+ path: nextPath
400
+ };
401
+ const child = value[key];
402
+ const violation = findYjsStateViolation(child, nextPath, ancestors);
403
+ if (violation) return violation;
404
+ }
405
+ ancestors.delete(value);
406
+ };
407
+ const assertYjsSerializableState = (state, path = []) => {
408
+ const violation = findYjsStateViolation(state, path);
409
+ if (!violation) return;
410
+ if (violation.type === "symbol-key") throw new YjsSerializableStateError(`Yjs binding does not support symbol-keyed state because Y.Map keys are strings. Found symbol key at ${formatPropertyPath(violation.path)}.`);
411
+ if (violation.type === "symbol-value") throw new YjsSerializableStateError(`Yjs binding does not support symbol-valued state because symbols cannot be cloned into Yjs documents. Found symbol value at ${formatPropertyPath(violation.path)}.`);
412
+ throw new YjsSerializableStateError(`Yjs binding does not support ${violation.type} state because only plain objects, arrays, and primitive values round-trip through Yjs updates. Found unsupported value at ${formatPropertyPath(violation.path)}.`);
413
+ };
414
+ const assertRemoteOperationsSerializable = (operations) => {
415
+ for (const operation of operations) if (operation.type === "set") assertYjsSerializableState(operation.value, operation.path);
416
+ };
417
+ const createRootReplacementPatches = (currentState, nextState) => {
418
+ const patches = [];
419
+ const inversePatches = [];
420
+ const nextKeys = new Set(getOwnEnumerableKeys(nextState));
421
+ for (const key of getOwnEnumerableKeys(currentState)) {
422
+ if (typeof key === "symbol" || nextKeys.has(key)) continue;
423
+ patches.push({
424
+ op: "remove",
425
+ path: [key]
426
+ });
427
+ inversePatches.push({
428
+ op: "add",
429
+ path: [key],
430
+ value: currentState[key]
431
+ });
432
+ }
433
+ for (const key of nextKeys) {
434
+ if (typeof key === "symbol") continue;
435
+ if (!Object.prototype.hasOwnProperty.call(currentState, key)) {
436
+ patches.push({
437
+ op: "add",
438
+ path: [key],
439
+ value: nextState[key]
440
+ });
441
+ inversePatches.push({
442
+ op: "remove",
443
+ path: [key]
444
+ });
445
+ continue;
446
+ }
447
+ if (Object.is(currentState[key], nextState[key])) continue;
448
+ patches.push({
449
+ op: "replace",
450
+ path: [key],
451
+ value: nextState[key]
452
+ });
453
+ inversePatches.push({
454
+ op: "replace",
455
+ path: [key],
456
+ value: currentState[key]
457
+ });
458
+ }
459
+ return {
460
+ patches,
461
+ inversePatches
462
+ };
463
+ };
464
+ const __unsafeTestOnly__ = {
465
+ getYValueAtPath: (root, path) => getYValueAtPath(root, path),
466
+ setAtPath: (target, path, value) => {
467
+ setAtPath(target, path, value);
468
+ },
469
+ deleteAtPath: (target, path) => {
470
+ deleteAtPath(target, path);
471
+ }
356
472
  };
357
- var bindYjs = (store, options = {}) => {
358
- if (store.share === "client") {
359
- throw new Error("Yjs binding is not supported in client store mode.");
360
- }
361
- const doc = options.doc ?? new Y.Doc();
362
- const key = options.key ?? `coaction:${store.name}`;
363
- const map = doc.getMap(key);
364
- const localOrigin = /* @__PURE__ */ Symbol(`coaction-yjs:${store.name}`);
365
- let destroyed = false;
366
- let syncingFromYjs = false;
367
- let lastSyncedState = (() => {
368
- const pureState = clone(store.getPureState());
369
- return isPlainObject(pureState) ? pureState : {};
370
- })();
371
- let flushScheduled = false;
372
- let pendingSnapshot = null;
373
- let pendingOperations = [];
374
- const applyRemoteState = (state) => {
375
- const next = clone(state);
376
- syncingFromYjs = true;
377
- try {
378
- store.setState(next);
379
- const pureState = clone(store.getPureState());
380
- lastSyncedState = isPlainObject(pureState) ? pureState : {};
381
- } finally {
382
- syncingFromYjs = false;
383
- }
384
- };
385
- const applyRemoteOperations = (operations) => {
386
- if (operations.length === 0) {
387
- return;
388
- }
389
- syncingFromYjs = true;
390
- try {
391
- store.setState((draft) => {
392
- const mutableDraft = draft;
393
- for (const operation of operations) {
394
- if (operation.type === "set") {
395
- setAtPath(mutableDraft, operation.path, operation.value);
396
- } else {
397
- deleteAtPath(mutableDraft, operation.path);
398
- }
399
- }
400
- });
401
- const pureState = clone(store.getPureState());
402
- lastSyncedState = isPlainObject(pureState) ? pureState : {};
403
- } finally {
404
- syncingFromYjs = false;
405
- }
406
- };
407
- const getStateMap = () => {
408
- const state = map.get(STATE_KEY);
409
- if (state instanceof Y.Map) {
410
- return state;
411
- }
412
- return null;
413
- };
414
- const scheduleFlushFromYjs = () => {
415
- if (destroyed || flushScheduled) {
416
- return;
417
- }
418
- flushScheduled = true;
419
- scheduleMicrotask(flushFromYjs);
420
- };
421
- const flushFromYjs = () => {
422
- flushScheduled = false;
423
- if (destroyed) {
424
- return;
425
- }
426
- if (pendingSnapshot) {
427
- const snapshot = pendingSnapshot;
428
- pendingSnapshot = null;
429
- pendingOperations = [];
430
- try {
431
- applyRemoteState(snapshot);
432
- } catch (error) {
433
- if (isSetStateReentryError(error)) {
434
- pendingSnapshot = snapshot;
435
- setTimeout(scheduleFlushFromYjs, 0);
436
- return;
437
- }
438
- throw error;
439
- }
440
- }
441
- if (pendingOperations.length === 0) {
442
- return;
443
- }
444
- const operations = compactOperations(pendingOperations);
445
- pendingOperations = [];
446
- try {
447
- applyRemoteOperations(operations);
448
- } catch (error) {
449
- if (isSetStateReentryError(error)) {
450
- pendingOperations = [...operations, ...pendingOperations];
451
- setTimeout(scheduleFlushFromYjs, 0);
452
- return;
453
- }
454
- throw error;
455
- }
456
- };
457
- const enqueueSnapshot = (snapshot) => {
458
- pendingSnapshot = snapshot;
459
- pendingOperations = [];
460
- scheduleFlushFromYjs();
461
- };
462
- const enqueueOperations = (operations) => {
463
- if (operations.length === 0) {
464
- return;
465
- }
466
- if (!pendingSnapshot) {
467
- pendingOperations.push(...operations);
468
- }
469
- scheduleFlushFromYjs();
470
- };
471
- const syncNow = () => {
472
- if (destroyed || syncingFromYjs) {
473
- return;
474
- }
475
- const pureState = clone(store.getPureState());
476
- if (!isPlainObject(pureState)) {
477
- return;
478
- }
479
- doc.transact(() => {
480
- syncObjectToYMap(stateMap, lastSyncedState, pureState);
481
- }, localOrigin);
482
- lastSyncedState = pureState;
483
- };
484
- const stateObserver = (events, transaction) => {
485
- if (transaction.origin === localOrigin) {
486
- return;
487
- }
488
- enqueueOperations(collectRemoteOperations(events, stateMap));
489
- };
490
- let stateMap;
491
- const existingStateMap = getStateMap();
492
- if (existingStateMap) {
493
- stateMap = existingStateMap;
494
- applyRemoteState(toPlainObject(stateMap));
495
- } else {
496
- const currentState = map.get(STATE_KEY);
497
- if (isPlainObject(currentState)) {
498
- stateMap = createYMap(currentState);
499
- doc.transact(() => {
500
- map.set(STATE_KEY, stateMap);
501
- }, localOrigin);
502
- applyRemoteState(currentState);
503
- } else {
504
- const pureState = clone(store.getPureState());
505
- stateMap = createYMap(isPlainObject(pureState) ? pureState : {});
506
- doc.transact(() => {
507
- map.set(STATE_KEY, stateMap);
508
- }, localOrigin);
509
- }
510
- }
511
- stateMap.observeDeep(stateObserver);
512
- const observer = (event) => {
513
- if (event.transaction.origin === localOrigin) {
514
- return;
515
- }
516
- if (!event.keysChanged.has(STATE_KEY)) {
517
- return;
518
- }
519
- const nextStateMap = getStateMap();
520
- if (nextStateMap) {
521
- if (stateMap !== nextStateMap) {
522
- stateMap.unobserveDeep(stateObserver);
523
- stateMap = nextStateMap;
524
- stateMap.observeDeep(stateObserver);
525
- }
526
- enqueueSnapshot(toPlainObject(nextStateMap));
527
- return;
528
- }
529
- const currentState = map.get(STATE_KEY);
530
- if (isPlainObject(currentState)) {
531
- const migrated = createYMap(currentState);
532
- doc.transact(() => {
533
- map.set(STATE_KEY, migrated);
534
- }, localOrigin);
535
- if (stateMap !== migrated) {
536
- stateMap.unobserveDeep(stateObserver);
537
- stateMap = migrated;
538
- stateMap.observeDeep(stateObserver);
539
- }
540
- enqueueSnapshot(currentState);
541
- }
542
- };
543
- map.observe(observer);
544
- const unsubscribe = store.subscribe(() => {
545
- syncNow();
546
- });
547
- const binding = {
548
- doc,
549
- map,
550
- syncNow,
551
- destroy: () => {
552
- if (destroyed) {
553
- return;
554
- }
555
- destroyed = true;
556
- unsubscribe();
557
- map.unobserve(observer);
558
- stateMap.unobserveDeep(stateObserver);
559
- if (!options.doc) {
560
- doc.destroy();
561
- }
562
- }
563
- };
564
- if (process.env.NODE_ENV === "test") {
565
- binding.__unsafeTestOnly__ = {
566
- applyRemoteOperations: (operations) => {
567
- applyRemoteOperations(operations);
568
- }
569
- };
570
- }
571
- return binding;
473
+ const bindYjs = (store, options = {}) => {
474
+ if (store.share === "client") throw new Error("Yjs binding is not supported in client store mode.");
475
+ const doc = options.doc ?? new yjs.Doc();
476
+ const key = options.key ?? `coaction:${store.name}`;
477
+ const map = doc.getMap(key);
478
+ const localOrigin = Symbol(`coaction-yjs:${store.name}`);
479
+ let destroyed = false;
480
+ let syncingFromYjs = false;
481
+ assertYjsSerializableState(store.getPureState());
482
+ let lastSyncedState = (() => {
483
+ const pureState = clone(store.getPureState());
484
+ return isPlainObject(pureState) ? pureState : {};
485
+ })();
486
+ let flushScheduled = false;
487
+ let pendingSnapshot = null;
488
+ let pendingOperations = [];
489
+ const restoreLastSyncedState = () => {
490
+ syncingFromYjs = true;
491
+ try {
492
+ store.apply(lastSyncedState);
493
+ } finally {
494
+ syncingFromYjs = false;
495
+ }
496
+ };
497
+ const applyRemoteState = (state) => {
498
+ assertYjsSerializableState(state);
499
+ const next = sanitizePlainValue(state);
500
+ syncingFromYjs = true;
501
+ try {
502
+ if (store.share === "main") store.setState(next, () => {
503
+ const { patches, inversePatches } = createRootReplacementPatches(store.getPureState(), next);
504
+ const finalPatches = store.patch ? store.patch({
505
+ patches,
506
+ inversePatches
507
+ }) : {
508
+ patches,
509
+ inversePatches
510
+ };
511
+ if (finalPatches.patches.length) store.apply(store.getPureState(), finalPatches.patches);
512
+ return [
513
+ store.getPureState(),
514
+ finalPatches.patches,
515
+ finalPatches.inversePatches
516
+ ];
517
+ });
518
+ else {
519
+ store.setState(null);
520
+ store.apply(next);
521
+ }
522
+ const pureState = clone(store.getPureState());
523
+ lastSyncedState = isPlainObject(pureState) ? pureState : {};
524
+ } finally {
525
+ syncingFromYjs = false;
526
+ }
527
+ };
528
+ const applyRemoteOperations = (operations) => {
529
+ if (operations.length === 0) return;
530
+ assertRemoteOperationsSerializable(operations);
531
+ syncingFromYjs = true;
532
+ try {
533
+ store.setState((draft) => {
534
+ const mutableDraft = draft;
535
+ for (const operation of operations) if (operation.type === "set") setAtPath(mutableDraft, operation.path, operation.value);
536
+ else deleteAtPath(mutableDraft, operation.path);
537
+ });
538
+ const pureState = clone(store.getPureState());
539
+ lastSyncedState = isPlainObject(pureState) ? pureState : {};
540
+ } finally {
541
+ syncingFromYjs = false;
542
+ }
543
+ };
544
+ const getStateMap = () => {
545
+ const state = map.get(STATE_KEY);
546
+ if (state instanceof yjs.Map) return state;
547
+ return null;
548
+ };
549
+ const scheduleFlushFromYjs = () => {
550
+ if (destroyed || flushScheduled) return;
551
+ flushScheduled = true;
552
+ scheduleMicrotask(flushFromYjs);
553
+ };
554
+ const flushFromYjs = () => {
555
+ flushScheduled = false;
556
+ if (destroyed) return;
557
+ if (pendingSnapshot) {
558
+ const snapshot = pendingSnapshot;
559
+ pendingSnapshot = null;
560
+ pendingOperations = [];
561
+ try {
562
+ applyRemoteState(snapshot);
563
+ } catch (error) {
564
+ if (isSetStateReentryError(error)) {
565
+ pendingSnapshot = snapshot;
566
+ setTimeout(scheduleFlushFromYjs, 0);
567
+ return;
568
+ }
569
+ if (isYjsSerializableStateError(error)) {
570
+ restoreRootState();
571
+ return;
572
+ }
573
+ throw error;
574
+ }
575
+ }
576
+ if (pendingOperations.length === 0) return;
577
+ const operations = compactOperations(pendingOperations);
578
+ pendingOperations = [];
579
+ try {
580
+ applyRemoteOperations(operations);
581
+ } catch (error) {
582
+ if (isSetStateReentryError(error)) {
583
+ pendingOperations = [...operations, ...pendingOperations];
584
+ setTimeout(scheduleFlushFromYjs, 0);
585
+ return;
586
+ }
587
+ if (isYjsSerializableStateError(error)) {
588
+ restoreRootState();
589
+ return;
590
+ }
591
+ throw error;
592
+ }
593
+ };
594
+ const enqueueSnapshot = (snapshot) => {
595
+ pendingSnapshot = snapshot;
596
+ pendingOperations = [];
597
+ scheduleFlushFromYjs();
598
+ };
599
+ const enqueueOperations = (operations) => {
600
+ if (operations.length === 0) return;
601
+ if (!pendingSnapshot) pendingOperations.push(...operations);
602
+ scheduleFlushFromYjs();
603
+ };
604
+ const syncNow = () => {
605
+ if (destroyed || syncingFromYjs) return;
606
+ try {
607
+ assertYjsSerializableState(store.getPureState());
608
+ } catch (error) {
609
+ restoreLastSyncedState();
610
+ throw error;
611
+ }
612
+ const pureState = clone(store.getPureState());
613
+ if (!isPlainObject(pureState)) return;
614
+ doc.transact(() => {
615
+ syncObjectToYMap(stateMap, lastSyncedState, pureState);
616
+ }, localOrigin);
617
+ lastSyncedState = pureState;
618
+ };
619
+ const stateObserver = (events, transaction) => {
620
+ if (transaction.origin === localOrigin) return;
621
+ enqueueOperations(collectRemoteOperations(events, stateMap));
622
+ };
623
+ let stateMap;
624
+ let stateMapObserved = false;
625
+ const unobserveStateMap = () => {
626
+ if (!stateMapObserved) return;
627
+ stateMap.unobserveDeep(stateObserver);
628
+ stateMapObserved = false;
629
+ };
630
+ const observeStateMap = (nextStateMap) => {
631
+ if (stateMap === nextStateMap && stateMapObserved) return;
632
+ unobserveStateMap();
633
+ stateMap = nextStateMap;
634
+ stateMap.observeDeep(stateObserver);
635
+ stateMapObserved = true;
636
+ };
637
+ const migrateRootState = (nextState) => {
638
+ const migrated = createYMap(nextState);
639
+ doc.transact(() => {
640
+ map.set(STATE_KEY, migrated);
641
+ }, localOrigin);
642
+ observeStateMap(migrated);
643
+ enqueueSnapshot(nextState);
644
+ };
645
+ const restoreRootState = () => {
646
+ const pureState = clone(store.getPureState());
647
+ const nextState = isPlainObject(pureState) ? pureState : lastSyncedState;
648
+ const restored = createYMap(nextState);
649
+ doc.transact(() => {
650
+ map.set(STATE_KEY, restored);
651
+ }, localOrigin);
652
+ observeStateMap(restored);
653
+ lastSyncedState = nextState;
654
+ };
655
+ const applyInitialRemoteState = (state) => {
656
+ runWithoutHistoryRecording(store, () => {
657
+ try {
658
+ applyRemoteState(state);
659
+ } catch (error) {
660
+ if (isYjsSerializableStateError(error)) {
661
+ restoreRootState();
662
+ return;
663
+ }
664
+ throw error;
665
+ }
666
+ });
667
+ };
668
+ const existingStateMap = getStateMap();
669
+ if (existingStateMap) {
670
+ stateMap = existingStateMap;
671
+ applyInitialRemoteState(toPlainObject(stateMap));
672
+ } else {
673
+ const currentState = map.get(STATE_KEY);
674
+ if (isPlainObject(currentState)) {
675
+ stateMap = createYMap(currentState);
676
+ doc.transact(() => {
677
+ map.set(STATE_KEY, stateMap);
678
+ }, localOrigin);
679
+ applyInitialRemoteState(currentState);
680
+ } else {
681
+ const pureState = clone(store.getPureState());
682
+ stateMap = createYMap(isPlainObject(pureState) ? pureState : {});
683
+ doc.transact(() => {
684
+ map.set(STATE_KEY, stateMap);
685
+ }, localOrigin);
686
+ }
687
+ }
688
+ observeStateMap(stateMap);
689
+ const observer = (event) => {
690
+ if (event.transaction.origin === localOrigin) return;
691
+ if (!event.keysChanged.has(STATE_KEY)) return;
692
+ const stateChange = event.changes.keys.get(STATE_KEY);
693
+ const nextStateMap = getStateMap();
694
+ if (nextStateMap) {
695
+ observeStateMap(nextStateMap);
696
+ enqueueSnapshot(toPlainObject(nextStateMap));
697
+ return;
698
+ }
699
+ const currentState = map.get(STATE_KEY);
700
+ if (isPlainObject(currentState)) {
701
+ migrateRootState(currentState);
702
+ return;
703
+ }
704
+ if (stateChange?.action === "delete") {
705
+ migrateRootState({});
706
+ return;
707
+ }
708
+ restoreRootState();
709
+ };
710
+ map.observe(observer);
711
+ const unsubscribe = store.subscribe(() => {
712
+ syncNow();
713
+ });
714
+ const binding = {
715
+ doc,
716
+ map,
717
+ syncNow,
718
+ destroy: () => {
719
+ if (destroyed) return;
720
+ destroyed = true;
721
+ unsubscribe();
722
+ map.unobserve(observer);
723
+ unobserveStateMap();
724
+ if (!options.doc) doc.destroy();
725
+ }
726
+ };
727
+ if (process.env.NODE_ENV === "test") binding.__unsafeTestOnly__ = { applyRemoteOperations: (operations) => {
728
+ applyRemoteOperations(operations);
729
+ } };
730
+ return binding;
572
731
  };
573
- var yjs = (options = {}) => (store) => {
574
- const binding = bindYjs(store, options);
575
- const baseDestroy = store.destroy;
576
- store.destroy = () => {
577
- binding.destroy();
578
- baseDestroy();
579
- };
580
- return store;
732
+ const yjs$1 = (options = {}) => (store) => {
733
+ let binding;
734
+ const cancelBinding = (0, coaction.onStoreReady)(store, () => {
735
+ binding = bindYjs(store, options);
736
+ });
737
+ const baseDestroy = store.destroy;
738
+ let destroyed = false;
739
+ store.destroy = () => {
740
+ if (destroyed) return;
741
+ destroyed = true;
742
+ cancelBinding();
743
+ binding?.destroy();
744
+ binding = void 0;
745
+ baseDestroy();
746
+ };
747
+ return store;
581
748
  };
582
-
583
- // index.ts
584
- __reExport(index_exports, src_exports, module.exports);
585
- // Annotate the CommonJS export names for ESM import in node:
586
- 0 && (module.exports = {
587
- __unsafeTestOnly__,
588
- bindYjs,
589
- yjs
749
+ //#endregion
750
+ exports.__unsafeTestOnly__ = __unsafeTestOnly__;
751
+ exports.bindYjs = bindYjs;
752
+ exports.yjs = yjs$1;
753
+ Object.keys(yjs).forEach(function(k) {
754
+ if (k !== "default" && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
755
+ enumerable: true,
756
+ get: function() {
757
+ return yjs[k];
758
+ }
759
+ });
590
760
  });