@cuboapp/api-backend 3.0.1 → 3.0.3

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/api-backend",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Backend Api for CuboApp",
5
5
  "main": "src/index.ts",
6
6
  "repository": "git@github.com:cuboapp/api-backend.git",
@@ -14,8 +14,8 @@
14
14
  "@cuboapp/utils": "1.0.12"
15
15
  },
16
16
  "peerDependencies": {
17
- "@cuboapp/crdt": "1.0.14",
18
- "@cuboapp/ws": "1.0.9",
17
+ "@cuboapp/crdt": "1.0.16",
18
+ "@cuboapp/ws": "1.0.10",
19
19
  "mysql2": "3.22.5",
20
20
  "pg": "8.22.0",
21
21
  "yjs": "^13.6.31"
@@ -38,8 +38,8 @@
38
38
  }
39
39
  },
40
40
  "devDependencies": {
41
- "@cuboapp/crdt": "1.0.14",
42
- "@cuboapp/ws": "1.0.9",
41
+ "@cuboapp/crdt": "file:../crdt",
42
+ "@cuboapp/ws": "1.0.10",
43
43
  "@types/node": "^26.0.0",
44
44
  "pg": "^8.22.0",
45
45
  "typescript": "^6.0.3"
package/src/core/index.ts CHANGED
@@ -391,7 +391,7 @@ export class CuboBackendApi<T extends CuboApiEntitiesMap<T>, A extends unknown =
391
391
  await this.options.hooks.onAfterUpdate(entity, response, prev as T[K], opts)
392
392
  }
393
393
 
394
- this.crdtPush('update', entity, response, opts)
394
+ this.crdtPush('update', entity, response, opts, prev, Object.keys(dto))
395
395
  if (augmentation?.afterCrdtUpdate && !this.excluded(opts, 'afterCrdtUpdate')) {
396
396
  await augmentation.afterCrdtUpdate({ ...this.ctx(entity, req, opts, queryOptions), row: response })
397
397
  }
@@ -529,7 +529,14 @@ export class CuboBackendApi<T extends CuboApiEntitiesMap<T>, A extends unknown =
529
529
  if (this.options.hooks?.onAfterUpdate && !this.excluded(opts, 'baseHooks')) {
530
530
  await this.options.hooks.onAfterUpdate(entity, row, prevById.get((row as any).id) as T[K], opts)
531
531
  }
532
- this.crdtPush('update', entity, row, opts)
532
+ this.crdtPush(
533
+ 'update',
534
+ entity,
535
+ row,
536
+ opts,
537
+ prevById.get((row as any).id),
538
+ Object.keys(dto)
539
+ )
533
540
  }
534
541
 
535
542
  return updated
@@ -676,12 +683,19 @@ export class CuboBackendApi<T extends CuboApiEntitiesMap<T>, A extends unknown =
676
683
  if (raw.replacements) queryDto.replacements = { ...(queryDto.replacements || {}), ...raw.replacements }
677
684
  }
678
685
 
