@kyneta/yjs-schema 1.7.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import {
2
- change,
2
+ batch,
3
3
  createRef,
4
4
  deriveIdentity,
5
5
  exportEntirety,
@@ -59,7 +59,7 @@ describe("yjs.bind", () => {
59
59
  const bound = yjs.bind(TodoSchema)
60
60
  expect(bound._brand).toBe("BoundSchema")
61
61
  expect(bound.schema).toBe(TodoSchema)
62
- expect(bound.syncProtocol).toEqual(SYNC_COLLABORATIVE)
62
+ expect(bound.syncMode).toEqual(SYNC_COLLABORATIVE)
63
63
  })
64
64
 
65
65
  it("has a factory builder function", () => {
@@ -89,7 +89,7 @@ describe("yjs.bind", () => {
89
89
 
90
90
  // Populate via the substrate's writable context
91
91
  const doc = createYjsDocFromFactory(factory, SimpleSchema)
92
- change(doc, (d: any) => {
92
+ batch(doc, (d: any) => {
93
93
  d.title.insert(0, "Test")
94
94
  d.count.set(7)
95
95
  })
@@ -107,7 +107,7 @@ describe("yjs.bind", () => {
107
107
 
108
108
  // Create and populate
109
109
  const doc1 = createYjsDocFromFactory(factory, SimpleSchema)
110
- change(doc1, (d: any) => {
110
+ batch(doc1, (d: any) => {
111
111
  d.title.insert(0, "Snap")
112
112
  d.count.set(42)
113
113
  })
@@ -230,7 +230,7 @@ describe("yjs.bind", () => {
230
230
  describe("unwrap() escape hatch", () => {
231
231
  it("returns the underlying Y.Doc from a createDoc ref", () => {
232
232
  const doc = createDoc(yjs.bind(SimpleSchema))
233
- change(doc, (d: any) => {
233
+ batch(doc, (d: any) => {
234
234
  d.title.insert(0, "Escape")
235
235
  d.count.set(0)
236
236
  })
@@ -242,7 +242,7 @@ describe("yjs.bind", () => {
242
242
 
243
243
  it("returns a Y.Doc with the correct root map state", () => {
244
244
  const doc = createDoc(yjs.bind(SimpleSchema))
245
- change(doc, (d: any) => {
245
+ batch(doc, (d: any) => {
246
246
  d.title.insert(0, "Hello")
247
247
  d.count.set(42)
248
248
  })
@@ -281,7 +281,7 @@ describe("yjs.bind", () => {
281
281
 
282
282
  it("text mutations through escape hatch are visible", () => {
283
283
  const doc = createDoc(yjs.bind(SimpleSchema))
284
- change(doc, (d: any) => {
284
+ batch(doc, (d: any) => {
285
285
  d.title.insert(0, "Hello")
286
286
  })
287
287
  const yjsDoc = unwrap(doc) as Y.Doc
@@ -1,5 +1,5 @@
1
1
  import {
2
- change,
2
+ batch,
3
3
  createDoc,
4
4
  createRef,
5
5
  Schema,
@@ -93,15 +93,15 @@ describe("createDoc", () => {
93
93
  describe("with seeds", () => {
94
94
  it("creates a doc with scalar seed values", () => {
95
95
  const doc = createDoc(boundSimple)
96
- change(doc, (d: any) => {
96
+ batch(doc, (d: any) => {
97
97
  d.title.insert(0, "Hello")
98
98
  d.count.set(42)
99
99
  })
100
- // Separate change() calls for list pushes to preserve order
100
+ // Separate batch() calls for list pushes to preserve order
101
101
  // (Yjs reverses order within a single transaction)
102
- change(doc, (d: any) => d.items.push("a"))
103
- change(doc, (d: any) => d.items.push("b"))
104
- change(doc, (d: any) => d.items.push("c"))
102
+ batch(doc, (d: any) => d.items.push("a"))
103
+ batch(doc, (d: any) => d.items.push("b"))
104
+ batch(doc, (d: any) => d.items.push("c"))
105
105
  expect(doc.title()).toBe("Hello")
106
106
  expect(doc.count()).toBe(42)
107
107
  expect(doc.items()).toEqual(["a", "b", "c"])
@@ -109,7 +109,7 @@ describe("createDoc", () => {
109
109
 
110
110
  it("creates a doc with partial seed (defaults fill gaps)", () => {
111
111
  const doc = createDoc(boundSimple)
112
- change(doc, (d: any) => {
112
+ batch(doc, (d: any) => {
113
113
  d.title.insert(0, "Partial")
114
114
  })
115
115
  expect(doc.title()).toBe("Partial")
@@ -119,7 +119,7 @@ describe("createDoc", () => {
119
119
 
120
120
  it("creates a doc with nested struct seed", () => {
121
121
  const doc = createDoc(boundNested)
122
- change(doc, (d: any) => {
122
+ batch(doc, (d: any) => {
123
123
  d.title.insert(0, "Doc")
124
124
  d.meta.author.set("Alice")
125
125
  d.meta.tags.push("draft")
@@ -134,9 +134,9 @@ describe("createDoc", () => {
134
134
 
135
135
  it("creates a doc with struct list seed items", () => {
136
136
  const doc = createDoc(boundStructList)
137
- // Separate change() calls for list pushes to preserve order
138
- change(doc, (d: any) => d.tasks.push({ name: "Task 1", done: false }))
139
- change(doc, (d: any) => d.tasks.push({ name: "Task 2", done: true }))
137
+ // Separate batch() calls for list pushes to preserve order
138
+ batch(doc, (d: any) => d.tasks.push({ name: "Task 1", done: false }))
139
+ batch(doc, (d: any) => d.tasks.push({ name: "Task 2", done: true }))
140
140
  expect(doc.tasks.length).toBe(2)
141
141
  expect(doc.tasks.at(0)?.name()).toBe("Task 1")
142
142
  expect(doc.tasks.at(0)?.done()).toBe(false)
@@ -177,7 +177,7 @@ describe("createDoc", () => {
177
177
  SimpleSchema,
178
178
  createYjsSubstrate(yjsDoc, SimpleSchema),
179
179
  )
180
- change(doc, (d: any) => {
180
+ batch(doc, (d: any) => {
181
181
  d.title.insert(0, "Hello")
182
182
  d.count.set(42)
183
183
  })
@@ -221,15 +221,26 @@ describe("createDoc", () => {
221
221
  // createDoc with payload (fromEntirety)
222
222
  // ===========================================================================
223
223
 
224
+ describe("root document replacement", () => {
225
+ it("throws an actionable error when attempting to replace the root struct", () => {
226
+ const doc = createDoc(boundSimple)
227
+ expect(() => {
228
+ batch(doc, (d: any) => {
229
+ d.set({ title: "New", count: 1, items: [] })
230
+ })
231
+ }).toThrowError(/Cannot replace the root document struct/)
232
+ })
233
+ })
234
+
224
235
  describe("createDoc with payload", () => {
225
236
  it("reconstructs state from a snapshot", () => {
226
237
  const doc1 = createDoc(boundSimple)
227
- change(doc1, (d: any) => {
238
+ batch(doc1, (d: any) => {
228
239
  d.title.insert(0, "Snapshot")
229
240
  d.count.set(42)
230
241
  })
231
- change(doc1, (d: any) => d.items.push("a"))
232
- change(doc1, (d: any) => d.items.push("b"))
242
+ batch(doc1, (d: any) => d.items.push("a"))
243
+ batch(doc1, (d: any) => d.items.push("b"))
233
244
 
234
245
  const payload = exportEntirety(doc1)
235
246
  const doc2 = createDoc(boundSimple, payload)
@@ -241,11 +252,11 @@ describe("createDoc with payload", () => {
241
252
 
242
253
  it("reconstructs state after mutations", () => {
243
254
  const doc1 = createDoc(boundSimple)
244
- change(doc1, (d: any) => {
255
+ batch(doc1, (d: any) => {
245
256
  d.title.insert(0, "Start")
246
257
  })
247
258
 
248
- change(doc1, (d: any) => {
259
+ batch(doc1, (d: any) => {
249
260
  d.title.insert(5, " End")
250
261
  d.count.set(99)
251
262
  d.items.push("x")
@@ -261,13 +272,13 @@ describe("createDoc with payload", () => {
261
272
 
262
273
  it("reconstructs nested struct state from snapshot", () => {
263
274
  const doc1 = createDoc(boundNested)
264
- change(doc1, (d: any) => {
275
+ batch(doc1, (d: any) => {
265
276
  d.title.insert(0, "Nested")
266
277
  d.meta.author.set("Alice")
267
278
  d.labels.set("bug", "red")
268
279
  })
269
- change(doc1, (d: any) => d.meta.tags.push("v1"))
270
- change(doc1, (d: any) => d.meta.tags.push("v2"))
280
+ batch(doc1, (d: any) => d.meta.tags.push("v1"))
281
+ batch(doc1, (d: any) => d.meta.tags.push("v2"))
271
282
 
272
283
  const payload = exportEntirety(doc1)
273
284
  const doc2 = createDoc(boundNested, payload)
@@ -281,8 +292,8 @@ describe("createDoc with payload", () => {
281
292
 
282
293
  it("reconstructs struct list state from snapshot", () => {
283
294
  const doc1 = createDoc(boundStructList)
284
- change(doc1, (d: any) => d.tasks.push({ name: "Task A", done: false }))
285
- change(doc1, (d: any) => d.tasks.push({ name: "Task B", done: true }))
295
+ batch(doc1, (d: any) => d.tasks.push({ name: "Task A", done: false }))
296
+ batch(doc1, (d: any) => d.tasks.push({ name: "Task B", done: true }))
286
297
 
287
298
  const payload = exportEntirety(doc1)
288
299
  const doc2 = createDoc(boundStructList, payload)
@@ -294,13 +305,13 @@ describe("createDoc with payload", () => {
294
305
 
295
306
  it("is writable after reconstruction", () => {
296
307
  const doc1 = createDoc(boundSimple)
297
- change(doc1, (d: any) => {
308
+ batch(doc1, (d: any) => {
298
309
  d.title.insert(0, "Original")
299
310
  })
300
311
  const payload = exportEntirety(doc1)
301
312
  const doc2 = createDoc(boundSimple, payload)
302
313
 
303
- change(doc2, (d: any) => {
314
+ batch(doc2, (d: any) => {
304
315
  d.title.insert(8, " Copy")
305
316
  d.count.set(7)
306
317
  })
@@ -311,7 +322,7 @@ describe("createDoc with payload", () => {
311
322
 
312
323
  it("is observable after reconstruction", () => {
313
324
  const doc1 = createDoc(boundSimple)
314
- change(doc1, (d: any) => {
325
+ batch(doc1, (d: any) => {
315
326
  d.title.insert(0, "Original")
316
327
  })
317
328
  const payload = exportEntirety(doc1)
@@ -322,7 +333,7 @@ describe("createDoc with payload", () => {
322
333
  received.push(changeset)
323
334
  })
324
335
 
325
- change(doc2, (d: any) => {
336
+ batch(doc2, (d: any) => {
326
337
  d.count.set(42)
327
338
  })
328
339
 
@@ -346,7 +357,7 @@ describe("sync primitives", () => {
346
357
  const doc = createDoc(boundSimple)
347
358
  const v1 = version(doc)
348
359
 
349
- change(doc, (d: any) => {
360
+ batch(doc, (d: any) => {
350
361
  d.count.set(1)
351
362
  })
352
363
  const v2 = version(doc)
@@ -356,7 +367,7 @@ describe("sync primitives", () => {
356
367
 
357
368
  it("serialize/parse round-trips", () => {
358
369
  const doc = createDoc(boundSimple)
359
- change(doc, (d: any) => {
370
+ batch(doc, (d: any) => {
360
371
  d.title.insert(0, "Test")
361
372
  })
362
373
  const v = version(doc)
@@ -369,7 +380,7 @@ describe("sync primitives", () => {
369
380
  describe("exportEntirety", () => {
370
381
  it("returns a binary payload", () => {
371
382
  const doc = createDoc(boundSimple)
372
- change(doc, (d: any) => {
383
+ batch(doc, (d: any) => {
373
384
  d.title.insert(0, "Snap")
374
385
  })
375
386
  const payload = exportEntirety(doc)
@@ -382,7 +393,7 @@ describe("sync primitives", () => {
382
393
  describe("exportSince + merge", () => {
383
394
  it("syncs incremental changes between two docs", () => {
384
395
  const doc1 = createDoc(boundSimple)
385
- change(doc1, (d: any) => {
396
+ batch(doc1, (d: any) => {
386
397
  d.title.insert(0, "Start")
387
398
  })
388
399
  const doc2 = createDoc(boundSimple, exportEntirety(doc1))
@@ -390,7 +401,7 @@ describe("sync primitives", () => {
390
401
  const v2Before = version(doc2)
391
402
 
392
403
  // Mutate doc1
393
- change(doc1, (d: any) => {
404
+ batch(doc1, (d: any) => {
394
405
  d.title.insert(5, " Edited")
395
406
  d.count.set(42)
396
407
  d.items.push("new-item")
@@ -414,21 +425,21 @@ describe("sync primitives", () => {
414
425
 
415
426
  // First round
416
427
  let vBefore = version(doc2)
417
- change(doc1, (d: any) => {
428
+ batch(doc1, (d: any) => {
418
429
  d.title.insert(0, "A")
419
430
  })
420
431
  merge(doc2, exportSince(doc1, vBefore)!)
421
432
 
422
433
  // Second round
423
434
  vBefore = version(doc2)
424
- change(doc1, (d: any) => {
435
+ batch(doc1, (d: any) => {
425
436
  d.title.insert(1, "B")
426
437
  })
427
438
  merge(doc2, exportSince(doc1, vBefore)!)
428
439
 
429
440
  // Third round
430
441
  vBefore = version(doc2)
431
- change(doc1, (d: any) => {
442
+ batch(doc1, (d: any) => {
432
443
  d.count.set(3)
433
444
  })
434
445
  merge(doc2, exportSince(doc1, vBefore)!)
@@ -439,14 +450,14 @@ describe("sync primitives", () => {
439
450
 
440
451
  it("changefeed fires on merge", () => {
441
452
  const doc1 = createDoc(boundSimple)
442
- change(doc1, (d: any) => {
453
+ batch(doc1, (d: any) => {
443
454
  d.title.insert(0, "Source")
444
455
  })
445
456
  const doc2 = createDoc(boundSimple, exportEntirety(doc1))
446
457
 
447
458
  const v2Before = version(doc2)
448
459
 
449
- change(doc1, (d: any) => {
460
+ batch(doc1, (d: any) => {
450
461
  d.count.set(77)
451
462
  })
452
463
 
@@ -468,7 +479,7 @@ describe("sync primitives", () => {
468
479
  const doc2 = createDoc(boundSimple, exportEntirety(doc1))
469
480
 
470
481
  const v2Before = version(doc2)
471
- change(doc1, (d: any) => {
482
+ batch(doc1, (d: any) => {
472
483
  d.count.set(1)
473
484
  })
474
485
 
@@ -486,10 +497,10 @@ describe("sync primitives", () => {
486
497
  describe("versions equal after sync", () => {
487
498
  it("versions equal after full snapshot sync", () => {
488
499
  const doc1 = createDoc(boundSimple)
489
- change(doc1, (d: any) => {
500
+ batch(doc1, (d: any) => {
490
501
  d.title.insert(0, "Same")
491
502
  })
492
- change(doc1, (d: any) => {
503
+ batch(doc1, (d: any) => {
493
504
  d.count.set(42)
494
505
  })
495
506
 
@@ -506,10 +517,10 @@ describe("sync primitives", () => {
506
517
  const v2Before = version(doc2)
507
518
 
508
519
  // Independent mutations
509
- change(doc1, (d: any) => {
520
+ batch(doc1, (d: any) => {
510
521
  d.title.insert(0, "A")
511
522
  })
512
- change(doc2, (d: any) => {
523
+ batch(doc2, (d: any) => {
513
524
  d.count.set(7)
514
525
  })
515
526
 
@@ -543,11 +554,11 @@ describe("full workflow", () => {
543
554
  // 3. Mutate doc1
544
555
  const vBefore = version(doc2)
545
556
 
546
- change(doc1, (d: any) => {
557
+ batch(doc1, (d: any) => {
547
558
  d.tasks.push({ name: "Buy milk", done: false })
548
559
  })
549
560
 
550
- change(doc1, (d: any) => {
561
+ batch(doc1, (d: any) => {
551
562
  d.tasks.push({ name: "Walk dog", done: false })
552
563
  })
553
564
 
@@ -569,7 +580,7 @@ describe("full workflow", () => {
569
580
  // 8. Mutate doc2 and sync back
570
581
  const v1Before = version(doc1)
571
582
 
572
- change(doc2, (d: any) => {
583
+ batch(doc2, (d: any) => {
573
584
  d.tasks.push({ name: "Read book", done: false })
574
585
  })
575
586
 
@@ -584,10 +595,10 @@ describe("full workflow", () => {
584
595
  it("create → mutate → snapshot → reconstruct → continue", () => {
585
596
  // 1. Create and mutate
586
597
  const doc1 = createDoc(boundSimple)
587
- change(doc1, (d: any) => {
598
+ batch(doc1, (d: any) => {
588
599
  d.title.insert(0, "Start")
589
600
  })
590
- change(doc1, (d: any) => {
601
+ batch(doc1, (d: any) => {
591
602
  d.title.insert(5, " Middle")
592
603
  d.count.set(10)
593
604
  d.items.push("first")
@@ -603,7 +614,7 @@ describe("full workflow", () => {
603
614
  expect(doc2.items()).toEqual(["first"])
604
615
 
605
616
  // 4. Continue mutating the reconstructed doc
606
- change(doc2, (d: any) => {
617
+ batch(doc2, (d: any) => {
607
618
  d.title.insert(12, " End")
608
619
  d.count.set(20)
609
620
  d.items.push("second")
@@ -629,11 +640,11 @@ describe("full workflow", () => {
629
640
  const v2Before = version(doc2)
630
641
 
631
642
  // 2. Both peers edit concurrently
632
- change(doc1, (d: any) => {
643
+ batch(doc1, (d: any) => {
633
644
  d.title.insert(0, "Peer1")
634
645
  d.items.push("from-1")
635
646
  })
636
- change(doc2, (d: any) => {
647
+ batch(doc2, (d: any) => {
637
648
  d.count.set(42)
638
649
  d.items.push("from-2")
639
650
  })