@cuboapp/crdt 1.0.20 → 1.0.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cuboapp/crdt",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "description": "CRDT for CUBO",
5
5
  "main": "src/index.ts",
6
6
  "repository": {
@@ -1,6 +1,6 @@
1
1
  import { keyBy, pick, uuid } from '@cuboapp/utils'
2
2
  import { WsClientEvent } from '@cuboapp/ws'
3
- import { computed, reactive } from 'vue'
3
+ import { computed, reactive, shallowReactive } from 'vue'
4
4
  import { applyAwarenessUpdate, Awareness, encodeAwarenessUpdate, removeAwarenessStates } from 'y-protocols/awareness'
5
5
  import { applyUpdate, Doc } from 'yjs'
6
6
 
@@ -234,8 +234,8 @@ export class CuboCrdtClient<M> {
234
234
 
235
235
  this.store[storeKey] = {
236
236
  state,
237
- docs: new Map(),
238
- awarenesses: new Map()
237
+ docs: shallowReactive(new Map()),
238
+ awarenesses: shallowReactive(new Map())
239
239
  }
240
240
  }
241
241
 
@@ -551,6 +551,47 @@ export class CuboCrdtClient<M> {
551
551
  }
552
552
  }
553
553
 
554
+ private ensureDocumentAwareness(
555
+ ctx: CuboCrdtClientSubscribeEvent,
556
+ opts: CuboCrdtClientDocUpdateOptions,
557
+ doc: Doc,
558
+ entity_id: number
559
+ ) {
560
+ if (!opts.awareness) {
561
+ return
562
+ }
563
+
564
+ let awareness = this.store[opts.storeKey]?.awarenesses.get(entity_id)
565
+
566
+ if (awareness) {
567
+ return
568
+ }
569
+
570
+ awareness = new Awareness(doc)
571
+
572
+ awareness.on('update', ({ added, updated, removed }, origin) => {
573
+ if (origin === 'remote') {
574
+ return
575
+ }
576
+
577
+ const changed = added.concat(updated).concat(removed)
578
+ const update = encodeAwarenessUpdate(awareness!, changed)
579
+
580
+ this.ws.request({
581
+ method: CUBO_CRDT_EVENT.EVENT,
582
+ data: {
583
+ action: 'awareness',
584
+ entity: ctx.entity,
585
+ entity_id,
586
+ data: Array.from(update),
587
+ origin: { expose: 'other', subscribe_id: opts.subscribe_id }
588
+ }
589
+ })
590
+ })
591
+
592
+ this.store[opts.storeKey]?.awarenesses.set(entity_id, awareness)
593
+ }
594
+
554
595
  private async onDocumentCreate(ctx: CuboCrdtClientSubscribeEvent, opts: CuboCrdtClientDocUpdateOptions) {
555
596
  const entity_id = ctx.entity_id
556
597
  if (entity_id === undefined) {
@@ -568,6 +609,7 @@ export class CuboCrdtClient<M> {
568
609
 
569
610
  applyUpdate(existing, new Uint8Array(ctx.data as any), { react: false })
570
611
  this.applyRowJson(opts.storeKey, entity_id, existing)
612
+ this.ensureDocumentAwareness(ctx, opts, existing, entity_id)
571
613
  return
572
614
  }
573
615
 
@@ -630,38 +672,7 @@ export class CuboCrdtClient<M> {
630
672
  await opts.onAfterCreate(doc, update, ctx, opts)
631
673
  }
632
674
 
633
- if (opts?.awareness) {
634
- let awareness = this.store[opts.storeKey]?.awarenesses.get(entity_id)
635
-
636
- if (!awareness) {
637
- awareness = new Awareness(doc)
638
-
639
- awareness.on('update', ({ added, updated, removed }, origin) => {
640
- // console.log('[CRDT] awarness update', origin)
641
-
642
- if (origin === 'remote') {
643
- return
644
- }
645
-
646
- const changed = added.concat(updated).concat(removed)
647
- const update = encodeAwarenessUpdate(awareness, changed)
648
-
649
- this.ws.request({
650
- method: CUBO_CRDT_EVENT.EVENT,
651
- data: {
652
- action: 'awareness',
653
- entity: ctx.entity,
654
- entity_id,
655
- data: Array.from(update),
656
- // 'other' — не шлём свой же курсор обратно исходной подписке
657
- origin: { expose: 'other', subscribe_id: opts.subscribe_id }
658
- }
659
- })
660
- })
661
-
662
- this.store[opts.storeKey]?.awarenesses.set(entity_id, awareness)
663
- }
664
- }
675
+ this.ensureDocumentAwareness(ctx, opts, doc, entity_id)
665
676
  }
666
677
 
667
678
  private async onDocumentUpdate(ctx: CuboCrdtClientSubscribeEvent, opts: CuboCrdtClientDocUpdateOptions) {
@@ -19,28 +19,7 @@ export class CuboCrdtServerDocument {
19
19
  })
20
20
 
21
21
  if (opts.awareness) {
22
- this.awareness = new Awareness(this.ydoc)
23
- this.awareness.setLocalState(null)
24
-
25
- this.awareness.on('update', ({ added, updated, removed }, origin: CuboCrdtServerDocumentOrigin) => {
26
- const subId = origin?.subscribe_id
27
-
28
- if (subId) {
29
- let set = this.awarenessBySubscribe.get(subId)
30
- if (!set) {
31
- set = new Set()
32
- this.awarenessBySubscribe.set(subId, set)
33
- }
34
-
35
- added.concat(updated).forEach((id) => set!.add(id))
36
- removed.forEach((id) => set!.delete(id))
37
- }
38
-
39
- const changed = added.concat(updated).concat(removed)
40
- const update = encodeAwarenessUpdate(this.awareness!, changed)
41
-
42
- this.opts?.onAwarenessUpdate?.(update, origin)
43
- })
22
+ this.enableAwareness()
44
23
  }
45
24
 
46
25
  this.persistedState = cloneDeep(opts.initialState ?? {})
@@ -72,6 +51,35 @@ export class CuboCrdtServerDocument {
72
51
  })
