@automerge/automerge-repo-solid-primitives 2.5.0 → 2.5.2-alpha.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,912 +1,1479 @@
1
- import { onCleanup as Y, createMemo as G, createContext as X, useContext as J, createResource as Z, createEffect as Q } from "solid-js";
2
- import { createStore as ee, produce as te, reconcile as re } from "solid-js/store";
3
- const m = Symbol.for("_am_meta"), w = Symbol.for("_am_trace"), y = Symbol.for("_am_objectId"), O = Symbol.for("_am_isProxy"), A = Symbol.for("_am_clearCache"), ne = Symbol.for("_am_uint"), oe = Symbol.for("_am_int"), se = Symbol.for("_am_f64"), T = Symbol.for("_am_counter"), W = Symbol.for("_am_immutableString");
4
- class ie {
5
- constructor(e) {
6
- this.value = e || 0, Reflect.defineProperty(this, T, { value: !0 });
7
- }
8
- /**
9
- * A peculiar JavaScript language feature from its early days: if the object
10
- * `x` has a `valueOf()` method that returns a number, you can use numerical
11
- * operators on the object `x` directly, such as `x + 1` or `x < 4`.
12
- * This method is also called when coercing a value to a string by
13
- * concatenating it with another string, as in `x + ''`.
14
- * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf
15
- */
16
- valueOf() {
17
- return this.value;
18
- }
19
- /**
20
- * Returns the counter value as a decimal string. If `x` is a counter object,
21
- * this method is called e.g. when you do `['value: ', x].join('')` or when
22
- * you use string interpolation: `value: ${x}`.
23
- */
24
- toString() {
25
- return this.valueOf().toString();
26
- }
27
- /**
28
- * Returns the counter value, so that a JSON serialization of an Automerge
29
- * document represents the counter simply as an integer.
30
- */
31
- toJSON() {
32
- return this.value;
33
- }
34
- /**
35
- * Increases the value of the counter by `delta`. If `delta` is not given,
36
- * increases the value of the counter by 1.
37
- *
38
- * Will throw an error if used outside of a change callback.
39
- */
40
- increment(e) {
41
- throw new Error("Counters should not be incremented outside of a change callback");
42
- }
43
- /**
44
- * Decreases the value of the counter by `delta`. If `delta` is not given,
45
- * decreases the value of the counter by 1.
46
- *
47
- * Will throw an error if used outside of a change callback.
48
- */
49
- decrement(e) {
50
- throw new Error("Counters should not be decremented outside of a change callback");
51
- }
52
- }
53
- class ue extends ie {
54
- constructor(e, r, o, s, n) {
55
- super(e), this.context = r, this.path = o, this.objectId = s, this.key = n;
56
- }
57
- /**
58
- * Increases the value of the counter by `delta`. If `delta` is not given,
59
- * increases the value of the counter by 1.
60
- */
61
- increment(e) {
62
- return e = typeof e == "number" ? e : 1, this.context.increment(this.objectId, this.key, e), this.value += e, this.value;
63
- }
64
- /**
65
- * Decreases the value of the counter by `delta`. If `delta` is not given,
66
- * decreases the value of the counter by 1.
67
- */
68
- decrement(e) {
69
- return this.increment(typeof e == "number" ? -e : -1);
70
- }
1
+ import { onCleanup, createMemo, createContext, useContext, createResource, createEffect } from 'solid-js';
2
+ import { createStore, produce, reconcile } from 'solid-js/store';
3
+
4
+ // Properties of the document root object
5
+ const STATE = Symbol.for("_am_meta"); // symbol used to hide application metadata on automerge objects
6
+ const TRACE = Symbol.for("_am_trace"); // used for debugging
7
+ const OBJECT_ID = Symbol.for("_am_objectId"); // symbol used to hide the object id on automerge objects
8
+ const IS_PROXY = Symbol.for("_am_isProxy"); // symbol used to test if the document is a proxy object
9
+ const CLEAR_CACHE = Symbol.for("_am_clearCache"); // symbol used to tell a proxy object to clear its cache
10
+ const UINT = Symbol.for("_am_uint");
11
+ const INT = Symbol.for("_am_int");
12
+ const F64 = Symbol.for("_am_f64");
13
+ const COUNTER = Symbol.for("_am_counter");
14
+ const IMMUTABLE_STRING = Symbol.for("_am_immutableString");
15
+
16
+ /**
17
+ * The most basic CRDT: an integer value that can be changed only by
18
+ * incrementing and decrementing. Since addition of integers is commutative,
19
+ * the value trivially converges.
20
+ */
21
+ class Counter {
22
+ constructor(value) {
23
+ this.value = value || 0;
24
+ Reflect.defineProperty(this, COUNTER, { value: true });
25
+ }
26
+ /**
27
+ * A peculiar JavaScript language feature from its early days: if the object
28
+ * `x` has a `valueOf()` method that returns a number, you can use numerical
29
+ * operators on the object `x` directly, such as `x + 1` or `x < 4`.
30
+ * This method is also called when coercing a value to a string by
31
+ * concatenating it with another string, as in `x + ''`.
32
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf
33
+ */
34
+ valueOf() {
35
+ return this.value;
36
+ }
37
+ /**
38
+ * Returns the counter value as a decimal string. If `x` is a counter object,
39
+ * this method is called e.g. when you do `['value: ', x].join('')` or when
40
+ * you use string interpolation: `value: ${x}`.
41
+ */
42
+ toString() {
43
+ return this.valueOf().toString();
44
+ }
45
+ /**
46
+ * Returns the counter value, so that a JSON serialization of an Automerge
47
+ * document represents the counter simply as an integer.
48
+ */
49
+ toJSON() {
50
+ return this.value;
51
+ }
52
+ /**
53
+ * Increases the value of the counter by `delta`. If `delta` is not given,
54
+ * increases the value of the counter by 1.
55
+ *
56
+ * Will throw an error if used outside of a change callback.
57
+ */
58
+ increment(_delta) {
59
+ throw new Error("Counters should not be incremented outside of a change callback");
60
+ }
61
+ /**
62
+ * Decreases the value of the counter by `delta`. If `delta` is not given,
63
+ * decreases the value of the counter by 1.
64
+ *
65
+ * Will throw an error if used outside of a change callback.
66
+ */
67
+ decrement(_delta) {
68
+ throw new Error("Counters should not be decremented outside of a change callback");
69
+ }
71
70
  }
72
- function ae(t, e, r, o, s) {
73
- return new ue(t, e, r, o, s);
71
+ /**
72
+ * An instance of this class is used when a counter is accessed within a change
73
+ * callback.
74
+ */
75
+ class WriteableCounter extends Counter {
76
+ constructor(value, context, path, objectId, key) {
77
+ super(value);
78
+ this.context = context;
79
+ this.path = path;
80
+ this.objectId = objectId;
81
+ this.key = key;
82
+ }
83
+ /**
84
+ * Increases the value of the counter by `delta`. If `delta` is not given,
85
+ * increases the value of the counter by 1.
86
+ */
87
+ increment(delta) {
88
+ delta = typeof delta === "number" ? delta : 1;
89
+ this.context.increment(this.objectId, this.key, delta);
90
+ this.value += delta;
91
+ return this.value;
92
+ }
93
+ /**
94
+ * Decreases the value of the counter by `delta`. If `delta` is not given,
95
+ * decreases the value of the counter by 1.
96
+ */
97
+ decrement(delta) {
98
+ return this.increment(typeof delta === "number" ? -delta : -1);
99
+ }
74
100
  }
75
- var z;
76
- class ce {
77
- constructor(e) {
78
- this[z] = !0, this.val = e;
79
- }
80
- /**
81
- * Returns the content of the ImmutableString object as a simple string
82
- */
83
- toString() {
84
- return this.val;
85
- }
86
- toJSON() {
87
- return this.val;
88
- }
101
+ /**
102
+ * Returns an instance of `WriteableCounter` for use in a change callback.
103
+ * `context` is the proxy context that keeps track of the mutations.
104
+ * `objectId` is the ID of the object containing the counter, and `key` is
105
+ * the property name (key in map, or index in list) where the counter is
106
+ * located.
107
+ */
108
+ function getWriteableCounter(value, context, path, objectId, key) {
109
+ return new WriteableCounter(value, context, path, objectId, key);
89
110
  }
90
- z = W;
91
- function h(t) {
92
- if (typeof t == "string" && /^[0-9]+$/.test(t) && (t = parseInt(t, 10)), typeof t != "number")
93
- return t;
94
- if (t < 0 || isNaN(t) || t === 1 / 0 || t === -1 / 0)
95
- throw new RangeError("A list index must be positive, but you passed " + t);
96
- return t;
97
- }
98
- function p(t, e) {
99
- const { context: r, objectId: o, path: s } = t, n = r.getWithType(o, e);
100
- if (n === null)
101
- return;
102
- const i = n[0], u = n[1];
103
- switch (i) {
104
- case void 0:
105
- return;
106
- case "map":
107
- return P(r, u, [...s, e]);
108
- case "list":
109
- return _(r, u, [...s, e]);
110
- case "text":
111
- return r.text(u);
112
- case "str":
113
- return new ce(u);
114
- case "uint":
115
- return u;
116
- case "int":
117
- return u;
118
- case "f64":
119
- return u;
120
- case "boolean":
121
- return u;
122
- case "null":
123
- return null;
124
- case "bytes":
125
- return u;
126
- case "timestamp":
127
- return u;
128
- case "counter":
129
- return ae(u, r, s, o, e);
130
- default:
131
- throw RangeError(`datatype ${i} unimplemented`);
132
- }
111
+ //module.exports = { Counter, getWriteableCounter }
112
+
113
+ var _a;
114
+ class ImmutableString {
115
+ constructor(val) {
116
+ // Used to detect whether a value is a ImmutableString object rather than using an instanceof check
117
+ this[_a] = true;
118
+ this.val = val;
119
+ }
120
+ /**
121
+ * Returns the content of the ImmutableString object as a simple string
122
+ */
123
+ toString() {
124
+ return this.val;
125
+ }
126
+ toJSON() {
127
+ return this.val;
128
+ }
133
129
  }
134
- function S(t, e, r) {
135
- const o = typeof t;
136
- switch (o) {
137
- case "object":
138
- if (t == null)
139
- return [null, "null"];
140
- if (t[ne])
141
- return [t.value, "uint"];
142
- if (t[oe])
143
- return [t.value, "int"];
144
- if (t[se])
145
- return [t.value, "f64"];
146
- if (t[T])
147
- return [t.value, "counter"];
148
- if (t instanceof Date)
149
- return [t.getTime(), "timestamp"];
150
- if (pe(t))
151
- return [t.toString(), "str"];
152
- if (t instanceof Uint8Array)
153
- return [t, "bytes"];
154
- if (t instanceof Array)
155
- return [t, "list"];
156
- if (Object.prototype.toString.call(t) === "[object Object]")
157
- return [t, "map"];
158
- throw E(t, r) ? new RangeError("Cannot create a reference to an existing document object") : new RangeError(`Cannot assign unknown object: ${t}`);
159
- case "boolean":
160
- return [t, "boolean"];
161
- case "number":
162
- return Number.isInteger(t) ? [t, "int"] : [t, "f64"];
163
- case "string":
164
- return [t, "text"];
165
- case "undefined":
166
- throw new RangeError([
167
- `Cannot assign undefined value at ${M(e)}, `,
168
- "because `undefined` is not a valid JSON data type. ",
169
- "You might consider setting the property's value to `null`, ",
170
- "or using `delete` to remove it altogether."
171
- ].join(""));
172
- default:
173
- throw new RangeError([
174
- `Cannot assign ${o} value at ${M(e)}. `,
175
- "All JSON primitive datatypes (object, array, string, number, boolean, null) ",
176
- `are supported in an Automerge document; ${o} values are not. `
177
- ].join(""));
178
- }
130
+ _a = IMMUTABLE_STRING;
131
+
132
+ function parseListIndex(key) {
133
+ if (typeof key === "string" && /^[0-9]+$/.test(key))
134
+ key = parseInt(key, 10);
135
+ if (typeof key !== "number") {
136
+ return key;
137
+ }
138
+ if (key < 0 || isNaN(key) || key === Infinity || key === -Infinity) {
139
+ throw new RangeError("A list index must be positive, but you passed " + key);
140
+ }
141
+ return key;
179
142
  }
180
- function E(t, e) {
181
- var r, o;
182
- return t instanceof Date ? !1 : !!(t && ((o = (r = t[m]) === null || r === void 0 ? void 0 : r.handle) === null || o === void 0 ? void 0 : o.__wbg_ptr) === e.__wbg_ptr);
183
- }
184
- const fe = {
185
- get(t, e) {
186
- const { context: r, objectId: o, cache: s } = t;
187
- return e === Symbol.toStringTag ? t[Symbol.toStringTag] : e === y ? o : e === O ? !0 : e === w ? t.trace : e === m ? { handle: r } : (s[e] || (s[e] = p(t, e)), s[e]);
188
- },
189
- set(t, e, r) {
190
- const { context: o, objectId: s, path: n } = t;
191
- if (t.cache = {}, E(r, o))
192
- throw new RangeError("Cannot create a reference to an existing document object");
193
- if (e === w)
194
- return t.trace = r, !0;
195
- if (e === A)
196
- return !0;
197
- const [i, u] = S(r, [...n, e], o);
198
- switch (u) {
199
- case "list": {
200
- const a = o.putObject(s, e, []), f = _(o, a, [...n, e]);
201
- for (let c = 0; c < i.length; c++)
202
- f[c] = i[c];
203
- break;
204
- }
205
- case "text": {
206
- o.putObject(s, e, i);
207
- break;
208
- }
209
- case "map": {
210
- const a = o.putObject(s, e, {}), f = P(o, a, [...n, e]);
211
- for (const c in i)
212
- f[c] = i[c];
213
- break;
214
- }
215
- default:
216
- o.put(s, e, i, u);
217
- }
218
- return !0;
219
- },
220
- deleteProperty(t, e) {
221
- const { context: r, objectId: o } = t;
222
- return t.cache = {}, r.delete(o, e), !0;
223
- },
224
- has(t, e) {
225
- return this.get(t, e) !== void 0;
226
- },
227
- getOwnPropertyDescriptor(t, e) {
228
- const r = this.get(t, e);
229
- if (typeof r < "u")
230
- return {
231
- configurable: !0,
232
- enumerable: !0,
233
- value: r
234
- };
235
- },
236
- ownKeys(t) {
237
- const { context: e, objectId: r } = t, o = e.keys(r);
238
- return [...new Set(o)];
239
- }
240
- }, F = {
241
- get(t, e) {
242
- const { context: r, objectId: o } = t;
243
- return e = h(e), e === Symbol.hasInstance ? (s) => Array.isArray(s) : e === Symbol.toStringTag ? t[Symbol.toStringTag] : e === y ? o : e === O ? !0 : e === w ? t.trace : e === m ? { handle: r } : e === "length" ? r.length(o) : typeof e == "number" ? p(t, e) : C(t)[e];
244
- },
245
- set(t, e, r) {
246
- const { context: o, objectId: s, path: n } = t;
247
- if (e = h(e), E(r, o))
248
- throw new RangeError("Cannot create a reference to an existing document object");
249
- if (e === A)
250
- return !0;
251
- if (e === w)
252
- return t.trace = r, !0;
253
- if (typeof e == "string")
254
- throw new RangeError("list index must be a number");
255
- const [i, u] = S(r, [...n, e], o);
256
- switch (u) {
257
- case "list": {
258
- let a;
259
- e >= o.length(s) ? a = o.insertObject(s, e, []) : a = o.putObject(s, e, []), _(o, a, [...n, e]).splice(0, 0, ...i);
260
- break;
261
- }
262
- case "text": {
263
- e >= o.length(s) ? o.insertObject(s, e, i) : o.putObject(s, e, i);
264
- break;
265
- }
266
- case "map": {
267
- let a;
268
- e >= o.length(s) ? a = o.insertObject(s, e, {}) : a = o.putObject(s, e, {});
269
- const f = P(o, a, [...n, e]);
270
- for (const c in i)
271
- f[c] = i[c];
272
- break;
273
- }
274
- default:
275
- e >= o.length(s) ? o.insert(s, e, i, u) : o.put(s, e, i, u);
276
- }
277
- return !0;
278
- },
279
- deleteProperty(t, e) {
280
- const { context: r, objectId: o } = t;
281
- e = h(e);
282
- const s = r.get(o, e);
283
- if (s != null && s[0] == "counter")
284
- throw new TypeError("Unsupported operation: deleting a counter from a list");
285
- return r.delete(o, e), !0;
286
- },
287
- has(t, e) {
288
- const { context: r, objectId: o } = t;
289
- return e = h(e), typeof e == "number" ? e < r.length(o) : e === "length";
290
- },
291
- getOwnPropertyDescriptor(t, e) {
292
- const { context: r, objectId: o } = t;
293
- return e === "length" ? { writable: !0, value: r.length(o) } : e === y ? { configurable: !1, enumerable: !1, value: o } : (e = h(e), { configurable: !0, enumerable: !0, value: p(t, e) });
294
- },
295
- getPrototypeOf(t) {
296
- return Object.getPrototypeOf(t);
297
- },
298
- ownKeys() {
299
- const t = [];
300
- return t.push("length"), t;
301
- }
302
- };
303
- Object.assign({}, F, {
304
- get(t, e) {
305
- const { context: r, objectId: o } = t;
306
- return e = h(e), e === Symbol.hasInstance ? (s) => Array.isArray(s) : e === Symbol.toStringTag ? t[Symbol.toStringTag] : e === y ? o : e === O ? !0 : e === w ? t.trace : e === m ? { handle: r } : e === "length" ? r.length(o) : typeof e == "number" ? p(t, e) : le(t)[e] || C(t)[e];
307
- },
308
- getPrototypeOf() {
309
- return Object.getPrototypeOf(new Text());
310
- }
311
- });
312
- function P(t, e, r) {
313
- const o = {
314
- context: t,
315
- objectId: e,
316
- path: r || [],
317
- cache: {}
318
- }, s = {};
319
- return Object.assign(s, o), new Proxy(s, fe);
320
- }
321
- function _(t, e, r) {
322
- const o = {
323
- context: t,
324
- objectId: e,
325
- path: r || [],
326
- cache: {}
327
- }, s = [];
328
- return Object.assign(s, o), new Proxy(s, F);
329
- }
330
- function C(t) {
331
- const { context: e, objectId: r, path: o } = t;
332
- return {
333
- at(n) {
334
- return p(t, n);
335
- },
336
- deleteAt(n, i) {
337
- return typeof i == "number" ? e.splice(r, n, i) : e.delete(r, n), this;
338
- },
339
- fill(n, i, u) {
340
- const [a, f] = S(n, [...o, i], e), c = e.length(r);
341
- i = h(i || 0), u = h(u || c);
342
- for (let l = i; l < Math.min(u, c); l++)
343
- f === "list" || f === "map" || f === "text" ? e.putObject(r, l, a) : e.put(r, l, a, f);
344
- return this;
345
- },
346
- indexOf(n, i = 0) {
347
- const u = e.length(r);
348
- for (let a = i; a < u; a++) {
349
- const f = e.getWithType(r, a);
350
- if (!f)
351
- continue;
352
- const [c, l] = f;
353
- if (!["map", "list", "text"].includes(c)) {
354
- if (l === n)
355
- return a;
356
- continue;
357
- }
358
- if (c === "text" && typeof n == "string" && n === p(t, a) || n[y] === l)
359
- return a;
360
- }
361
- return -1;
362
- },
363
- insertAt(n, ...i) {
364
- return this.splice(n, 0, ...i), this;
365
- },
366
- pop() {
367
- const n = e.length(r);
368
- if (n == 0)
369
- return;
370
- const i = p(t, n - 1);
371
- return e.delete(r, n - 1), i;
372
- },
373
- push(...n) {
374
- const i = e.length(r);
375
- return this.splice(i, 0, ...n), e.length(r);
376
- },
377
- shift() {
378
- if (e.length(r) == 0)
143
+ function valueAt(target, prop) {
144
+ const { context, objectId, path } = target;
145
+ const value = context.getWithType(objectId, prop);
146
+ if (value === null) {
379
147
  return;
380
- const n = p(t, 0);
381
- return e.delete(r, 0), n;
382
- },
383
- splice(n, i, ...u) {
384
- n = h(n), typeof i != "number" && (i = e.length(r) - n), i = h(i);
385
- for (const c of u)
386
- if (E(c, e))
387
- throw new RangeError("Cannot create a reference to an existing document object");
388
- const a = [];
389
- for (let c = 0; c < i; c++) {
390
- const l = p(t, n);
391
- l !== void 0 && a.push(l), e.delete(r, n);
392
- }
393
- const f = u.map((c, l) => {
394
- try {
395
- return S(c, [...o], e);
396
- } catch (g) {
397
- throw g instanceof RangeError ? new RangeError(`${g.message} (at index ${l} in the input)`) : g;
148
+ }
149
+ const datatype = value[0];
150
+ const val = value[1];
151
+ switch (datatype) {
152
+ case undefined:
153
+ return;
154
+ case "map":
155
+ return mapProxy(context, val, [...path, prop]);
156
+ case "list":
157
+ return listProxy(context, val, [...path, prop]);
158
+ case "text":
159
+ return context.text(val);
160
+ case "str":
161
+ return new ImmutableString(val);
162
+ case "uint":
163
+ return val;
164
+ case "int":
165
+ return val;
166
+ case "f64":
167
+ return val;
168
+ case "boolean":
169
+ return val;
170
+ case "null":
171
+ return null;
172
+ case "bytes":
173
+ return val;
174
+ case "timestamp":
175
+ return val;
176
+ case "counter": {
177
+ const counter = getWriteableCounter(val, context, path, objectId, prop);
178
+ return counter;
398
179
  }
399
- });
400
- for (const [c, l] of f) {
401
- switch (l) {
402
- case "list": {
403
- const g = e.insertObject(r, n, []);
404
- _(e, g, [...o, n]).splice(0, 0, ...c);
405
- break;
406
- }
407
- case "text": {
408
- e.insertObject(r, n, c);
409
- break;
410
- }
411
- case "map": {
412
- const g = e.insertObject(r, n, {}), L = P(e, g, [...o, n]);
413
- for (const D in c)
414
- L[D] = c[D];
415
- break;
416
- }
417
- default:
418
- e.insert(r, n, c, l);
180
+ default:
181
+ throw RangeError(`datatype ${datatype} unimplemented`);
182
+ }
183
+ }
184
+ function import_value(value, path, context) {
185
+ const type = typeof value;
186
+ switch (type) {
187
+ case "object":
188
+ if (value == null) {
189
+ return [null, "null"];
190
+ }
191
+ else if (value[UINT]) {
192
+ return [value.value, "uint"];
193
+ }
194
+ else if (value[INT]) {
195
+ return [value.value, "int"];
196
+ }
197
+ else if (value[F64]) {
198
+ return [value.value, "f64"];
199
+ }
200
+ else if (value[COUNTER]) {
201
+ return [value.value, "counter"];
202
+ }
203
+ else if (value instanceof Date) {
204
+ return [value.getTime(), "timestamp"];
205
+ }
206
+ else if (isImmutableString(value)) {
207
+ return [value.toString(), "str"];
208
+ }
209
+ else if (value instanceof Uint8Array) {
210
+ return [value, "bytes"];
211
+ }
212
+ else if (value instanceof Array) {
213
+ return [value, "list"];
214
+ }
215
+ else if (Object.prototype.toString.call(value) === "[object Object]") {
216
+ return [value, "map"];
217
+ }
218
+ else if (isSameDocument(value, context)) {
219
+ throw new RangeError("Cannot create a reference to an existing document object");
220
+ }
221
+ else {
222
+ throw new RangeError(`Cannot assign unknown object: ${value}`);
223
+ }
224
+ case "boolean":
225
+ return [value, "boolean"];
226
+ case "number":
227
+ if (Number.isInteger(value)) {
228
+ return [value, "int"];
229
+ }
230
+ else {
231
+ return [value, "f64"];
232
+ }
233
+ case "string":
234
+ return [value, "text"];
235
+ case "undefined":
236
+ throw new RangeError([
237
+ `Cannot assign undefined value at ${printPath(path)}, `,
238
+ "because `undefined` is not a valid JSON data type. ",
239
+ "You might consider setting the property's value to `null`, ",
240
+ "or using `delete` to remove it altogether.",
241
+ ].join(""));
242
+ default:
243
+ throw new RangeError([
244
+ `Cannot assign ${type} value at ${printPath(path)}. `,
245
+ `All JSON primitive datatypes (object, array, string, number, boolean, null) `,
246
+ `are supported in an Automerge document; ${type} values are not. `,
247
+ ].join(""));
248
+ }
249
+ }
250
+ // When we assign a value to a property in a proxy we recursively walk through
251
+ // the value we are assigning and copy it into the document. This is generally
252
+ // desirable behaviour. However, a very common bug is to accidentally assign a
253
+ // value which is already in the document to another key within the same
254
+ // document, this often leads to surprising behaviour where users expected to
255
+ // _move_ the object, but it is instead copied. To avoid this we check if the
256
+ // value is from the same document and if it is we throw an error, this means
257
+ // we require an explicit Object.assign call to copy the object, thus avoiding
258
+ // the footgun
259
+ function isSameDocument(val, context) {
260
+ var _b, _c;
261
+ // Date is technically an object, but immutable, so allowing people to assign
262
+ // a date from one place in the document to another place in the document is
263
+ // not likely to be a bug
264
+ if (val instanceof Date) {
265
+ return false;
266
+ }
267
+ // this depends on __wbg_ptr being the wasm pointer
268
+ // a new version of wasm-bindgen will break this
269
+ // but the tests should expose the break
270
+ if (val && ((_c = (_b = val[STATE]) === null || _b === void 0 ? void 0 : _b.handle) === null || _c === void 0 ? void 0 : _c.__wbg_ptr) === context.__wbg_ptr) {
271
+ return true;
272
+ }
273
+ return false;
274
+ }
275
+ const MapHandler = {
276
+ get(target, key) {
277
+ const { context, objectId, cache } = target;
278
+ if (key === Symbol.toStringTag) {
279
+ return target[Symbol.toStringTag];
419
280
  }
420
- n += 1;
421
- }
422
- return a;
423
- },
424
- unshift(...n) {
425
- return this.splice(0, 0, ...n), e.length(r);
426
- },
427
- entries() {
428
- let n = 0;
429
- return {
430
- next: () => {
431
- const u = p(t, n);
432
- return u === void 0 ? { value: void 0, done: !0 } : { value: [n++, u], done: !1 };
433
- },
434
- [Symbol.iterator]() {
435
- return this;
281
+ if (key === OBJECT_ID)
282
+ return objectId;
283
+ if (key === IS_PROXY)
284
+ return true;
285
+ if (key === TRACE)
286
+ return target.trace;
287
+ if (key === STATE)
288
+ return { handle: context };
289
+ if (!cache[key]) {
290
+ cache[key] = valueAt(target, key);
436
291
  }
437
- };
292
+ return cache[key];
438
293
  },
439
- keys() {
440
- let n = 0;
441
- const i = e.length(r);
442
- return {
443
- next: () => n < i ? { value: n++, done: !1 } : { value: void 0, done: !0 },
444
- [Symbol.iterator]() {
445
- return this;
446
- }
447
- };
448
- },
449
- values() {
450
- let n = 0;
451
- return {
452
- next: () => {
453
- const u = p(t, n++);
454
- return u === void 0 ? { value: void 0, done: !0 } : { value: u, done: !1 };
455
- },
456
- [Symbol.iterator]() {
457
- return this;
294
+ set(target, key, val) {
295
+ const { context, objectId, path } = target;
296
+ target.cache = {}; // reset cache on set
297
+ if (isSameDocument(val, context)) {
298
+ throw new RangeError("Cannot create a reference to an existing document object");
458
299
  }
459
- };
460
- },
461
- toArray() {
462
- const n = [];
463
- let i;
464
- do
465
- i = p(t, n.length), i !== void 0 && n.push(i);
466
- while (i !== void 0);
467
- return n;
468
- },
469
- map(n) {
470
- return this.toArray().map(n);
471
- },
472
- toString() {
473
- return this.toArray().toString();
474
- },
475
- toLocaleString() {
476
- return this.toArray().toLocaleString();
477
- },
478
- forEach(n) {
479
- return this.toArray().forEach(n);
480
- },
481
- // todo: real concat function is different
482
- concat(n) {
483
- return this.toArray().concat(n);
484
- },
485
- every(n) {
486
- return this.toArray().every(n);
487
- },
488
- filter(n) {
489
- return this.toArray().filter(n);
490
- },
491
- find(n) {
492
- let i = 0;
493
- for (const u of this) {
494
- if (n(u, i))
495
- return u;
496
- i += 1;
497
- }
300
+ if (key === TRACE) {
301
+ target.trace = val;
302
+ return true;
303
+ }
304
+ if (key === CLEAR_CACHE) {
305
+ return true;
306
+ }
307
+ const [value, datatype] = import_value(val, [...path, key], context);
308
+ switch (datatype) {
309
+ case "list": {
310
+ const list = context.putObject(objectId, key, []);
311
+ const proxyList = listProxy(context, list, [...path, key]);
312
+ for (let i = 0; i < value.length; i++) {
313
+ proxyList[i] = value[i];
314
+ }
315
+ break;
316
+ }
317
+ case "text": {
318
+ context.putObject(objectId, key, value);
319
+ break;
320
+ }
321
+ case "map": {
322
+ const map = context.putObject(objectId, key, {});
323
+ const proxyMap = mapProxy(context, map, [...path, key]);
324
+ for (const key in value) {
325
+ proxyMap[key] = value[key];
326
+ }
327
+ break;
328
+ }
329
+ default:
330
+ context.put(objectId, key, value, datatype);
331
+ }
332
+ return true;
498
333
  },
499
- findIndex(n) {
500
- let i = 0;
501
- for (const u of this) {
502
- if (n(u, i))
503
- return i;
504
- i += 1;
505
- }
506
- return -1;
334
+ deleteProperty(target, key) {
335
+ const { context, objectId } = target;
336
+ target.cache = {}; // reset cache on delete
337
+ context.delete(objectId, key);
338
+ return true;
507
339
  },
508
- includes(n) {
509
- return this.find((i) => i === n) !== void 0;
340
+ has(target, key) {
341
+ const value = this.get(target, key);
342
+ return value !== undefined;
510
343
  },
511
- join(n) {
512
- return this.toArray().join(n);
344
+ getOwnPropertyDescriptor(target, key) {
345
+ // const { context, objectId } = target
346
+ const value = this.get(target, key);
347
+ if (typeof value !== "undefined") {
348
+ return {
349
+ configurable: true,
350
+ enumerable: true,
351
+ value,
352
+ };
353
+ }
513
354
  },
514
- reduce(n, i) {
515
- return this.toArray().reduce(n, i);
355
+ ownKeys(target) {
356
+ const { context, objectId } = target;
357
+ // FIXME - this is a tmp workaround until fix the dupe key bug in keys()
358
+ const keys = context.keys(objectId);
359
+ return [...new Set(keys)];
516
360
  },
517
- reduceRight(n, i) {
518
- return this.toArray().reduceRight(n, i);
361
+ };
362
+ const ListHandler = {
363
+ get(target, index) {
364
+ const { context, objectId } = target;
365
+ index = parseListIndex(index);
366
+ if (index === Symbol.hasInstance) {
367
+ return (instance) => {
368
+ return Array.isArray(instance);
369
+ };
370
+ }
371
+ if (index === Symbol.toStringTag) {
372
+ return target[Symbol.toStringTag];
373
+ }
374
+ if (index === OBJECT_ID)
375
+ return objectId;
376
+ if (index === IS_PROXY)
377
+ return true;
378
+ if (index === TRACE)
379
+ return target.trace;
380
+ if (index === STATE)
381
+ return { handle: context };
382
+ if (index === "length")
383
+ return context.length(objectId);
384
+ if (typeof index === "number") {
385
+ return valueAt(target, index);
386
+ }
387
+ else {
388
+ return listMethods(target)[index];
389
+ }
519
390
  },
520
- lastIndexOf(n, i = 1 / 0) {
521
- return this.toArray().lastIndexOf(n, i);
391
+ set(target, index, val) {
392
+ const { context, objectId, path } = target;
393
+ index = parseListIndex(index);
394
+ if (isSameDocument(val, context)) {
395
+ throw new RangeError("Cannot create a reference to an existing document object");
396
+ }
397
+ if (index === CLEAR_CACHE) {
398
+ return true;
399
+ }
400
+ if (index === TRACE) {
401
+ target.trace = val;
402
+ return true;
403
+ }
404
+ if (typeof index == "string") {
405
+ throw new RangeError("list index must be a number");
406
+ }
407
+ const [value, datatype] = import_value(val, [...path, index], context);
408
+ switch (datatype) {
409
+ case "list": {
410
+ let list;
411
+ if (index >= context.length(objectId)) {
412
+ list = context.insertObject(objectId, index, []);
413
+ }
414
+ else {
415
+ list = context.putObject(objectId, index, []);
416
+ }
417
+ const proxyList = listProxy(context, list, [...path, index]);
418
+ proxyList.splice(0, 0, ...value);
419
+ break;
420
+ }
421
+ case "text": {
422
+ if (index >= context.length(objectId)) {
423
+ context.insertObject(objectId, index, value);
424
+ }
425
+ else {
426
+ context.putObject(objectId, index, value);
427
+ }
428
+ break;
429
+ }
430
+ case "map": {
431
+ let map;
432
+ if (index >= context.length(objectId)) {
433
+ map = context.insertObject(objectId, index, {});
434
+ }
435
+ else {
436
+ map = context.putObject(objectId, index, {});
437
+ }
438
+ const proxyMap = mapProxy(context, map, [...path, index]);
439
+ for (const key in value) {
440
+ proxyMap[key] = value[key];
441
+ }
442
+ break;
443
+ }
444
+ default:
445
+ if (index >= context.length(objectId)) {
446
+ context.insert(objectId, index, value, datatype);
447
+ }
448
+ else {
449
+ context.put(objectId, index, value, datatype);
450
+ }
451
+ }
452
+ return true;
522
453
  },
523
- slice(n, i) {
524
- return this.toArray().slice(n, i);
454
+ deleteProperty(target, index) {
455
+ const { context, objectId } = target;
456
+ index = parseListIndex(index);
457
+ const elem = context.get(objectId, index);
458
+ if (elem != null && elem[0] == "counter") {
459
+ throw new TypeError("Unsupported operation: deleting a counter from a list");
460
+ }
461
+ context.delete(objectId, index);
462
+ return true;
525
463
  },
526
- some(n) {
527
- let i = 0;
528
- for (const u of this) {
529
- if (n(u, i))
530
- return !0;
531
- i += 1;
532
- }
533
- return !1;
464
+ has(target, index) {
465
+ const { context, objectId } = target;
466
+ index = parseListIndex(index);
467
+ if (typeof index === "number") {
468
+ return index < context.length(objectId);
469
+ }
470
+ return index === "length";
534
471
  },
535
- [Symbol.iterator]: function* () {
536
- let n = 0, i = p(t, n);
537
- for (; i !== void 0; )
538
- yield i, n += 1, i = p(t, n);
539
- }
540
- };
541
- }
542
- function le(t) {
543
- const { context: e, objectId: r } = t;
544
- return {
545
- set(s, n) {
546
- return this[s] = n;
472
+ getOwnPropertyDescriptor(target, index) {
473
+ const { context, objectId } = target;
474
+ if (index === "length")
475
+ return { writable: true, value: context.length(objectId) };
476
+ if (index === OBJECT_ID)
477
+ return { configurable: false, enumerable: false, value: objectId };
478
+ index = parseListIndex(index);
479
+ const value = valueAt(target, index);
480
+ return { configurable: true, enumerable: true, value };
547
481
  },
548
- get(s) {
549
- return this[s];
482
+ getPrototypeOf(target) {
483
+ return Object.getPrototypeOf(target);
550
484
  },
551
- toString() {
552
- return e.text(r).replace(//g, "");
485
+ ownKeys( /*target*/) {
486
+ const keys = [];
487
+ // uncommenting this causes assert.deepEqual() to fail when comparing to a pojo array
488
+ // but not uncommenting it causes for (i in list) {} to not enumerate values properly
489
+ //const {context, objectId } = target
490
+ //for (let i = 0; i < target.context.length(objectId); i++) { keys.push(i.toString()) }
491
+ keys.push("length");
492
+ return keys;
553
493
  },
554
- toSpans() {
555
- const s = [];
556
- let n = "";
557
- const i = e.length(r);
558
- for (let u = 0; u < i; u++) {
559
- const a = this[u];
560
- typeof a == "string" ? n += a : (n.length > 0 && (s.push(n), n = ""), s.push(a));
561
- }
562
- return n.length > 0 && s.push(n), s;
563
- },
564
- toJSON() {
565
- return this.toString();
494
+ };
495
+ Object.assign({}, ListHandler, {
496
+ get(target, index) {
497
+ const { context, objectId } = target;
498
+ index = parseListIndex(index);
499
+ if (index === Symbol.hasInstance) {
500
+ return (instance) => {
501
+ return Array.isArray(instance);
502
+ };
503
+ }
504
+ if (index === Symbol.toStringTag) {
505
+ return target[Symbol.toStringTag];
506
+ }
507
+ if (index === OBJECT_ID)
508
+ return objectId;
509
+ if (index === IS_PROXY)
510
+ return true;
511
+ if (index === TRACE)
512
+ return target.trace;
513
+ if (index === STATE)
514
+ return { handle: context };
515
+ if (index === "length")
516
+ return context.length(objectId);
517
+ if (typeof index === "number") {
518
+ return valueAt(target, index);
519
+ }
520
+ else {
521
+ return textMethods(target)[index] || listMethods(target)[index];
522
+ }
566
523
  },
567
- indexOf(s, n = 0) {
568
- return e.text(r).indexOf(s, n);
524
+ getPrototypeOf( /*target*/) {
525
+ return Object.getPrototypeOf(new Text());
569
526
  },
570
- insertAt(s, ...n) {
571
- n.every((i) => typeof i == "string") ? e.splice(r, s, 0, n.join("")) : C(t).insertAt(s, ...n);
527
+ });
528
+ function mapProxy(context, objectId, path) {
529
+ const target = {
530
+ context,
531
+ objectId,
532
+ path: path || [],
533
+ cache: {},
534
+ };
535
+ const proxied = {};
536
+ Object.assign(proxied, target);
537
+ const result = new Proxy(proxied, MapHandler);
538
+ // conversion through unknown is necessary because the types are so different
539
+ return result;
540
+ }
541
+ function listProxy(context, objectId, path) {
542
+ const target = {
543
+ context,
544
+ objectId,
545
+ path: path || [],
546
+ cache: {},
547
+ };
548
+ const proxied = [];
549
+ Object.assign(proxied, target);
550
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
551
+ // @ts-ignore
552
+ return new Proxy(proxied, ListHandler);
553
+ }
554
+ function listMethods(target) {
555
+ const { context, objectId, path } = target;
556
+ const methods = {
557
+ at(index) {
558
+ return valueAt(target, index);
559
+ },
560
+ deleteAt(index, numDelete) {
561
+ if (typeof numDelete === "number") {
562
+ context.splice(objectId, index, numDelete);
563
+ }
564
+ else {
565
+ context.delete(objectId, index);
566
+ }
567
+ return this;
568
+ },
569
+ fill(val, start, end) {
570
+ const [value, datatype] = import_value(val, [...path, start], context);
571
+ const length = context.length(objectId);
572
+ start = parseListIndex(start || 0);
573
+ end = parseListIndex(end || length);
574
+ for (let i = start; i < Math.min(end, length); i++) {
575
+ if (datatype === "list" || datatype === "map") {
576
+ context.putObject(objectId, i, value);
577
+ }
578
+ else if (datatype === "text") {
579
+ context.putObject(objectId, i, value);
580
+ }
581
+ else {
582
+ context.put(objectId, i, value, datatype);
583
+ }
584
+ }
585
+ return this;
586
+ },
587
+ indexOf(searchElement, start = 0) {
588
+ const length = context.length(objectId);
589
+ for (let i = start; i < length; i++) {
590
+ const valueWithType = context.getWithType(objectId, i);
591
+ if (!valueWithType) {
592
+ continue;
593
+ }
594
+ const [valType, value] = valueWithType;
595
+ // Either the target element is an object, and we return if we have found
596
+ // the same object or it is a primitive value and we return if it matches
597
+ // the current value
598
+ const isObject = ["map", "list", "text"].includes(valType);
599
+ if (!isObject) {
600
+ // If the element is not an object, then check if the value is equal to the target
601
+ if (value === searchElement) {
602
+ return i;
603
+ }
604
+ else {
605
+ continue;
606
+ }
607
+ }
608
+ // if it's an object, but the type of the search element is a string, then we
609
+ // need to check if the object is a text object with the same value as the search element
610
+ if (valType === "text" && typeof searchElement === "string") {
611
+ if (searchElement === valueAt(target, i)) {
612
+ return i;
613
+ }
614
+ }
615
+ // The only possible match now is if the searchElement is an object already in the
616
+ // automerge document with the same object ID as the value
617
+ if (searchElement[OBJECT_ID] === value) {
618
+ return i;
619
+ }
620
+ }
621
+ return -1;
622
+ },
623
+ insertAt(index, ...values) {
624
+ this.splice(index, 0, ...values);
625
+ return this;
626
+ },
627
+ pop() {
628
+ const length = context.length(objectId);
629
+ if (length == 0) {
630
+ return undefined;
631
+ }
632
+ const last = valueAt(target, length - 1);
633
+ context.delete(objectId, length - 1);
634
+ return last;
635
+ },
636
+ push(...values) {
637
+ const len = context.length(objectId);
638
+ this.splice(len, 0, ...values);
639
+ return context.length(objectId);
640
+ },
641
+ shift() {
642
+ if (context.length(objectId) == 0)
643
+ return;
644
+ const first = valueAt(target, 0);
645
+ context.delete(objectId, 0);
646
+ return first;
647
+ },
648
+ splice(index, del, ...vals) {
649
+ index = parseListIndex(index);
650
+ // if del is undefined, delete until the end of the list
651
+ if (typeof del !== "number") {
652
+ del = context.length(objectId) - index;
653
+ }
654
+ del = parseListIndex(del);
655
+ for (const val of vals) {
656
+ if (isSameDocument(val, context)) {
657
+ throw new RangeError("Cannot create a reference to an existing document object");
658
+ }
659
+ }
660
+ const result = [];
661
+ for (let i = 0; i < del; i++) {
662
+ const value = valueAt(target, index);
663
+ if (value !== undefined) {
664
+ result.push(value);
665
+ }
666
+ context.delete(objectId, index);
667
+ }
668
+ const values = vals.map((val, index) => {
669
+ try {
670
+ return import_value(val, [...path], context);
671
+ }
672
+ catch (e) {
673
+ if (e instanceof RangeError) {
674
+ throw new RangeError(`${e.message} (at index ${index} in the input)`);
675
+ }
676
+ else {
677
+ throw e;
678
+ }
679
+ }
680
+ });
681
+ for (const [value, datatype] of values) {
682
+ switch (datatype) {
683
+ case "list": {
684
+ const list = context.insertObject(objectId, index, []);
685
+ const proxyList = listProxy(context, list, [...path, index]);
686
+ proxyList.splice(0, 0, ...value);
687
+ break;
688
+ }
689
+ case "text": {
690
+ context.insertObject(objectId, index, value);
691
+ break;
692
+ }
693
+ case "map": {
694
+ const map = context.insertObject(objectId, index, {});
695
+ const proxyMap = mapProxy(context, map, [...path, index]);
696
+ for (const key in value) {
697
+ proxyMap[key] = value[key];
698
+ }
699
+ break;
700
+ }
701
+ default:
702
+ context.insert(objectId, index, value, datatype);
703
+ }
704
+ index += 1;
705
+ }
706
+ return result;
707
+ },
708
+ unshift(...values) {
709
+ this.splice(0, 0, ...values);
710
+ return context.length(objectId);
711
+ },
712
+ entries() {
713
+ let i = 0;
714
+ const iterator = {
715
+ next: () => {
716
+ const value = valueAt(target, i);
717
+ if (value === undefined) {
718
+ return { value: undefined, done: true };
719
+ }
720
+ else {
721
+ return { value: [i++, value], done: false };
722
+ }
723
+ },
724
+ [Symbol.iterator]() {
725
+ return this;
726
+ },
727
+ };
728
+ return iterator;
729
+ },
730
+ keys() {
731
+ let i = 0;
732
+ const len = context.length(objectId);
733
+ const iterator = {
734
+ next: () => {
735
+ if (i < len) {
736
+ return { value: i++, done: false };
737
+ }
738
+ return { value: undefined, done: true };
739
+ },
740
+ [Symbol.iterator]() {
741
+ return this;
742
+ },
743
+ };
744
+ return iterator;
745
+ },
746
+ values() {
747
+ let i = 0;
748
+ const iterator = {
749
+ next: () => {
750
+ const value = valueAt(target, i++);
751
+ if (value === undefined) {
752
+ return { value: undefined, done: true };
753
+ }
754
+ else {
755
+ return { value, done: false };
756
+ }
757
+ },
758
+ [Symbol.iterator]() {
759
+ return this;
760
+ },
761
+ };
762
+ return iterator;
763
+ },
764
+ toArray() {
765
+ const list = [];
766
+ let value;
767
+ do {
768
+ value = valueAt(target, list.length);
769
+ if (value !== undefined) {
770
+ list.push(value);
771
+ }
772
+ } while (value !== undefined);
773
+ return list;
774
+ },
775
+ map(f) {
776
+ return this.toArray().map(f);
777
+ },
778
+ toString() {
779
+ return this.toArray().toString();
780
+ },
781
+ toLocaleString() {
782
+ return this.toArray().toLocaleString();
783
+ },
784
+ forEach(f) {
785
+ return this.toArray().forEach(f);
786
+ },
787
+ // todo: real concat function is different
788
+ concat(other) {
789
+ return this.toArray().concat(other);
790
+ },
791
+ every(f) {
792
+ return this.toArray().every(f);
793
+ },
794
+ filter(f) {
795
+ return this.toArray().filter(f);
796
+ },
797
+ find(f) {
798
+ let index = 0;
799
+ for (const v of this) {
800
+ if (f(v, index)) {
801
+ return v;
802
+ }
803
+ index += 1;
804
+ }
805
+ },
806
+ findIndex(f) {
807
+ let index = 0;
808
+ for (const v of this) {
809
+ if (f(v, index)) {
810
+ return index;
811
+ }
812
+ index += 1;
813
+ }
814
+ return -1;
815
+ },
816
+ includes(elem) {
817
+ return this.find(e => e === elem) !== undefined;
818
+ },
819
+ join(sep) {
820
+ return this.toArray().join(sep);
821
+ },
822
+ reduce(f, initialValue) {
823
+ return this.toArray().reduce(f, initialValue);
824
+ },
825
+ reduceRight(f, initialValue) {
826
+ return this.toArray().reduceRight(f, initialValue);
827
+ },
828
+ lastIndexOf(search, fromIndex = +Infinity) {
829
+ // this can be faster
830
+ return this.toArray().lastIndexOf(search, fromIndex);
831
+ },
832
+ slice(index, num) {
833
+ return this.toArray().slice(index, num);
834
+ },
835
+ some(f) {
836
+ let index = 0;
837
+ for (const v of this) {
838
+ if (f(v, index)) {
839
+ return true;
840
+ }
841
+ index += 1;
842
+ }
843
+ return false;
844
+ },
845
+ [Symbol.iterator]: function* () {
846
+ let i = 0;
847
+ let value = valueAt(target, i);
848
+ while (value !== undefined) {
849
+ yield value;
850
+ i += 1;
851
+ value = valueAt(target, i);
852
+ }
853
+ },
854
+ };
855
+ return methods;
856
+ }
857
+ function textMethods(target) {
858
+ const { context, objectId } = target;
859
+ const methods = {
860
+ set(index, value) {
861
+ return (this[index] = value);
862
+ },
863
+ get(index) {
864
+ return this[index];
865
+ },
866
+ toString() {
867
+ return context.text(objectId).replace(//g, "");
868
+ },
869
+ toSpans() {
870
+ const spans = [];
871
+ let chars = "";
872
+ const length = context.length(objectId);
873
+ for (let i = 0; i < length; i++) {
874
+ const value = this[i];
875
+ if (typeof value === "string") {
876
+ chars += value;
877
+ }
878
+ else {
879
+ if (chars.length > 0) {
880
+ spans.push(chars);
881
+ chars = "";
882
+ }
883
+ spans.push(value);
884
+ }
885
+ }
886
+ if (chars.length > 0) {
887
+ spans.push(chars);
888
+ }
889
+ return spans;
890
+ },
891
+ toJSON() {
892
+ return this.toString();
893
+ },
894
+ indexOf(o, start = 0) {
895
+ const text = context.text(objectId);
896
+ return text.indexOf(o, start);
897
+ },
898
+ insertAt(index, ...values) {
899
+ if (values.every(v => typeof v === "string")) {
900
+ context.splice(objectId, index, 0, values.join(""));
901
+ }
902
+ else {
903
+ listMethods(target).insertAt(index, ...values);
904
+ }
905
+ },
906
+ };
907
+ return methods;
908
+ }
909
+ function printPath(path) {
910
+ // print the path as a json pointer
911
+ const jsonPointerComponents = path.map(component => {
912
+ // if its a number just turn it into a string
913
+ if (typeof component === "number") {
914
+ return component.toString();
915
+ }
916
+ else if (typeof component === "string") {
917
+ // otherwise we have to escape `/` and `~` characters
918
+ return component.replace(/~/g, "~0").replace(/\//g, "~1");
919
+ }
920
+ });
921
+ if (path.length === 0) {
922
+ return "";
923
+ }
924
+ else {
925
+ return "/" + jsonPointerComponents.join("/");
572
926
  }
573
- };
574
927
  }
575
- function M(t) {
576
- const e = t.map((r) => {
577
- if (typeof r == "number")
578
- return r.toString();
579
- if (typeof r == "string")
580
- return r.replace(/~/g, "~0").replace(/\//g, "~1");
581
- });
582
- return t.length === 0 ? "" : "/" + e.join("/");
583
- }
584
- function pe(t) {
585
- return typeof t == "object" && t !== null && Object.prototype.hasOwnProperty.call(t, W);
586
- }
587
- function he(t) {
588
- return typeof t == "object" && t !== null && Object.prototype.hasOwnProperty.call(t, T);
589
- }
590
- let B;
591
- const v = typeof TextEncoder < "u" ? new TextEncoder("utf-8") : { encode: () => {
592
- throw Error("TextEncoder not available");
593
- } };
594
- v.encodeInto;
595
- const be = typeof TextDecoder < "u" ? new TextDecoder("utf-8", { ignoreBOM: !0, fatal: !0 }) : { decode: () => {
596
- throw Error("TextDecoder not available");
597
- } };
598
- typeof TextDecoder < "u" && be.decode();
599
- typeof FinalizationRegistry > "u" || new FinalizationRegistry((t) => B.__wbg_automerge_free(t >>> 0, 1));
600
- typeof FinalizationRegistry > "u" || new FinalizationRegistry((t) => B.__wbg_syncstate_free(t >>> 0, 1));
601
- function j(t, e = !0) {
602
- if (typeof t != "object")
603
- throw new RangeError("must be the document root");
604
- const r = Reflect.get(t, m);
605
- if (r === void 0 || r == null || e && x(t) !== "_root")
606
- throw new RangeError("must be the document root");
607
- return r;
608
- }
609
- function ge(t) {
610
- Reflect.set(t, A, !0);
611
- }
612
- function x(t) {
613
- return typeof t != "object" || t === null ? null : Reflect.get(t, y);
614
- }
615
- function k(t) {
616
- return !!Reflect.get(t, O);
617
- }
618
- function ye(t, e) {
619
- let r = Ee(t, e.path);
620
- if (e.action === "put")
621
- me(t, r, e);
622
- else if (e.action === "insert")
623
- de(t, r, e);
624
- else if (e.action === "del")
625
- we(t, r, e);
626
- else if (e.action === "splice")
627
- je(t, r, e);
628
- else if (e.action === "inc")
629
- Re(t, r, e);
630
- else if (e.action === "mark")
631
- Se(t, r, e);
632
- else if (e.action === "unmark")
633
- Oe(t, r, e);
634
- else if (e.action !== "conflict") throw new RangeError(`unsupported patch: ${e}`);
635
- }
636
- function me(t, e, r) {
637
- let { obj: o, prop: s } = b(e, -1);
638
- o[s] = r.value;
639
- }
640
- function de(t, e, r) {
641
- let { obj: o, prop: s } = b(e, -1);
642
- if (!Array.isArray(o))
643
- throw new RangeError("target is not an array for patch");
644
- if (typeof s != "number")
645
- throw new RangeError("index is not a number for patch");
646
- o.splice(s, 0, ...r.values);
647
- }
648
- function we(t, e, r) {
649
- let { obj: o, prop: s, parentPath: n } = b(e, -1);
650
- if (typeof s != "number")
651
- throw new RangeError("index is not a number for patch");
652
- if (Array.isArray(o))
653
- o.splice(s, r.length || 1);
654
- else if (typeof o == "string")
655
- if (R(t))
656
- K(t, n, s, r.length || 1);
928
+ /*
929
+ * Check if an object is a {@link ImmutableString}
930
+ */
931
+ function isImmutableString(obj) {
932
+ // We used to determine whether something was a ImmutableString by doing an instanceof check, but
933
+ // this doesn't work if the automerge module is loaded twice somehow. Instead, use the presence
934
+ // of a symbol to determine if something is a ImmutableString
935
+ return (typeof obj === "object" &&
936
+ obj !== null &&
937
+ Object.prototype.hasOwnProperty.call(obj, IMMUTABLE_STRING));
938
+ }
939
+ function isCounter(obj) {
940
+ // We used to determine whether something was a Counter by doing an instanceof check, but
941
+ // this doesn't work if the automerge module is loaded twice somehow. Instead, use the presence
942
+ // of a symbol to determine if something is a Counter
943
+ return (typeof obj === "object" &&
944
+ obj !== null &&
945
+ Object.prototype.hasOwnProperty.call(obj, COUNTER));
946
+ }
947
+
948
+ let wasm;
949
+
950
+ const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
951
+
952
+ (typeof cachedTextEncoder.encodeInto === 'function'
953
+ ? function (arg, view) {
954
+ return cachedTextEncoder.encodeInto(arg, view);
955
+ }
956
+ : function (arg, view) {
957
+ const buf = cachedTextEncoder.encode(arg);
958
+ view.set(buf);
959
+ return {
960
+ read: arg.length,
961
+ written: buf.length
962
+ };
963
+ });
964
+
965
+ const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
966
+
967
+ if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); }
968
+ (typeof FinalizationRegistry === 'undefined')
969
+ ? { }
970
+ : new FinalizationRegistry(ptr => wasm.__wbg_automerge_free(ptr >>> 0, 1));
971
+
972
+ (typeof FinalizationRegistry === 'undefined')
973
+ ? { }
974
+ : new FinalizationRegistry(ptr => wasm.__wbg_syncstate_free(ptr >>> 0, 1));
975
+
976
+ function _state(doc, checkroot = true) {
977
+ if (typeof doc !== "object") {
978
+ throw new RangeError("must be the document root");
979
+ }
980
+ const state = Reflect.get(doc, STATE);
981
+ if (state === undefined ||
982
+ state == null ||
983
+ (checkroot && _obj(doc) !== "_root")) {
984
+ throw new RangeError("must be the document root");
985
+ }
986
+ return state;
987
+ }
988
+ function _clear_cache(doc) {
989
+ Reflect.set(doc, CLEAR_CACHE, true);
990
+ }
991
+ function _obj(doc) {
992
+ if (!(typeof doc === "object") || doc === null) {
993
+ return null;
994
+ }
995
+ return Reflect.get(doc, OBJECT_ID);
996
+ }
997
+ function _is_proxy(doc) {
998
+ return !!Reflect.get(doc, IS_PROXY);
999
+ }
1000
+
1001
+ function applyPatch(doc, patch) {
1002
+ let path = resolvePath(doc, patch.path);
1003
+ if (patch.action === "put") {
1004
+ applyPutPatch(doc, path, patch);
1005
+ }
1006
+ else if (patch.action === "insert") {
1007
+ applyInsertPatch(doc, path, patch);
1008
+ }
1009
+ else if (patch.action === "del") {
1010
+ applyDelPatch(doc, path, patch);
1011
+ }
1012
+ else if (patch.action === "splice") {
1013
+ applySplicePatch(doc, path, patch);
1014
+ }
1015
+ else if (patch.action === "inc") {
1016
+ applyIncPatch(doc, path, patch);
1017
+ }
1018
+ else if (patch.action === "mark") {
1019
+ applyMarkPatch(doc, path, patch);
1020
+ }
1021
+ else if (patch.action === "unmark") {
1022
+ applyUnmarkPatch(doc, path, patch);
1023
+ }
1024
+ else if (patch.action === "conflict") ;
657
1025
  else {
658
- let { obj: i, prop: u } = b(e, -2);
659
- if (typeof s != "number")
660
- throw new RangeError("index is not a number for patch");
661
- let a = i[u];
662
- if (a == null || typeof a != "string")
663
- throw new RangeError("target is not a string for patch");
664
- let f = a.slice(0, s) + a.slice(s + (r.length || 1));
665
- i[u] = f;
666
- }
667
- else
668
- throw new RangeError("target is not an array or string for patch");
669
- }
670
- function je(t, e, r) {
671
- if (R(t)) {
672
- let { obj: o, prop: s, parentPath: n } = b(e, -1);
673
- if (typeof s != "number")
674
- throw new RangeError("index is not a number for patch");
675
- K(t, n, s, 0, r.value);
676
- } else {
677
- let { obj: o, prop: s } = b(e, -1), { obj: n, prop: i } = b(e, -2);
678
- if (typeof s != "number")
679
- throw new RangeError("index is not a number for patch");
680
- let u = n[i];
681
- if (u == null || typeof u != "string")
682
- throw new RangeError("target is not a string for patch");
683
- let a = u.slice(0, s) + r.value + u.slice(s);
684
- n[i] = a;
685
- }
1026
+ throw new RangeError(`unsupported patch: ${patch}`);
1027
+ }
686
1028
  }
687
- function Re(t, e, r) {
688
- let { obj: o, prop: s } = b(e, -1);
689
- const n = o[s];
690
- if (R(t)) {
691
- if (!he(n))
692
- throw new RangeError("target is not a counter for patch");
693
- n.increment(r.value);
694
- } else {
695
- if (typeof n != "number")
696
- throw new RangeError("target is not a number for patch");
697
- o[s] = n + r.value;
698
- }
1029
+ function applyPutPatch(doc, path, patch) {
1030
+ let { obj: parent, prop } = pathElemAt(path, -1);
1031
+ parent[prop] = patch.value;
1032
+ }
1033
+ function applyInsertPatch(doc, path, patch) {
1034
+ let { obj: parent, prop } = pathElemAt(path, -1);
1035
+ if (!Array.isArray(parent)) {
1036
+ throw new RangeError(`target is not an array for patch`);
1037
+ }
1038
+ if (!(typeof prop === "number")) {
1039
+ throw new RangeError(`index is not a number for patch`);
1040
+ }
1041
+ parent.splice(prop, 0, ...patch.values);
1042
+ }
1043
+ function applyDelPatch(doc, path, patch) {
1044
+ let { obj: parent, prop, parentPath } = pathElemAt(path, -1);
1045
+ if (!(typeof prop === "number")) {
1046
+ throw new RangeError(`index is not a number for patch`);
1047
+ }
1048
+ if (Array.isArray(parent)) {
1049
+ parent.splice(prop, patch.length || 1);
1050
+ }
1051
+ else if (typeof parent === "string") {
1052
+ if (isAutomerge(doc)) {
1053
+ splice(doc, parentPath, prop, patch.length || 1);
1054
+ }
1055
+ else {
1056
+ let { obj: grandParent, prop: grandParentProp } = pathElemAt(path, -2);
1057
+ if (typeof prop !== "number") {
1058
+ throw new RangeError(`index is not a number for patch`);
1059
+ }
1060
+ let target = grandParent[grandParentProp];
1061
+ if (target == null || typeof target !== "string") {
1062
+ throw new RangeError(`target is not a string for patch`);
1063
+ }
1064
+ let newString = target.slice(0, prop) + target.slice(prop + (patch.length || 1));
1065
+ grandParent[grandParentProp] = newString;
1066
+ }
1067
+ }
1068
+ else {
1069
+ throw new RangeError(`target is not an array or string for patch`);
1070
+ }
1071
+ }
1072
+ function applySplicePatch(doc, path, patch) {
1073
+ if (isAutomerge(doc)) {
1074
+ let { obj: parent, prop, parentPath } = pathElemAt(path, -1);
1075
+ if (!(typeof prop === "number")) {
1076
+ throw new RangeError(`index is not a number for patch`);
1077
+ }
1078
+ splice(doc, parentPath, prop, 0, patch.value);
1079
+ }
1080
+ else {
1081
+ let { obj: parent, prop } = pathElemAt(path, -1);
1082
+ let { obj: grandParent, prop: grandParentProp } = pathElemAt(path, -2);
1083
+ if (typeof prop !== "number") {
1084
+ throw new RangeError(`index is not a number for patch`);
1085
+ }
1086
+ let target = grandParent[grandParentProp];
1087
+ if (target == null || typeof target !== "string") {
1088
+ throw new RangeError(`target is not a string for patch`);
1089
+ }
1090
+ let newString = target.slice(0, prop) + patch.value + target.slice(prop);
1091
+ grandParent[grandParentProp] = newString;
1092
+ }
699
1093
  }
700
- function Se(t, e, r) {
701
- let { obj: o, prop: s } = b(e, -1);
702
- if (R(t))
703
- for (const n of r.marks)
704
- Ae(
705
- t,
706
- r.path,
1094
+ function applyIncPatch(doc, path, patch) {
1095
+ let { obj: parent, prop } = pathElemAt(path, -1);
1096
+ const counter = parent[prop];
1097
+ if (isAutomerge(doc)) {
1098
+ if (!isCounter(counter)) {
1099
+ throw new RangeError(`target is not a counter for patch`);
1100
+ }
1101
+ counter.increment(patch.value);
1102
+ }
1103
+ else {
1104
+ if (!(typeof counter === "number")) {
1105
+ throw new RangeError(`target is not a number for patch`);
1106
+ }
1107
+ parent[prop] = counter + patch.value;
1108
+ }
1109
+ }
1110
+ function applyMarkPatch(doc, path, patch) {
1111
+ let { obj: parent, prop } = pathElemAt(path, -1);
1112
+ if (!isAutomerge(doc)) {
1113
+ return;
1114
+ }
1115
+ for (const markSpec of patch.marks) {
1116
+ mark(doc, patch.path,
707
1117
  // TODO: add mark expansion to patches. This will require emitting
708
1118
  // the expand values in patches.
709
- { start: n.start, end: n.end, expand: "none" },
710
- n.name,
711
- n.value
712
- );
713
- }
714
- function Oe(t, e, r) {
715
- R(t) && Te(t, r.path, { start: r.start, end: r.end, expand: "none" }, r.name);
716
- }
717
- function q(t, e) {
718
- for (const r of e)
719
- ye(t, r);
720
- }
721
- function Ee(t, e) {
722
- const r = [];
723
- let o = t, s = [];
724
- for (const [n, i] of e.entries())
725
- if (r.push({ obj: o, prop: i, parentPath: s.slice() }), s.push(i), n !== e.length - 1) {
726
- if (o == null || typeof o != "object")
727
- throw new Error(`Invalid path: ${e}`);
728
- o = o[i];
729
- } else
730
- break;
731
- return r;
732
- }
733
- function b(t, e) {
734
- let r = t.at(e);
735
- if (r == null)
736
- throw new Error("invalid path");
737
- return r;
738
- }
739
- function Pe(t, e, r) {
740
- if (typeof r == "string") {
741
- if (/^-?[0-9]+@[0-9a-zA-Z]+$|^[se]$/.test(r))
742
- return t.handle.getCursorPosition(e, r);
743
- throw new RangeError("index must be a number or cursor");
744
- } else
745
- return r;
746
- }
747
- function _e(t, e) {
748
- return x(t);
749
- }
750
- function ve(t, e, r) {
751
- N(e, "before"), N(r, "after");
752
- const o = j(t);
753
- return o.mostRecentPatch && I(o.mostRecentPatch.before, e) && I(o.mostRecentPatch.after, r) ? o.mostRecentPatch.patches : o.handle.diff(e, r);
754
- }
755
- function N(t, e) {
756
- if (!Array.isArray(t))
757
- throw new Error(`${e} must be an array`);
758
- }
759
- function I(t, e) {
760
- if (!U(t) || !U(e))
761
- return t === e;
762
- const r = Object.keys(t).sort(), o = Object.keys(e).sort();
763
- if (r.length !== o.length)
764
- return !1;
765
- for (let s = 0; s < r.length; s++)
766
- if (r[s] !== o[s] || !I(t[r[s]], e[o[s]]))
767
- return !1;
768
- return !0;
769
- }
770
- function Ie(t) {
771
- const e = j(t);
772
- return e.heads || e.handle.getHeads();
773
- }
774
- function R(t) {
775
- return typeof t == "object" && t !== null ? _e(t) === "_root" && !!Reflect.get(t, m) : !1;
776
- }
777
- function U(t) {
778
- return typeof t == "object" && t !== null;
779
- }
780
- function K(t, e, r, o, s) {
781
- const n = $(t, e, "splice");
782
- if (!k(t))
783
- throw new RangeError("object cannot be modified outside of a change block");
784
- const i = j(t, !1);
785
- ge(t), r = Pe(i, n, r);
786
- try {
787
- return i.handle.splice(n, r, o, s);
788
- } catch (u) {
789
- throw new RangeError(`Cannot splice: ${u}`);
790
- }
1119
+ { start: markSpec.start, end: markSpec.end, expand: "none" }, markSpec.name, markSpec.value);
1120
+ }
791
1121
  }
792
- function Ae(t, e, r, o, s) {
793
- const n = $(t, e, "mark");
794
- if (!k(t))
795
- throw new RangeError("object cannot be modified outside of a change block");
796
- const i = j(t, !1);
797
- try {
798
- return i.handle.mark(n, r, o, s);
799
- } catch (u) {
800
- throw new RangeError(`Cannot mark: ${u}`);
801
- }
1122
+ function applyUnmarkPatch(doc, path, patch) {
1123
+ if (!isAutomerge(doc)) {
1124
+ return;
1125
+ }
1126
+ unmark(doc, patch.path, { start: patch.start, end: patch.end, expand: "none" }, patch.name);
802
1127
  }
803
- function Te(t, e, r, o) {
804
- const s = $(t, e, "unmark");
805
- if (!k(t))
806
- throw new RangeError("object cannot be modified outside of a change block");
807
- const n = j(t, !1);
808
- try {
809
- return n.handle.unmark(s, r, o);
810
- } catch (i) {
811
- throw new RangeError(`Cannot unmark: ${i}`);
812
- }
1128
+ function applyPatches(doc, patches) {
1129
+ for (const patch of patches) {
1130
+ applyPatch(doc, patch);
1131
+ }
1132
+ }
1133
+ /**
1134
+ * Walk through a path with an object and for each element in the path return a resolved path element.
1135
+ *
1136
+ * A resolved path element looks like this:
1137
+ *
1138
+ * ```typescript
1139
+ * {
1140
+ * obj: any, // The object that this element in the path is a property of
1141
+ * prop: Prop, // The property within `obj` that this path element points at
1142
+ * parentPath: Prop[] // The path to `obj` within the original `doc` passed to `resolvePath`
1143
+ * }
1144
+ * ````
1145
+ *
1146
+ * For example, given an object like this:
1147
+ *
1148
+ * ```typescript
1149
+ * {
1150
+ * todos: [{ task: "remember the milk"}]
1151
+ * }
1152
+ * ```
1153
+ *
1154
+ * Then `resolvePath(doc, ["todos", 0, "task"])` would return:
1155
+ *
1156
+ * ```typescript
1157
+ * [
1158
+ * { obj: { todos: [{ task: "remember the milk"}] }, prop: "todos", parentPath: [] },
1159
+ * { obj: [{ task: "remember the milk"}], prop: 0, parentPath: ["todos"] },
1160
+ * { obj: { task: "remember the milk" }, prop: "task", parentPath: ["todos", 0] }
1161
+ * ]
1162
+ * ```
1163
+ */
1164
+ function resolvePath(doc, path) {
1165
+ const result = [];
1166
+ let current = doc;
1167
+ let currentPath = [];
1168
+ for (const [index, prop] of path.entries()) {
1169
+ result.push({ obj: current, prop, parentPath: currentPath.slice() });
1170
+ currentPath.push(prop);
1171
+ if (index !== path.length - 1) {
1172
+ if (current == null || typeof current != "object") {
1173
+ // If we're not the last item in the path then we need the current
1174
+ // object to be an object so we can access it in the next iteration
1175
+ throw new Error(`Invalid path: ${path}`);
1176
+ }
1177
+ current = current[prop];
1178
+ }
1179
+ else {
1180
+ break;
1181
+ }
1182
+ }
1183
+ return result;
1184
+ }
1185
+ /**
1186
+ * Get an element from a resolved path, throwing an exception if the element does not exist
1187
+ *
1188
+ * @param resolved - The path to lookup in
1189
+ * @param index - The index of the element to lookup, negative indices search backwards
1190
+ */
1191
+ function pathElemAt(resolved, index) {
1192
+ let result = resolved.at(index);
1193
+ if (result == undefined) {
1194
+ throw new Error("invalid path");
1195
+ }
1196
+ return result;
1197
+ }
1198
+
1199
+ (undefined && undefined.__rest) || function (s, e) {
1200
+ var t = {};
1201
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
1202
+ t[p] = s[p];
1203
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
1204
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
1205
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
1206
+ t[p[i]] = s[p[i]];
1207
+ }
1208
+ return t;
1209
+ };
1210
+ function cursorToIndex(state, value, index) {
1211
+ if (typeof index == "string") {
1212
+ if (/^-?[0-9]+@[0-9a-zA-Z]+$|^[se]$/.test(index)) {
1213
+ return state.handle.getCursorPosition(value, index);
1214
+ }
1215
+ else {
1216
+ throw new RangeError("index must be a number or cursor");
1217
+ }
1218
+ }
1219
+ else {
1220
+ return index;
1221
+ }
1222
+ }
1223
+ /**
1224
+ * Return the object ID of an arbitrary javascript value
1225
+ *
1226
+ * This is useful to determine if something is actually an automerge document,
1227
+ * if `doc` is not an automerge document this will return null.
1228
+ */
1229
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1230
+ function getObjectId(doc, prop) {
1231
+ {
1232
+ return _obj(doc);
1233
+ }
1234
+ }
1235
+ /**
1236
+ * Create a set of patches representing the change from one set of heads to another
1237
+ *
1238
+ * If either of the heads are missing from the document the returned set of patches will be empty
1239
+ */
1240
+ function diff(doc, before, after) {
1241
+ checkHeads(before, "before");
1242
+ checkHeads(after, "after");
1243
+ const state = _state(doc);
1244
+ if (state.mostRecentPatch &&
1245
+ equals(state.mostRecentPatch.before, before) &&
1246
+ equals(state.mostRecentPatch.after, after)) {
1247
+ return state.mostRecentPatch.patches;
1248
+ }
1249
+ return state.handle.diff(before, after);
1250
+ }
1251
+ function checkHeads(heads, fieldname) {
1252
+ if (!Array.isArray(heads)) {
1253
+ throw new Error(`${fieldname} must be an array`);
1254
+ }
1255
+ }
1256
+ /** @hidden */
1257
+ // FIXME : no tests
1258
+ // FIXME can we just use deep equals now?
1259
+ function equals(val1, val2) {
1260
+ if (!isObject(val1) || !isObject(val2))
1261
+ return val1 === val2;
1262
+ const keys1 = Object.keys(val1).sort(), keys2 = Object.keys(val2).sort();
1263
+ if (keys1.length !== keys2.length)
1264
+ return false;
1265
+ for (let i = 0; i < keys1.length; i++) {
1266
+ if (keys1[i] !== keys2[i])
1267
+ return false;
1268
+ if (!equals(val1[keys1[i]], val2[keys2[i]]))
1269
+ return false;
1270
+ }
1271
+ return true;
1272
+ }
1273
+ /**
1274
+ * Get the hashes of the heads of this document
1275
+ */
1276
+ function getHeads(doc) {
1277
+ const state = _state(doc);
1278
+ return state.heads || state.handle.getHeads();
1279
+ }
1280
+ function isAutomerge(doc) {
1281
+ if (typeof doc == "object" && doc !== null) {
1282
+ return getObjectId(doc) === "_root" && !!Reflect.get(doc, STATE);
1283
+ }
1284
+ else {
1285
+ return false;
1286
+ }
1287
+ }
1288
+ function isObject(obj) {
1289
+ return typeof obj === "object" && obj !== null;
1290
+ }
1291
+ /**
1292
+ * Modify a string
1293
+ *
1294
+ * @typeParam T - The type of the value contained in the document
1295
+ * @param doc - The document to modify
1296
+ * @param path - The path to the string to modify
1297
+ * @param index - The position (as a {@link Cursor} or index) to edit.
1298
+ * If a cursor is used then the edit happens such that the cursor will
1299
+ * now point to the end of the newText, so you can continue to reuse
1300
+ * the same cursor for multiple calls to splice.
1301
+ * @param del - The number of code units to delete, a positive number
1302
+ * deletes N characters after the cursor, a negative number deletes
1303
+ * N characters before the cursor.
1304
+ * @param newText - The string to insert (if any).
1305
+ */
1306
+ function splice(doc, path, index, del, newText) {
1307
+ const objPath = absoluteObjPath(doc, path, "splice");
1308
+ if (!_is_proxy(doc)) {
1309
+ throw new RangeError("object cannot be modified outside of a change block");
1310
+ }
1311
+ const state = _state(doc, false);
1312
+ _clear_cache(doc);
1313
+ index = cursorToIndex(state, objPath, index);
1314
+ try {
1315
+ return state.handle.splice(objPath, index, del, newText);
1316
+ }
1317
+ catch (e) {
1318
+ throw new RangeError(`Cannot splice: ${e}`);
1319
+ }
1320
+ }
1321
+ function mark(doc, path, range, name, value) {
1322
+ const objPath = absoluteObjPath(doc, path, "mark");
1323
+ if (!_is_proxy(doc)) {
1324
+ throw new RangeError("object cannot be modified outside of a change block");
1325
+ }
1326
+ const state = _state(doc, false);
1327
+ try {
1328
+ return state.handle.mark(objPath, range, name, value);
1329
+ }
1330
+ catch (e) {
1331
+ throw new RangeError(`Cannot mark: ${e}`);
1332
+ }
1333
+ }
1334
+ function unmark(doc, path, range, name) {
1335
+ const objPath = absoluteObjPath(doc, path, "unmark");
1336
+ if (!_is_proxy(doc)) {
1337
+ throw new RangeError("object cannot be modified outside of a change block");
1338
+ }
1339
+ const state = _state(doc, false);
1340
+ try {
1341
+ return state.handle.unmark(objPath, range, name);
1342
+ }
1343
+ catch (e) {
1344
+ throw new RangeError(`Cannot unmark: ${e}`);
1345
+ }
1346
+ }
1347
+ function absoluteObjPath(doc, path, functionName) {
1348
+ path = path.slice();
1349
+ const objectId = _obj(doc);
1350
+ if (!objectId) {
1351
+ throw new RangeError(`invalid object for ${functionName}`);
1352
+ }
1353
+ path.unshift(objectId);
1354
+ return path.join("/");
1355
+ }
1356
+
1357
+ function autoproduce(payload) {
1358
+ return (doc) => applyPatches(doc, payload.patches);
1359
+ }
1360
+
1361
+ const cache = /* @__PURE__ */ new WeakMap();
1362
+ function initial(handle) {
1363
+ const template = {};
1364
+ applyPatches(template, diff(handle.doc(), [], getHeads(handle.doc())));
1365
+ return template;
813
1366
  }
814
- function $(t, e, r) {
815
- e = e.slice();
816
- const o = x(t);
817
- if (!o)
818
- throw new RangeError(`invalid object for ${r}`);
819
- return e.unshift(o), e.join("/");
820
- }
821
- function Ce(t) {
822
- return (e) => q(e, t.patches);
823
- }
824
- const d = /* @__PURE__ */ new WeakMap();
825
- function xe(t) {
826
- const e = {};
827
- return q(e, ve(t.doc(), [], Ie(t.doc()))), e;
828
- }
829
- function ke(t) {
830
- if (Y(() => {
831
- const n = d.get(t);
832
- n && (n.refs-- || n.cleanup());
833
- }), d.has(t)) {
834
- const n = d.get(t);
835
- return n.refs++, n.store;
1367
+ function makeDocumentProjection(handle) {
1368
+ onCleanup(() => {
1369
+ const item = cache.get(handle);
1370
+ if (!item) return;
1371
+ if (!item.refs--) {
1372
+ item.cleanup();
1373
+ }
1374
+ });
1375
+ if (cache.has(handle)) {
1376
+ const item = cache.get(handle);
1377
+ item.refs++;
1378
+ return item.store;
836
1379
  }
837
- const [e, r] = ee(xe(t));
838
- d.set(t, {
1380
+ const [doc, set] = createStore(initial(handle));
1381
+ cache.set(handle, {
839
1382
  refs: 0,
840
- store: e,
1383
+ store: doc,
841
1384
  cleanup() {
842
- t.off("change", o), t.off("delete", s), d.delete(t);
1385
+ handle.off("change", patch);
1386
+ handle.off("delete", ondelete);
1387
+ cache.delete(handle);
843
1388
  }
844
1389
  });
845
- function o(n) {
846
- r(te(Ce(n)));
1390
+ function patch(payload) {
1391
+ set(produce(autoproduce(payload)));
847
1392
  }
848
- function s() {
849
- r(re({}));
1393
+ function ondelete() {
1394
+ set(reconcile({}));
850
1395
  }
851
- return t.on("change", o), t.on("delete", s), e;
1396
+ handle.on("change", patch);
1397
+ handle.on("delete", ondelete);
1398
+ return doc;
852
1399
  }
853
- function $e(t) {
854
- return G(() => {
855
- const r = typeof t == "function" ? t() : t;
856
- return r && ke(r);
1400
+
1401
+ function createDocumentProjection(handle) {
1402
+ const projection = createMemo(() => {
1403
+ const unwrappedHandle = typeof handle == "function" ? handle() : handle;
1404
+ return unwrappedHandle && makeDocumentProjection(unwrappedHandle);
857
1405
  });
1406
+ return projection;
858
1407
  }
859
- const V = X(
1408
+
1409
+ const RepoContext = createContext(
860
1410
  null
861
- ), H = ["ready", "deleted", "unavailable"], Le = ["deleted", "unavailable"];
862
- function De(t, e) {
863
- const r = J(V);
864
- if (!e?.repo && !r)
1411
+ );
1412
+
1413
+ const readyStates = ["ready", "deleted", "unavailable"];
1414
+ const badStates = ["deleted", "unavailable"];
1415
+ function useDocHandle(url, options) {
1416
+ const contextRepo = useContext(RepoContext);
1417
+ if (!options?.repo && !contextRepo) {
865
1418
  throw new Error("use outside <RepoContext> requires options.repo");
866
- const o = e?.repo || r;
867
- function s() {
868
- if (e?.["~skipInitialValue"]) return;
869
- const u = typeof t == "function" ? t() : t;
870
- if (u)
871
- try {
872
- const a = new URL(u).pathname, f = o.handles[a];
873
- if (f?.isReady())
874
- return f;
875
- } catch (a) {
876
- console.error("Error parsing URL:", a);
1419
+ }
1420
+ const repo = options?.repo || contextRepo;
1421
+ function getExistingHandle() {
1422
+ if (options?.["~skipInitialValue"]) return void 0;
1423
+ const unwrappedURL = typeof url == "function" ? url() : url;
1424
+ if (!unwrappedURL) return void 0;
1425
+ try {
1426
+ const documentId = new URL(unwrappedURL).pathname;
1427
+ const existingHandle = repo.handles[documentId];
1428
+ if (existingHandle?.isReady()) {
1429
+ return existingHandle;
877
1430
  }
1431
+ } catch (error) {
1432
+ console.error("Error parsing URL:", error);
1433
+ }
878
1434
  }
879
- const [n, { mutate: i }] = Z(
880
- t,
881
- async (u) => {
882
- const a = await o.find(u, {
883
- allowableStates: H
884
- }), f = (c) => Promise.reject(new Error(`document not available: [${c}]`));
885
- return a.isReady() ? a : a.inState(Le) ? f(a.state) : a.whenReady(H).then(() => a.isReady() ? a : f(a.state));
1435
+ const [handle, { mutate }] = createResource(
1436
+ url,
1437
+ async (url2) => {
1438
+ const handle2 = await repo.find(url2, {
1439
+ allowableStates: readyStates
1440
+ });
1441
+ const reject = (state) => Promise.reject(new Error(`document not available: [${state}]`));
1442
+ if (handle2.isReady()) {
1443
+ return handle2;
1444
+ } else if (handle2.inState(badStates)) {
1445
+ return reject(handle2.state);
1446
+ }
1447
+ return handle2.whenReady(readyStates).then(() => {
1448
+ if (handle2.isReady()) {
1449
+ return handle2;
1450
+ }
1451
+ return reject(handle2.state);
1452
+ });
886
1453
  },
887
1454
  {
888
- initialValue: s()
1455
+ initialValue: getExistingHandle()
889
1456
  }
890
1457
  );
891
- return Q(() => {
892
- (typeof t == "function" ? t() : t) || i();
893
- }), n;
894
- }
895
- function Ue(t, e) {
896
- const r = De(t, e);
897
- return [$e(r), r];
898
- }
899
- function He() {
900
- const t = J(V);
901
- if (!t) throw new Error("Please wrap me in a <RepoContext value={repo}>");
902
- return t;
903
- }
904
- export {
905
- V as RepoContext,
906
- Ce as autoproduce,
907
- $e as createDocumentProjection,
908
- ke as makeDocumentProjection,
909
- De as useDocHandle,
910
- Ue as useDocument,
911
- He as useRepo
912
- };
1458
+ createEffect(() => {
1459
+ const unwrappedURL = typeof url == "function" ? url() : url;
1460
+ if (!unwrappedURL) {
1461
+ mutate();
1462
+ }
1463
+ });
1464
+ return handle;
1465
+ }
1466
+
1467
+ function useDocument(url, options) {
1468
+ const handle = useDocHandle(url, options);
1469
+ return [createDocumentProjection(handle), handle];
1470
+ }
1471
+
1472
+ function useRepo() {
1473
+ const repo = useContext(RepoContext);
1474
+ if (!repo) throw new Error("Please wrap me in a <RepoContext value={repo}>");
1475
+ return repo;
1476
+ }
1477
+
1478
+ export { RepoContext, autoproduce, createDocumentProjection, makeDocumentProjection, useDocHandle, useDocument, useRepo };
1479
+ //# sourceMappingURL=index.js.map