679
- private crdtPush(action: 'create' | 'update' | 'delete', entity: CuboEntity, row: any, opts: CuboCrudMethodOptions) {
686
+ private crdtPush(
687
+ action: 'create' | 'update' | 'delete',
688
+ entity: CuboEntity,
689
+ row: any,
690
+ opts: CuboCrudMethodOptions,
691
+ previousRow?: any,
692
+ changedKeys?: string[]
693
+ ) {
680
694
  // если апдейт пришёл ИЗ crdt (storeRow) — не пушим повторно, чтобы не зациклиться
681
695
  if (!this.crdt || !entity.crdt || opts.crdt) return
682
696
 
683
697
  if (action === 'create') this.crdt.pushCreate(entity, row)
684
- else if (action === 'update') this.crdt.pushUpdate(entity, row)
698
+ else if (action === 'update') this.crdt.pushUpdate(entity, row, previousRow, changedKeys)
685
699
  else this.crdt.pushDelete(entity, row)
686
700
  }
687
701
 
package/src/crdt/index.ts CHANGED
@@ -41,22 +41,34 @@ export class CuboCrdtAdapter<T extends CuboApiEntitiesMap<T>, A> {
41
41
 
42
42
  // подписка -> строки из БД (хуки CRUD пропускаем, чтобы не зациклить)
43
43
  fetchRows: async (client, subscribe: CuboCrdtServerSubscribe) => {
44
- const { rows } = await this.api.getMany(subscribe.entity as Extract<keyof T, string>, { query: subscribe.filters }, {
44
+ const { rows, totals } = await this.api.getMany(subscribe.entity as Extract<keyof T, string>, { query: subscribe.filters }, {
45
45
  auth: (client as CuboCrdtSocketClient<A>).auth,
46
46
  excludeHooks: ['afterCrdtCreate', 'afterCrdtUpdate']
47
47
  })
48
48
 
49
- return rows as T[Extract<keyof T, string>][]
49
+ return {
50
+ rows: rows as T[Extract<keyof T, string>][],
51
+ totals
52
+ }
50
53
  },
51
54
 
52
55
  // сохранение состояния дока обратно в БД (origin прокидываем, чтобы не пушить заново)
53
- storeRow: async (entity, entity_id, body, { origin, client }) => {
54
- await this.api.updateOne(entity as Extract<keyof T, string>, { query: { id: entity_id }, body }, {
56
+ storeRow: async (entity, entity_id, body, { previousRow, origin, client }) => {
57
+ const row = await this.api.updateOne(entity as Extract<keyof T, string>, { query: { id: entity_id }, body }, {
55
58
  crdt: origin,
56
59
  performer_id: (client as any)?.auth?.user_id,
57
60
  auth: (client as any)?.auth,
58
61
  excludeHooks: ['afterCrdtUpdate']
59
62
  })
63
+
64
+ if (row) {
65
+ this.server.notifyMutation(entity, {
66
+ action: 'update',
67
+ row,
68
+ previousRow: previousRow as T[Extract<keyof T, string>],
69
+ changedKeys: origin.keys
70
+ })
71
+ }
60
72
  },
61
73
 
62
74
  // фильтрация строки под конкретную подписку
@@ -95,16 +107,27 @@ export class CuboCrdtAdapter<T extends CuboApiEntitiesMap<T>, A> {
95
107
  // пуш изменений документов из CRUD-методов ядра
96
108
  public pushCreate(entity: CuboEntity, row: any) {
97
109
  if (!entity.crdt) return
98
- this.server.ensureDocument(entity.alias as Extract<keyof T, string>, row)
110
+ const alias = entity.alias as Extract<keyof T, string>
111
+ this.server.ensureDocument(alias, row)
112
+ this.server.notifyMutation(alias, { action: 'create', row })
99
113
  }
100
114
 
101
- public pushUpdate(entity: CuboEntity, row: any) {
115
+ public pushUpdate(entity: CuboEntity, row: any, previousRow?: any, changedKeys?: string[]) {
102
116
  if (!entity.crdt) return
103
- this.server.ensureDocument(entity.alias as Extract<keyof T, string>, row)
117
+ const alias = entity.alias as Extract<keyof T, string>
118
+ this.server.ensureDocument(alias, row)
119
+ this.server.notifyMutation(alias, {
120
+ action: 'update',
121
+ row,
122
+ previousRow,
123
+ changedKeys
124
+ })
104
125
  }
105
126
 
106
127
  public pushDelete(entity: CuboEntity, row: any, origin?: CuboCrdtServerDocumentOrigin) {
107
128
  if (!entity.crdt) return
108
- this.server.deleteDocument(entity.alias as Extract<keyof T, string>, row, origin)
129
+ const alias = entity.alias as Extract<keyof T, string>
130
+ this.server.deleteDocument(alias, row, origin)
131
+ this.server.notifyMutation(alias, { action: 'delete', row })
109
132
  }
110
133
  }