73
52
  }
74
53
 
54
+ public enableAwareness() {
55
+ if (this.awareness) {
56
+ return
57
+ }
58
+
59
+ this.awareness = new Awareness(this.ydoc)
60
+ this.awareness.setLocalState(null)
61
+
62
+ this.awareness.on('update', ({ added, updated, removed }, origin: CuboCrdtServerDocumentOrigin) => {
63
+ const subId = origin?.subscribe_id
64
+
65
+ if (subId) {
66
+ let set = this.awarenessBySubscribe.get(subId)
67
+ if (!set) {
68
+ set = new Set()
69
+ this.awarenessBySubscribe.set(subId, set)
70
+ }
71
+
72
+ added.concat(updated).forEach((id) => set!.add(id))
73
+ removed.forEach((id) => set!.delete(id))
74
+ }
75
+
76
+ const changed = added.concat(updated).concat(removed)
77
+ const update = encodeAwarenessUpdate(this.awareness!, changed)
78
+
79
+ this.opts?.onAwarenessUpdate?.(update, origin)
80
+ })
81
+ }
82
+
75
83
  public get name() {
76
84
  return this.opts.name
77
85
  }
@@ -605,6 +605,10 @@ export class CuboCrdtServer<M, A = {}, E extends Extract<keyof M, string> = Extr
605
605
 
606
606
  let document = this.documents.get(documentName)
607
607
  if (document) {
608
+ if (awareness) {
609
+ document.enableAwareness()
610
+ }
611
+
608
612
  // Освежаем существующий документ строкой из БД.
609
613
  //
610
614
  // Раньше документ возвращался как есть, а подписка отправляла клиенту его