@kyneta/yjs-schema 1.2.0 → 1.3.1
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/README.md +3 -3
- package/dist/index.d.ts +82 -170
- package/dist/index.js +176 -260
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/bind-constraints.test.ts +5 -13
- package/src/__tests__/bind-yjs.test.ts +57 -46
- package/src/__tests__/create.test.ts +80 -56
- package/src/__tests__/reader.test.ts +3 -14
- package/src/__tests__/record-text-spike.test.ts +38 -36
- package/src/__tests__/substrate.test.ts +47 -40
- package/src/bind-yjs.ts +9 -40
- package/src/change-mapping.ts +7 -2
- package/src/index.ts +24 -26
- package/src/native-map.ts +37 -0
- package/src/populate.ts +1 -1
- package/src/substrate.ts +19 -4
- package/src/version.ts +14 -67
- package/src/yjs-resolve.ts +1 -1
- package/src/create.ts +0 -177
- package/src/sync.ts +0 -107
package/dist/index.js
CHANGED
|
@@ -2,40 +2,150 @@
|
|
|
2
2
|
import {
|
|
3
3
|
applyChanges,
|
|
4
4
|
change,
|
|
5
|
+
createDoc,
|
|
6
|
+
createRef,
|
|
7
|
+
exportEntirety,
|
|
8
|
+
exportSince,
|
|
9
|
+
merge,
|
|
10
|
+
NATIVE,
|
|
5
11
|
Schema,
|
|
6
12
|
subscribe,
|
|
7
|
-
subscribeNode
|
|
13
|
+
subscribeNode,
|
|
14
|
+
unwrap,
|
|
15
|
+
version
|
|
8
16
|
} from "@kyneta/schema";
|
|
9
17
|
|
|
10
|
-
// src/
|
|
18
|
+
// src/bind-yjs.ts
|
|
11
19
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
registerSubstrate,
|
|
16
|
-
writable
|
|
20
|
+
BACKING_DOC as BACKING_DOC2,
|
|
21
|
+
createSubstrateNamespace,
|
|
22
|
+
STRUCTURAL_YJS_CLIENT_ID as STRUCTURAL_YJS_CLIENT_ID2
|
|
17
23
|
} from "@kyneta/schema";
|
|
24
|
+
import * as Y6 from "yjs";
|
|
25
|
+
|
|
26
|
+
// src/populate.ts
|
|
27
|
+
import { KIND, STRUCTURAL_YJS_CLIENT_ID, Zero } from "@kyneta/schema";
|
|
28
|
+
import * as Y from "yjs";
|
|
29
|
+
function ensureContainers(doc, schema, conditional = false) {
|
|
30
|
+
const rootMap = doc.getMap("root");
|
|
31
|
+
if (schema[KIND] !== "product") {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const savedClientID = doc.clientID;
|
|
35
|
+
doc.clientID = STRUCTURAL_YJS_CLIENT_ID;
|
|
36
|
+
try {
|
|
37
|
+
doc.transact(() => {
|
|
38
|
+
for (const [key, fieldSchema] of Object.entries(schema.fields).sort(
|
|
39
|
+
([a], [b]) => a.localeCompare(b)
|
|
40
|
+
)) {
|
|
41
|
+
if (conditional && rootMap.has(key)) continue;
|
|
42
|
+
ensureRootField(rootMap, key, fieldSchema);
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
} finally {
|
|
46
|
+
doc.clientID = savedClientID;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function ensureRootField(rootMap, key, fieldSchema) {
|
|
50
|
+
switch (fieldSchema[KIND]) {
|
|
51
|
+
case "text":
|
|
52
|
+
rootMap.set(key, new Y.Text());
|
|
53
|
+
return;
|
|
54
|
+
case "product":
|
|
55
|
+
rootMap.set(key, ensureMapContainers(fieldSchema));
|
|
56
|
+
return;
|
|
57
|
+
case "sequence":
|
|
58
|
+
rootMap.set(key, new Y.Array());
|
|
59
|
+
return;
|
|
60
|
+
case "map":
|
|
61
|
+
rootMap.set(key, new Y.Map());
|
|
62
|
+
return;
|
|
63
|
+
case "scalar":
|
|
64
|
+
case "sum": {
|
|
65
|
+
const zero = Zero.structural(fieldSchema);
|
|
66
|
+
if (zero !== void 0) {
|
|
67
|
+
rootMap.set(key, zero);
|
|
68
|
+
}
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
case "counter":
|
|
72
|
+
case "set":
|
|
73
|
+
case "tree":
|
|
74
|
+
case "movable":
|
|
75
|
+
throw new Error(
|
|
76
|
+
`Yjs substrate does not support [KIND]="${fieldSchema[KIND]}". Supported kinds: text, product, sequence, map, scalar, sum. Encountered unsupported kind at root field "${key}".`
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function ensureMapContainers(schema) {
|
|
81
|
+
const map = new Y.Map();
|
|
82
|
+
if (schema[KIND] !== "product") return map;
|
|
83
|
+
for (const [key, fieldSchema] of Object.entries(
|
|
84
|
+
schema.fields
|
|
85
|
+
).sort(([a], [b]) => a.localeCompare(b))) {
|
|
86
|
+
switch (fieldSchema[KIND]) {
|
|
87
|
+
case "text":
|
|
88
|
+
map.set(key, new Y.Text());
|
|
89
|
+
break;
|
|
90
|
+
case "product":
|
|
91
|
+
map.set(key, ensureMapContainers(fieldSchema));
|
|
92
|
+
break;
|
|
93
|
+
case "sequence":
|
|
94
|
+
map.set(key, new Y.Array());
|
|
95
|
+
break;
|
|
96
|
+
case "map":
|
|
97
|
+
map.set(key, new Y.Map());
|
|
98
|
+
break;
|
|
99
|
+
case "scalar":
|
|
100
|
+
case "sum": {
|
|
101
|
+
const zero = Zero.structural(fieldSchema);
|
|
102
|
+
if (zero !== void 0) {
|
|
103
|
+
map.set(key, zero);
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
case "counter":
|
|
108
|
+
case "set":
|
|
109
|
+
case "tree":
|
|
110
|
+
case "movable":
|
|
111
|
+
throw new Error(
|
|
112
|
+
`Yjs substrate does not support [KIND]="${fieldSchema[KIND]}". Supported kinds: text, product, sequence, map, scalar, sum. Encountered unsupported kind at nested field "${key}".`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return map;
|
|
117
|
+
}
|
|
18
118
|
|
|
19
119
|
// src/substrate.ts
|
|
20
|
-
import {
|
|
120
|
+
import {
|
|
121
|
+
BACKING_DOC,
|
|
122
|
+
buildWritableContext,
|
|
123
|
+
executeBatch,
|
|
124
|
+
KIND as KIND3
|
|
125
|
+
} from "@kyneta/schema";
|
|
21
126
|
import * as Y5 from "yjs";
|
|
22
127
|
|
|
23
128
|
// src/change-mapping.ts
|
|
24
|
-
import {
|
|
25
|
-
|
|
129
|
+
import {
|
|
130
|
+
advanceSchema as advanceSchema2,
|
|
131
|
+
expandMapOpsToLeaves,
|
|
132
|
+
KIND as KIND2,
|
|
133
|
+
RawPath
|
|
134
|
+
} from "@kyneta/schema";
|
|
135
|
+
import * as Y3 from "yjs";
|
|
26
136
|
|
|
27
137
|
// src/yjs-resolve.ts
|
|
28
138
|
import { advanceSchema } from "@kyneta/schema";
|
|
29
|
-
import * as
|
|
139
|
+
import * as Y2 from "yjs";
|
|
30
140
|
function stepIntoYjs(current, segment) {
|
|
31
141
|
const resolved = segment.resolve();
|
|
32
|
-
if (current instanceof
|
|
142
|
+
if (current instanceof Y2.Map) {
|
|
33
143
|
return current.get(resolved);
|
|
34
144
|
}
|
|
35
|
-
if (current instanceof
|
|
145
|
+
if (current instanceof Y2.Array) {
|
|
36
146
|
return current.get(resolved);
|
|
37
147
|
}
|
|
38
|
-
if (current instanceof
|
|
148
|
+
if (current instanceof Y2.Text) {
|
|
39
149
|
throw new Error(`yjs-resolve: cannot step into Y.Text`);
|
|
40
150
|
}
|
|
41
151
|
return void 0;
|
|
@@ -83,7 +193,7 @@ function applyChangeToYjs(rootMap, rootSchema, path, change2) {
|
|
|
83
193
|
}
|
|
84
194
|
function applyTextChange(rootMap, rootSchema, path, change2) {
|
|
85
195
|
const resolved = resolveYjsType(rootMap, rootSchema, path);
|
|
86
|
-
if (!(resolved instanceof
|
|
196
|
+
if (!(resolved instanceof Y3.Text)) {
|
|
87
197
|
throw new Error(
|
|
88
198
|
`applyChangeToYjs: TextChange target at path [${pathToString(path)}] is not a Y.Text`
|
|
89
199
|
);
|
|
@@ -92,7 +202,7 @@ function applyTextChange(rootMap, rootSchema, path, change2) {
|
|
|
92
202
|
}
|
|
93
203
|
function applySequenceChange(rootMap, rootSchema, path, change2) {
|
|
94
204
|
const resolved = resolveYjsType(rootMap, rootSchema, path);
|
|
95
|
-
if (!(resolved instanceof
|
|
205
|
+
if (!(resolved instanceof Y3.Array)) {
|
|
96
206
|
throw new Error(
|
|
97
207
|
`applyChangeToYjs: SequenceChange target at path [${pathToString(path)}] is not a Y.Array`
|
|
98
208
|
);
|
|
@@ -117,7 +227,7 @@ function applySequenceChange(rootMap, rootSchema, path, change2) {
|
|
|
117
227
|
}
|
|
118
228
|
function applyMapChange(rootMap, rootSchema, path, change2) {
|
|
119
229
|
const resolved = resolveYjsType(rootMap, rootSchema, path);
|
|
120
|
-
if (!(resolved instanceof
|
|
230
|
+
if (!(resolved instanceof Y3.Map)) {
|
|
121
231
|
throw new Error(
|
|
122
232
|
`applyChangeToYjs: MapChange target at path [${pathToString(path)}] is not a Y.Map`
|
|
123
233
|
);
|
|
@@ -146,11 +256,11 @@ function applyReplaceChange(rootMap, rootSchema, path, change2) {
|
|
|
146
256
|
const parentPath = path.slice(0, -1);
|
|
147
257
|
const parent = resolveYjsType(rootMap, rootSchema, parentPath);
|
|
148
258
|
const resolved = lastSeg.resolve();
|
|
149
|
-
if (parent instanceof
|
|
259
|
+
if (parent instanceof Y3.Map && lastSeg.role === "key") {
|
|
150
260
|
const targetSchema = resolveSchemaAtPath(rootSchema, path);
|
|
151
261
|
const yjsValue = maybeCreateSharedType(change2.value, targetSchema);
|
|
152
262
|
parent.set(resolved, yjsValue);
|
|
153
|
-
} else if (parent instanceof
|
|
263
|
+
} else if (parent instanceof Y3.Array && lastSeg.role === "index") {
|
|
154
264
|
const targetSchema = resolveSchemaAtPath(rootSchema, path);
|
|
155
265
|
const yjsValue = maybeCreateSharedType(change2.value, targetSchema);
|
|
156
266
|
parent.delete(resolved, 1);
|
|
@@ -166,7 +276,7 @@ function maybeCreateSharedType(value, schema) {
|
|
|
166
276
|
switch (schema[KIND2]) {
|
|
167
277
|
// First-class text → Y.Text
|
|
168
278
|
case "text": {
|
|
169
|
-
const text = new
|
|
279
|
+
const text = new Y3.Text();
|
|
170
280
|
if (typeof value === "string" && value.length > 0) {
|
|
171
281
|
text.insert(0, value);
|
|
172
282
|
}
|
|
@@ -180,7 +290,7 @@ function maybeCreateSharedType(value, schema) {
|
|
|
180
290
|
}
|
|
181
291
|
case "sequence": {
|
|
182
292
|
if (!Array.isArray(value)) return value;
|
|
183
|
-
const arr = new
|
|
293
|
+
const arr = new Y3.Array();
|
|
184
294
|
const itemSchema = schema.item;
|
|
185
295
|
const items = value.map(
|
|
186
296
|
(item) => maybeCreateSharedType(item, itemSchema)
|
|
@@ -192,7 +302,7 @@ function maybeCreateSharedType(value, schema) {
|
|
|
192
302
|
if (value === null || value === void 0 || typeof value !== "object" || Array.isArray(value)) {
|
|
193
303
|
return value;
|
|
194
304
|
}
|
|
195
|
-
const map = new
|
|
305
|
+
const map = new Y3.Map();
|
|
196
306
|
const valueSchema = schema.item;
|
|
197
307
|
for (const [k, v] of Object.entries(value)) {
|
|
198
308
|
map.set(k, maybeCreateSharedType(v, valueSchema));
|
|
@@ -213,7 +323,7 @@ function maybeCreateSharedType(value, schema) {
|
|
|
213
323
|
}
|
|
214
324
|
}
|
|
215
325
|
function createStructuredMap(obj, productSchema) {
|
|
216
|
-
const map = new
|
|
326
|
+
const map = new Y3.Map();
|
|
217
327
|
if (productSchema[KIND2] !== "product") {
|
|
218
328
|
for (const [key, val] of Object.entries(obj)) {
|
|
219
329
|
map.set(key, val);
|
|
@@ -231,7 +341,7 @@ function createStructuredMap(obj, productSchema) {
|
|
|
231
341
|
)) {
|
|
232
342
|
if (key in obj) continue;
|
|
233
343
|
if (fieldSchema[KIND2] === "text") {
|
|
234
|
-
map.set(key, new
|
|
344
|
+
map.set(key, new Y3.Text());
|
|
235
345
|
}
|
|
236
346
|
}
|
|
237
347
|
return map;
|
|
@@ -259,13 +369,13 @@ function yjsPathToKynetaPath(yjsPath) {
|
|
|
259
369
|
return path;
|
|
260
370
|
}
|
|
261
371
|
function eventToChange(event) {
|
|
262
|
-
if (event.target instanceof
|
|
372
|
+
if (event.target instanceof Y3.Text) {
|
|
263
373
|
return textEventToChange(event);
|
|
264
374
|
}
|
|
265
|
-
if (event.target instanceof
|
|
375
|
+
if (event.target instanceof Y3.Array) {
|
|
266
376
|
return arrayEventToChange(event);
|
|
267
377
|
}
|
|
268
|
-
if (event.target instanceof
|
|
378
|
+
if (event.target instanceof Y3.Map) {
|
|
269
379
|
return mapEventToChange(event);
|
|
270
380
|
}
|
|
271
381
|
return null;
|
|
@@ -323,9 +433,9 @@ function mapEventToChange(event) {
|
|
|
323
433
|
};
|
|
324
434
|
}
|
|
325
435
|
function extractEventValue(value) {
|
|
326
|
-
if (value instanceof
|
|
327
|
-
if (value instanceof
|
|
328
|
-
if (value instanceof
|
|
436
|
+
if (value instanceof Y3.Map) return value.toJSON();
|
|
437
|
+
if (value instanceof Y3.Array) return value.toJSON();
|
|
438
|
+
if (value instanceof Y3.Text) return value.toJSON();
|
|
329
439
|
return value;
|
|
330
440
|
}
|
|
331
441
|
function resolveSchemaAtPath(rootSchema, path) {
|
|
@@ -356,99 +466,6 @@ function pathToString(path) {
|
|
|
356
466
|
return path.segments.map((seg) => String(seg.resolve())).join(".");
|
|
357
467
|
}
|
|
358
468
|
|
|
359
|
-
// src/populate.ts
|
|
360
|
-
import { KIND as KIND3, STRUCTURAL_YJS_CLIENT_ID, Zero } from "@kyneta/schema";
|
|
361
|
-
import * as Y3 from "yjs";
|
|
362
|
-
function ensureContainers(doc, schema, conditional = false) {
|
|
363
|
-
const rootMap = doc.getMap("root");
|
|
364
|
-
if (schema[KIND3] !== "product") {
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
const savedClientID = doc.clientID;
|
|
368
|
-
doc.clientID = STRUCTURAL_YJS_CLIENT_ID;
|
|
369
|
-
try {
|
|
370
|
-
doc.transact(() => {
|
|
371
|
-
for (const [key, fieldSchema] of Object.entries(schema.fields).sort(
|
|
372
|
-
([a], [b]) => a.localeCompare(b)
|
|
373
|
-
)) {
|
|
374
|
-
if (conditional && rootMap.has(key)) continue;
|
|
375
|
-
ensureRootField(rootMap, key, fieldSchema);
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
} finally {
|
|
379
|
-
doc.clientID = savedClientID;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
function ensureRootField(rootMap, key, fieldSchema) {
|
|
383
|
-
switch (fieldSchema[KIND3]) {
|
|
384
|
-
case "text":
|
|
385
|
-
rootMap.set(key, new Y3.Text());
|
|
386
|
-
return;
|
|
387
|
-
case "product":
|
|
388
|
-
rootMap.set(key, ensureMapContainers(fieldSchema));
|
|
389
|
-
return;
|
|
390
|
-
case "sequence":
|
|
391
|
-
rootMap.set(key, new Y3.Array());
|
|
392
|
-
return;
|
|
393
|
-
case "map":
|
|
394
|
-
rootMap.set(key, new Y3.Map());
|
|
395
|
-
return;
|
|
396
|
-
case "scalar":
|
|
397
|
-
case "sum": {
|
|
398
|
-
const zero = Zero.structural(fieldSchema);
|
|
399
|
-
if (zero !== void 0) {
|
|
400
|
-
rootMap.set(key, zero);
|
|
401
|
-
}
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
|
-
case "counter":
|
|
405
|
-
case "set":
|
|
406
|
-
case "tree":
|
|
407
|
-
case "movable":
|
|
408
|
-
throw new Error(
|
|
409
|
-
`Yjs substrate does not support [KIND]="${fieldSchema[KIND3]}". Supported kinds: text, product, sequence, map, scalar, sum. Encountered unsupported kind at root field "${key}".`
|
|
410
|
-
);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
function ensureMapContainers(schema) {
|
|
414
|
-
const map = new Y3.Map();
|
|
415
|
-
if (schema[KIND3] !== "product") return map;
|
|
416
|
-
for (const [key, fieldSchema] of Object.entries(
|
|
417
|
-
schema.fields
|
|
418
|
-
).sort(([a], [b]) => a.localeCompare(b))) {
|
|
419
|
-
switch (fieldSchema[KIND3]) {
|
|
420
|
-
case "text":
|
|
421
|
-
map.set(key, new Y3.Text());
|
|
422
|
-
break;
|
|
423
|
-
case "product":
|
|
424
|
-
map.set(key, ensureMapContainers(fieldSchema));
|
|
425
|
-
break;
|
|
426
|
-
case "sequence":
|
|
427
|
-
map.set(key, new Y3.Array());
|
|
428
|
-
break;
|
|
429
|
-
case "map":
|
|
430
|
-
map.set(key, new Y3.Map());
|
|
431
|
-
break;
|
|
432
|
-
case "scalar":
|
|
433
|
-
case "sum": {
|
|
434
|
-
const zero = Zero.structural(fieldSchema);
|
|
435
|
-
if (zero !== void 0) {
|
|
436
|
-
map.set(key, zero);
|
|
437
|
-
}
|
|
438
|
-
break;
|
|
439
|
-
}
|
|
440
|
-
case "counter":
|
|
441
|
-
case "set":
|
|
442
|
-
case "tree":
|
|
443
|
-
case "movable":
|
|
444
|
-
throw new Error(
|
|
445
|
-
`Yjs substrate does not support [KIND]="${fieldSchema[KIND3]}". Supported kinds: text, product, sequence, map, scalar, sum. Encountered unsupported kind at nested field "${key}".`
|
|
446
|
-
);
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
return map;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
469
|
// src/reader.ts
|
|
453
470
|
import * as Y4 from "yjs";
|
|
454
471
|
function extractValue(resolved) {
|
|
@@ -507,23 +524,13 @@ function yjsReader(doc, schema) {
|
|
|
507
524
|
}
|
|
508
525
|
|
|
509
526
|
// src/version.ts
|
|
510
|
-
import {
|
|
527
|
+
import {
|
|
528
|
+
base64ToUint8Array,
|
|
529
|
+
uint8ArrayToBase64,
|
|
530
|
+
versionVectorCompare,
|
|
531
|
+
versionVectorMeet
|
|
532
|
+
} from "@kyneta/schema";
|
|
511
533
|
import { decodeStateVector } from "yjs";
|
|
512
|
-
function uint8ArrayToBase64(bytes) {
|
|
513
|
-
let binary = "";
|
|
514
|
-
for (let i = 0; i < bytes.length; i++) {
|
|
515
|
-
binary += String.fromCharCode(bytes[i]);
|
|
516
|
-
}
|
|
517
|
-
return btoa(binary);
|
|
518
|
-
}
|
|
519
|
-
function base64ToUint8Array(base64) {
|
|
520
|
-
const binary = atob(base64);
|
|
521
|
-
const bytes = new Uint8Array(binary.length);
|
|
522
|
-
for (let i = 0; i < binary.length; i++) {
|
|
523
|
-
bytes[i] = binary.charCodeAt(i);
|
|
524
|
-
}
|
|
525
|
-
return bytes;
|
|
526
|
-
}
|
|
527
534
|
function encodeStateVector(map) {
|
|
528
535
|
const bytes = [];
|
|
529
536
|
function writeVarUint(value) {
|
|
@@ -557,45 +564,19 @@ var YjsVersion = class _YjsVersion {
|
|
|
557
564
|
/**
|
|
558
565
|
* Compare with another version using version-vector partial order.
|
|
559
566
|
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
* - Collect the union of all client IDs from both maps.
|
|
564
|
-
* - For each client, compare clocks (missing client = clock 0).
|
|
565
|
-
* - If all clocks in `this` ≤ `other` and at least one strictly less → `"behind"`
|
|
566
|
-
* - If all clocks in `this` ≥ `other` and at least one strictly greater → `"ahead"`
|
|
567
|
-
* - If all clocks equal → `"equal"`
|
|
568
|
-
* - Otherwise → `"concurrent"`
|
|
567
|
+
* Delegates to the shared `versionVectorCompare` utility after decoding
|
|
568
|
+
* both state vectors via `Y.decodeStateVector()`.
|
|
569
569
|
*
|
|
570
|
-
*
|
|
570
|
+
* @throws If `other` is not a `YjsVersion`.
|
|
571
571
|
*/
|
|
572
572
|
compare(other) {
|
|
573
573
|
if (!(other instanceof _YjsVersion)) {
|
|
574
574
|
throw new Error("YjsVersion can only be compared with another YjsVersion");
|
|
575
575
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
for (const id of otherMap.keys()) allClients.add(id);
|
|
581
|
-
let hasLess = false;
|
|
582
|
-
let hasGreater = false;
|
|
583
|
-
for (const clientId of allClients) {
|
|
584
|
-
const thisClock = thisMap.get(clientId) ?? 0;
|
|
585
|
-
const otherClock = otherMap.get(clientId) ?? 0;
|
|
586
|
-
if (thisClock < otherClock) {
|
|
587
|
-
hasLess = true;
|
|
588
|
-
}
|
|
589
|
-
if (thisClock > otherClock) {
|
|
590
|
-
hasGreater = true;
|
|
591
|
-
}
|
|
592
|
-
if (hasLess && hasGreater) {
|
|
593
|
-
return "concurrent";
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
if (hasLess && !hasGreater) return "behind";
|
|
597
|
-
if (hasGreater && !hasLess) return "ahead";
|
|
598
|
-
return "equal";
|
|
576
|
+
return versionVectorCompare(
|
|
577
|
+
decodeStateVector(this.sv),
|
|
578
|
+
decodeStateVector(other.sv)
|
|
579
|
+
);
|
|
599
580
|
}
|
|
600
581
|
/**
|
|
601
582
|
* Greatest lower bound (lattice meet) of two Yjs versions.
|
|
@@ -608,9 +589,7 @@ var YjsVersion = class _YjsVersion {
|
|
|
608
589
|
*/
|
|
609
590
|
meet(other) {
|
|
610
591
|
if (!(other instanceof _YjsVersion)) {
|
|
611
|
-
throw new Error(
|
|
612
|
-
"YjsVersion can only be meet'd with another YjsVersion"
|
|
613
|
-
);
|
|
592
|
+
throw new Error("YjsVersion can only be meet'd with another YjsVersion");
|
|
614
593
|
}
|
|
615
594
|
const thisMap = decodeStateVector(this.sv);
|
|
616
595
|
const otherMap = decodeStateVector(other.sv);
|
|
@@ -666,6 +645,12 @@ function createYjsSubstrate(doc, schema) {
|
|
|
666
645
|
context() {
|
|
667
646
|
if (!cachedCtx) {
|
|
668
647
|
cachedCtx = buildWritableContext(substrate);
|
|
648
|
+
cachedCtx.nativeResolver = (nodeSchema, path) => {
|
|
649
|
+
if (path.segments.length === 0) return doc;
|
|
650
|
+
if (nodeSchema[KIND3] === "scalar" || nodeSchema[KIND3] === "sum")
|
|
651
|
+
return void 0;
|
|
652
|
+
return resolveYjsType(rootMap, schema, path);
|
|
653
|
+
};
|
|
669
654
|
}
|
|
670
655
|
return cachedCtx;
|
|
671
656
|
},
|
|
@@ -730,9 +715,7 @@ function createYjsSubstrate(doc, schema) {
|
|
|
730
715
|
}
|
|
731
716
|
function createYjsReplica(doc) {
|
|
732
717
|
let currentDoc = doc;
|
|
733
|
-
let currentBase = new YjsVersion(
|
|
734
|
-
Y5.encodeStateVector(new Y5.Doc())
|
|
735
|
-
);
|
|
718
|
+
let currentBase = new YjsVersion(Y5.encodeStateVector(new Y5.Doc()));
|
|
736
719
|
return {
|
|
737
720
|
get [BACKING_DOC]() {
|
|
738
721
|
return currentDoc;
|
|
@@ -828,57 +811,7 @@ var yjsSubstrateFactory = {
|
|
|
828
811
|
}
|
|
829
812
|
};
|
|
830
813
|
|
|
831
|
-
// src/create.ts
|
|
832
|
-
var substrates = /* @__PURE__ */ new WeakMap();
|
|
833
|
-
function getSubstrate(doc) {
|
|
834
|
-
const s = substrates.get(doc);
|
|
835
|
-
if (!s) {
|
|
836
|
-
throw new Error(
|
|
837
|
-
"version/exportEntirety/merge called on an object without a YjsSubstrate. Use a doc created by createYjsDoc() or createYjsDocFromEntirety()."
|
|
838
|
-
);
|
|
839
|
-
}
|
|
840
|
-
return s;
|
|
841
|
-
}
|
|
842
|
-
function registerDoc(schema, substrate) {
|
|
843
|
-
const doc = interpret(schema, substrate.context()).with(readable).with(writable).with(observation).done();
|
|
844
|
-
substrates.set(doc, substrate);
|
|
845
|
-
registerSubstrate(doc, substrate);
|
|
846
|
-
return doc;
|
|
847
|
-
}
|
|
848
|
-
function isYDoc(value) {
|
|
849
|
-
return value !== null && value !== void 0 && typeof value === "object" && "getMap" in value && "getText" in value && "getArray" in value && "transact" in value && typeof value.transact === "function" && // Y.Doc has clientID; distinguish from other objects
|
|
850
|
-
"clientID" in value && typeof value.clientID === "number";
|
|
851
|
-
}
|
|
852
|
-
var createYjsDoc = (schema, doc) => {
|
|
853
|
-
if (doc !== void 0 && isYDoc(doc)) {
|
|
854
|
-
return registerDoc(schema, createYjsSubstrate(doc, schema));
|
|
855
|
-
}
|
|
856
|
-
return registerDoc(schema, yjsSubstrateFactory.create(schema));
|
|
857
|
-
};
|
|
858
|
-
var createYjsDocFromEntirety = (schema, payload) => registerDoc(schema, yjsSubstrateFactory.fromEntirety(payload, schema));
|
|
859
|
-
|
|
860
|
-
// src/sync.ts
|
|
861
|
-
function version(doc) {
|
|
862
|
-
return getSubstrate(doc).version();
|
|
863
|
-
}
|
|
864
|
-
function exportEntirety(doc) {
|
|
865
|
-
return getSubstrate(doc).exportEntirety();
|
|
866
|
-
}
|
|
867
|
-
function exportSince(doc, since) {
|
|
868
|
-
return getSubstrate(doc).exportSince(since);
|
|
869
|
-
}
|
|
870
|
-
function merge(doc, payload, origin) {
|
|
871
|
-
getSubstrate(doc).merge(payload, origin);
|
|
872
|
-
}
|
|
873
|
-
|
|
874
814
|
// src/bind-yjs.ts
|
|
875
|
-
import {
|
|
876
|
-
BACKING_DOC as BACKING_DOC2,
|
|
877
|
-
createSubstrateNamespace,
|
|
878
|
-
STRUCTURAL_YJS_CLIENT_ID as STRUCTURAL_YJS_CLIENT_ID2,
|
|
879
|
-
unwrap
|
|
880
|
-
} from "@kyneta/schema";
|
|
881
|
-
import * as Y6 from "yjs";
|
|
882
815
|
function hashPeerId(peerId) {
|
|
883
816
|
let hash = 2166136261;
|
|
884
817
|
for (let i = 0; i < peerId.length; i++) {
|
|
@@ -917,46 +850,28 @@ function createYjsFactory(peerId) {
|
|
|
917
850
|
}
|
|
918
851
|
};
|
|
919
852
|
}
|
|
920
|
-
var yjs = {
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
replicaFactory: yjsReplicaFactory
|
|
926
|
-
},
|
|
927
|
-
ephemeral: {
|
|
928
|
-
factory: (ctx) => createYjsFactory(ctx.peerId),
|
|
929
|
-
replicaFactory: yjsReplicaFactory
|
|
930
|
-
}
|
|
853
|
+
var yjs = createSubstrateNamespace({
|
|
854
|
+
strategies: {
|
|
855
|
+
collaborative: {
|
|
856
|
+
factory: (ctx) => createYjsFactory(ctx.peerId),
|
|
857
|
+
replicaFactory: yjsReplicaFactory
|
|
931
858
|
},
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
let substrate;
|
|
936
|
-
try {
|
|
937
|
-
substrate = unwrap(ref);
|
|
938
|
-
} catch {
|
|
939
|
-
throw new Error(
|
|
940
|
-
"yjs.unwrap() requires a ref backed by a Yjs substrate. Use a doc created by exchange.get() with a yjs.bind() schema, or by createYjsDoc()."
|
|
941
|
-
);
|
|
859
|
+
ephemeral: {
|
|
860
|
+
factory: (ctx) => createYjsFactory(ctx.peerId),
|
|
861
|
+
replicaFactory: yjsReplicaFactory
|
|
942
862
|
}
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
"yjs.unwrap() requires a ref backed by a Yjs substrate. The ref has a substrate but it is not a Yjs substrate. Use a doc created with a yjs.bind() schema or createYjsDoc()."
|
|
947
|
-
);
|
|
948
|
-
}
|
|
949
|
-
return doc;
|
|
950
|
-
}
|
|
951
|
-
};
|
|
863
|
+
},
|
|
864
|
+
defaultStrategy: "collaborative"
|
|
865
|
+
});
|
|
952
866
|
export {
|
|
867
|
+
NATIVE,
|
|
953
868
|
Schema,
|
|
954
869
|
YjsVersion,
|
|
955
870
|
applyChangeToYjs,
|
|
956
871
|
applyChanges,
|
|
957
872
|
change,
|
|
958
|
-
|
|
959
|
-
|
|
873
|
+
createDoc,
|
|
874
|
+
createRef,
|
|
960
875
|
createYjsSubstrate,
|
|
961
876
|
ensureContainers,
|
|
962
877
|
eventsToOps,
|
|
@@ -967,6 +882,7 @@ export {
|
|
|
967
882
|
stepIntoYjs,
|
|
968
883
|
subscribe,
|
|
969
884
|
subscribeNode,
|
|
885
|
+
unwrap,
|
|
970
886
|
version,
|
|
971
887
|
yjs,
|
|
972
888
|
yjsReader,
|