oak-backend-base 3.4.1 → 3.5.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/LICENSE +232 -0
- package/README.md +3 -0
- package/lib/AppLoader.d.ts +5 -4
- package/lib/AppLoader.js +17 -17
- package/lib/ClusterAppLoader.d.ts +1 -2
- package/lib/ClusterAppLoader.js +8 -5
- package/lib/DataSubscriber.d.ts +18 -18
- package/lib/DataSubscriber.js +158 -158
- package/lib/DbStore.d.ts +2 -2
- package/lib/DbStore.js +1 -1
- package/lib/Synchronizer.d.ts +3 -2
- package/lib/Synchronizer.js +134 -103
- package/lib/cluster/DataSubscriber.d.ts +1 -2
- package/lib/cluster/DataSubscriber.js +1 -3
- package/lib/types/Sync.d.ts +16 -16
- package/lib/types/Sync.js +5 -5
- package/package.json +5 -5
package/lib/Synchronizer.js
CHANGED
|
@@ -15,8 +15,8 @@ class Synchronizer {
|
|
|
15
15
|
config;
|
|
16
16
|
schema;
|
|
17
17
|
remotePullInfoMap = {};
|
|
18
|
-
pullMaxBornAtMap = {};
|
|
19
18
|
channelDict = {};
|
|
19
|
+
contextBuilder;
|
|
20
20
|
pushAccessMap = {};
|
|
21
21
|
/**
|
|
22
22
|
* 向某一个远端对象push opers。根据幂等性,这里如果失败了必须反复推送
|
|
@@ -30,7 +30,12 @@ class Synchronizer {
|
|
|
30
30
|
// todo 加密
|
|
31
31
|
const queue = channel.queue;
|
|
32
32
|
const opers = queue.map(ele => ele.oper);
|
|
33
|
-
|
|
33
|
+
if (process.env.NODE_ENV === 'development') {
|
|
34
|
+
console.log('向远端结点sync oper', JSON.stringify(opers.map(ele => ({
|
|
35
|
+
id: ele.id,
|
|
36
|
+
seq: ele.$$seq$$,
|
|
37
|
+
}))), 'txnId:', context.getCurrentTxnId());
|
|
38
|
+
}
|
|
34
39
|
const finalApi = (0, path_1.join)(api, selfEncryptInfo.id);
|
|
35
40
|
const res = await fetch(finalApi, {
|
|
36
41
|
method: 'post',
|
|
@@ -61,6 +66,9 @@ class Synchronizer {
|
|
|
61
66
|
/**
|
|
62
67
|
* 返回结构见this.getSelfEndpoint
|
|
63
68
|
*/
|
|
69
|
+
if (process.env.NODE_ENV === 'development') {
|
|
70
|
+
console.log('同步oper返回结果', JSON.stringify(json), 'txnId:', context.getCurrentTxnId());
|
|
71
|
+
}
|
|
64
72
|
const { successIds, failed, redundantIds } = json;
|
|
65
73
|
if (failed) {
|
|
66
74
|
const { id, error } = failed;
|
|
@@ -76,7 +84,7 @@ class Synchronizer {
|
|
|
76
84
|
aliveOperIds.push(...this.channelDict[k].queue.map(ele => ele.oper.id));
|
|
77
85
|
}
|
|
78
86
|
}
|
|
79
|
-
const overIds = (0, lodash_1.difference)(successIds, aliveOperIds);
|
|
87
|
+
const overIds = (0, lodash_1.difference)(successIds.concat(redundantIds), aliveOperIds);
|
|
80
88
|
if (overIds.length > 0) {
|
|
81
89
|
await context.operate('oper', {
|
|
82
90
|
id: await (0, uuid_1.generateNewIdAsync)(),
|
|
@@ -112,7 +120,7 @@ class Synchronizer {
|
|
|
112
120
|
if (channel.queue.length > 0) {
|
|
113
121
|
// 最大延迟redo时间512秒
|
|
114
122
|
const retryDelay = Math.pow(2, Math.min(9, retry)) * 1000;
|
|
115
|
-
console.error(`有${channel.queue.length}个oper
|
|
123
|
+
console.error(`有${channel.queue.length}个oper同步失败,id是「${channel.queue.map(ele => ele.oper.id).join(',')}」,将于${retryDelay}毫秒后重试`);
|
|
116
124
|
return new Promise((resolve) => {
|
|
117
125
|
setTimeout(async () => {
|
|
118
126
|
await this.startChannel(context, channel, retry + 1);
|
|
@@ -149,11 +157,32 @@ class Synchronizer {
|
|
|
149
157
|
(0, assert_1.default)(channel.api === (0, path_1.join)(url, 'endpoint', endpoint));
|
|
150
158
|
(0, assert_1.default)(channel.entity === remoteEntity);
|
|
151
159
|
(0, assert_1.default)(channel.entityId === remoteEntityId);
|
|
160
|
+
if (channel.queue.find(ele => ele.oper.id === oper.id)) {
|
|
161
|
+
console.error('aaaaa');
|
|
162
|
+
}
|
|
152
163
|
channel.queue.push({
|
|
153
164
|
oper,
|
|
154
165
|
onSynchronized,
|
|
155
166
|
});
|
|
156
167
|
}
|
|
168
|
+
refineOperData(oper, rowIds) {
|
|
169
|
+
const { action, id, targetEntity, data, $$seq$$, filter } = oper;
|
|
170
|
+
const data2 = (action === 'create' && data instanceof Array) ? data.filter(ele => rowIds.includes(ele.id)) : data;
|
|
171
|
+
// 过滤掉数据中的跨事务trigger信息
|
|
172
|
+
if (data2 instanceof Array) {
|
|
173
|
+
data2.forEach((d) => {
|
|
174
|
+
(0, lodash_2.unset)(d, types_1.TriggerDataAttribute);
|
|
175
|
+
(0, lodash_2.unset)(d, types_1.TriggerUuidAttribute);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
(0, lodash_2.unset)(data2, types_1.TriggerDataAttribute);
|
|
180
|
+
(0, lodash_2.unset)(data2, types_1.TriggerUuidAttribute);
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
id, action, targetEntity, data: data2, $$seq$$, filter,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
157
186
|
async dispatchOperToChannels(oper, context) {
|
|
158
187
|
const { operatorId, targetEntity, filter, action, data } = oper;
|
|
159
188
|
const entityIds = (0, filter_1.getRelevantIds)(filter);
|
|
@@ -192,18 +221,7 @@ class Synchronizer {
|
|
|
192
221
|
}
|
|
193
222
|
const selfEncryptInfo = encryptInfoDict[selfEntityId];
|
|
194
223
|
// 推送到远端结点的oper
|
|
195
|
-
const oper2 =
|
|
196
|
-
id: oper.id,
|
|
197
|
-
action: action,
|
|
198
|
-
data: (action === 'create' && data instanceof Array) ? data.filter(ele => rowIds.includes(ele.id)) : data,
|
|
199
|
-
filter: {
|
|
200
|
-
id: rowIds.length === 1 ? rowIds[0] : {
|
|
201
|
-
$in: rowIds,
|
|
202
|
-
}
|
|
203
|
-
},
|
|
204
|
-
$$seq$$: oper.$$seq$$,
|
|
205
|
-
targetEntity,
|
|
206
|
-
};
|
|
224
|
+
const oper2 = this.refineOperData(oper, rowIds);
|
|
207
225
|
const { url } = await getRemoteAccessInfo(context, {
|
|
208
226
|
userId,
|
|
209
227
|
remoteEntityId: entityId,
|
|
@@ -227,69 +245,85 @@ class Synchronizer {
|
|
|
227
245
|
* 每个进程都保证把当前所有的oper顺序处理掉,就不会有乱序的问题,大家通过database上的锁来完成同步
|
|
228
246
|
* @param context
|
|
229
247
|
*/
|
|
230
|
-
async trySynchronizeOpers(
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
},
|
|
239
|
-
}
|
|
240
|
-
}, { dontCollect: true });
|
|
241
|
-
if (dirtyOpers.length > 0) {
|
|
242
|
-
// 这一步是加锁,保证只有一个进程完成推送,推送者提交前会将$$triggerData$$清零
|
|
243
|
-
const ids = dirtyOpers.map(ele => ele.id);
|
|
244
|
-
dirtyOpers = await context.select('oper', {
|
|
248
|
+
async trySynchronizeOpers() {
|
|
249
|
+
const context = this.contextBuilder();
|
|
250
|
+
await context.begin();
|
|
251
|
+
// 暂时全用root身份去执行(未来不一定对)
|
|
252
|
+
await context.initialize();
|
|
253
|
+
context.openRootMode();
|
|
254
|
+
try {
|
|
255
|
+
let dirtyOpers = await context.select('oper', {
|
|
245
256
|
data: {
|
|
246
257
|
id: 1,
|
|
247
|
-
action: 1,
|
|
248
|
-
data: 1,
|
|
249
|
-
targetEntity: 1,
|
|
250
|
-
operatorId: 1,
|
|
251
|
-
[types_1.TriggerDataAttribute]: 1,
|
|
252
|
-
bornAt: 1,
|
|
253
|
-
$$createAt$$: 1,
|
|
254
|
-
$$seq$$: 1,
|
|
255
|
-
filter: 1,
|
|
256
258
|
},
|
|
257
259
|
filter: {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
260
|
+
[types_1.TriggerDataAttribute]: {
|
|
261
|
+
$exists: true,
|
|
262
|
+
},
|
|
263
|
+
}
|
|
264
|
+
}, { dontCollect: true });
|
|
262
265
|
if (dirtyOpers.length > 0) {
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
await
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
266
|
+
// 这一步是加锁,保证只有一个进程完成推送,推送者提交前会将$$triggerData$$清零
|
|
267
|
+
const ids = dirtyOpers.map(ele => ele.id);
|
|
268
|
+
dirtyOpers = await context.select('oper', {
|
|
269
|
+
data: {
|
|
270
|
+
id: 1,
|
|
271
|
+
action: 1,
|
|
272
|
+
data: 1,
|
|
273
|
+
targetEntity: 1,
|
|
274
|
+
operatorId: 1,
|
|
275
|
+
[types_1.TriggerDataAttribute]: 1,
|
|
276
|
+
bornAt: 1,
|
|
277
|
+
$$createAt$$: 1,
|
|
278
|
+
$$seq$$: 1,
|
|
279
|
+
filter: 1,
|
|
280
|
+
},
|
|
281
|
+
filter: {
|
|
282
|
+
id: { $in: ids },
|
|
283
|
+
},
|
|
284
|
+
}, { dontCollect: true, forUpdate: true });
|
|
285
|
+
dirtyOpers = dirtyOpers.filter(ele => !!ele[types_1.TriggerDataAttribute]);
|
|
286
|
+
if (dirtyOpers.length > 0) {
|
|
287
|
+
for (const c in this.channelDict) {
|
|
288
|
+
(0, assert_1.default)(this.channelDict[c].queue.length === 0);
|
|
272
289
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
await
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
[types_1.TriggerDataAttribute]: null,
|
|
280
|
-
[types_1.TriggerUuidAttribute]: null,
|
|
281
|
-
},
|
|
282
|
-
filter: {
|
|
283
|
-
id: {
|
|
284
|
-
$in: unpushedIds,
|
|
285
|
-
}
|
|
290
|
+
const pushedIds = [];
|
|
291
|
+
const unpushedIds = [];
|
|
292
|
+
await Promise.all(dirtyOpers.map(async (oper) => {
|
|
293
|
+
const result = await this.dispatchOperToChannels(oper, context);
|
|
294
|
+
if (result) {
|
|
295
|
+
pushedIds.push(oper.id);
|
|
286
296
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
297
|
+
else {
|
|
298
|
+
unpushedIds.push(oper.id);
|
|
299
|
+
}
|
|
300
|
+
}));
|
|
301
|
+
if (unpushedIds.length > 0) {
|
|
302
|
+
await context.operate('oper', {
|
|
303
|
+
id: await (0, uuid_1.generateNewIdAsync)(),
|
|
304
|
+
action: 'update',
|
|
305
|
+
data: {
|
|
306
|
+
[types_1.TriggerDataAttribute]: null,
|
|
307
|
+
[types_1.TriggerUuidAttribute]: null,
|
|
308
|
+
},
|
|
309
|
+
filter: {
|
|
310
|
+
id: {
|
|
311
|
+
$in: unpushedIds,
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}, {});
|
|
315
|
+
}
|
|
316
|
+
if (pushedIds.length > 0) {
|
|
317
|
+
await this.startAllChannel(context);
|
|
318
|
+
}
|
|
291
319
|
}
|
|
292
320
|
}
|
|
321
|
+
await context.commit();
|
|
322
|
+
}
|
|
323
|
+
catch (err) {
|
|
324
|
+
await context.rollback();
|
|
325
|
+
console.error(err);
|
|
326
|
+
throw err;
|
|
293
327
|
}
|
|
294
328
|
}
|
|
295
329
|
makeCreateOperTrigger() {
|
|
@@ -395,18 +429,19 @@ class Synchronizer {
|
|
|
395
429
|
return pushEntities.includes(data.targetEntity)
|
|
396
430
|
&& !!this.pushAccessMap[targetEntity].find(({ actions }) => !actions || actions.includes(action));
|
|
397
431
|
},
|
|
398
|
-
fn: async ({ ids }
|
|
432
|
+
fn: async ({ ids }) => {
|
|
399
433
|
(0, assert_1.default)(ids.length === 1);
|
|
400
|
-
this.trySynchronizeOpers(
|
|
434
|
+
this.trySynchronizeOpers();
|
|
401
435
|
// 内部自主处理triggerData,因此不需要让triggerExecutor处理
|
|
402
436
|
throw new types_1.OakMakeSureByMySelfException();
|
|
403
437
|
}
|
|
404
438
|
};
|
|
405
439
|
return createOperTrigger;
|
|
406
440
|
}
|
|
407
|
-
constructor(config, schema) {
|
|
441
|
+
constructor(config, schema, contextBuilder) {
|
|
408
442
|
this.config = config;
|
|
409
443
|
this.schema = schema;
|
|
444
|
+
this.contextBuilder = contextBuilder;
|
|
410
445
|
}
|
|
411
446
|
/**
|
|
412
447
|
* 根据sync的定义,生成对应的 commit triggers
|
|
@@ -418,8 +453,8 @@ class Synchronizer {
|
|
|
418
453
|
getSyncRoutine() {
|
|
419
454
|
return {
|
|
420
455
|
name: 'checkpoint routine for sync',
|
|
421
|
-
routine: async (
|
|
422
|
-
this.trySynchronizeOpers(
|
|
456
|
+
routine: async () => {
|
|
457
|
+
this.trySynchronizeOpers();
|
|
423
458
|
return {};
|
|
424
459
|
},
|
|
425
460
|
};
|
|
@@ -433,7 +468,9 @@ class Synchronizer {
|
|
|
433
468
|
// body中是传过来的oper数组信息
|
|
434
469
|
const { entity, entityId } = params;
|
|
435
470
|
const { [OAK_SYNC_HEADER_ENTITY]: meEntity, [OAK_SYNC_HEADER_ENTITYID]: meEntityId } = headers;
|
|
436
|
-
|
|
471
|
+
if (process.env.NODE_ENV === 'development') {
|
|
472
|
+
console.log('接收到来自远端的sync数据', entity, JSON.stringify(body));
|
|
473
|
+
}
|
|
437
474
|
const successIds = [];
|
|
438
475
|
const redundantIds = [];
|
|
439
476
|
let failed;
|
|
@@ -447,6 +484,7 @@ class Synchronizer {
|
|
|
447
484
|
if (pullEntities) {
|
|
448
485
|
pullEntities.forEach((def) => pullEntityDict[def.entity] = def);
|
|
449
486
|
}
|
|
487
|
+
const closeFn = context.openRootMode();
|
|
450
488
|
this.remotePullInfoMap[entity][entityId] = {
|
|
451
489
|
pullInfo: await getPullInfo(context, {
|
|
452
490
|
selfId: meEntityId,
|
|
@@ -454,6 +492,7 @@ class Synchronizer {
|
|
|
454
492
|
}),
|
|
455
493
|
pullEntityDict,
|
|
456
494
|
};
|
|
495
|
+
closeFn();
|
|
457
496
|
}
|
|
458
497
|
const { pullInfo, pullEntityDict } = this.remotePullInfoMap[entity][entityId];
|
|
459
498
|
const { userId, algorithm, publicKey, cxtInfo } = pullInfo;
|
|
@@ -463,36 +502,30 @@ class Synchronizer {
|
|
|
463
502
|
await context.initialize(cxtInfo);
|
|
464
503
|
}
|
|
465
504
|
// todo 解密
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
505
|
+
const opers = body;
|
|
506
|
+
const ids = opers.map(ele => ele.id);
|
|
507
|
+
const existeIds = (await context.select('oper', {
|
|
508
|
+
data: {
|
|
509
|
+
id: 1,
|
|
510
|
+
},
|
|
511
|
+
filter: {
|
|
512
|
+
id: {
|
|
513
|
+
$in: ids,
|
|
474
514
|
},
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
count: 1,
|
|
485
|
-
}, { dontCollect: true });
|
|
486
|
-
this.pullMaxBornAtMap[entityId] = maxHisOper?.bornAt || 0;
|
|
515
|
+
}
|
|
516
|
+
}, {})).map(ele => ele.id);
|
|
517
|
+
const staleOpers = opers.filter(ele => existeIds.includes(ele.id));
|
|
518
|
+
const freshOpers = opers.filter(ele => !existeIds.includes(ele.id));
|
|
519
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
520
|
+
const maxStaleSeq = Math.max(...staleOpers.map(ele => ele.$$seq$$));
|
|
521
|
+
for (const oper of freshOpers) {
|
|
522
|
+
(0, assert_1.default)(oper.$$seq$$ > maxStaleSeq, '发现了seq没有按序进行同步');
|
|
523
|
+
}
|
|
487
524
|
}
|
|
488
|
-
let maxBornAt = this.pullMaxBornAtMap[entityId];
|
|
489
|
-
const opers = body;
|
|
490
|
-
const outdatedOpers = opers.filter(ele => ele.$$seq$$ <= maxBornAt);
|
|
491
|
-
const freshOpers = opers.filter(ele => ele.$$seq$$ > maxBornAt);
|
|
492
525
|
await Promise.all([
|
|
493
526
|
// 无法严格保证推送按bornAt,所以一旦还有outdatedOpers,检查其已经被apply
|
|
494
527
|
(async () => {
|
|
495
|
-
const ids =
|
|
528
|
+
const ids = staleOpers.map(ele => ele.id);
|
|
496
529
|
if (ids.length > 0) {
|
|
497
530
|
const opersExisted = await context.select('oper', {
|
|
498
531
|
data: {
|
|
@@ -538,7 +571,6 @@ class Synchronizer {
|
|
|
538
571
|
};
|
|
539
572
|
await context.operate(targetEntity, operation, {});
|
|
540
573
|
successIds.push(id);
|
|
541
|
-
maxBornAt = $$seq$$;
|
|
542
574
|
}
|
|
543
575
|
catch (err) {
|
|
544
576
|
console.error(err);
|
|
@@ -552,7 +584,6 @@ class Synchronizer {
|
|
|
552
584
|
}
|
|
553
585
|
})()
|
|
554
586
|
]);
|
|
555
|
-
this.pullMaxBornAtMap[entityId] = maxBornAt;
|
|
556
587
|
return {
|
|
557
588
|
successIds,
|
|
558
589
|
failed,
|
|
@@ -12,8 +12,7 @@ import { Namespace } from 'socket.io';
|
|
|
12
12
|
export default class DataSubscriber<ED extends EntityDict & BaseEntityDict, Context extends BackendRuntimeContext<ED>> {
|
|
13
13
|
private ns;
|
|
14
14
|
private nsServer?;
|
|
15
|
-
|
|
16
|
-
constructor(ns: Namespace, contextBuilder: (scene?: string) => Promise<Context>, nsServer?: Namespace);
|
|
15
|
+
constructor(ns: Namespace, nsServer?: Namespace);
|
|
17
16
|
/**
|
|
18
17
|
* 来自外部的socket连接,监听数据变化
|
|
19
18
|
*/
|
|
@@ -12,11 +12,9 @@ const console_1 = require("console");
|
|
|
12
12
|
class DataSubscriber {
|
|
13
13
|
ns;
|
|
14
14
|
nsServer;
|
|
15
|
-
|
|
16
|
-
constructor(ns, contextBuilder, nsServer) {
|
|
15
|
+
constructor(ns, nsServer) {
|
|
17
16
|
this.ns = ns;
|
|
18
17
|
this.nsServer = nsServer;
|
|
19
|
-
this.contextBuilder = contextBuilder;
|
|
20
18
|
this.startup();
|
|
21
19
|
}
|
|
22
20
|
/**
|
package/lib/types/Sync.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { EntityDict } from 'oak-domain/lib/types';
|
|
2
|
-
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
|
3
|
-
import { BackendRuntimeContext } from 'oak-frontend-base/lib/context/BackendRuntimeContext';
|
|
4
|
-
import { RemotePushInfo, RemotePullInfo, SelfEncryptInfo, SyncRemoteConfigBase, SyncSelfConfigBase, SyncConfig } from 'oak-domain/lib/types/Sync';
|
|
5
|
-
interface SyncRemoteConfigWrapper<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>> extends SyncRemoteConfigBase<ED, Cxt> {
|
|
6
|
-
getRemotePushInfo: (userId: string) => Promise<RemotePushInfo>;
|
|
7
|
-
getRemotePullInfo: (id: string) => Promise<RemotePullInfo>;
|
|
8
|
-
}
|
|
9
|
-
interface SyncSelfConfigWrapper<ED extends EntityDict & BaseEntityDict> extends SyncSelfConfigBase<ED> {
|
|
10
|
-
getSelfEncryptInfo: () => Promise<SelfEncryptInfo>;
|
|
11
|
-
}
|
|
12
|
-
export interface SyncConfigWrapper<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>> {
|
|
13
|
-
self: SyncSelfConfigWrapper<ED>;
|
|
14
|
-
remotes: Array<SyncRemoteConfigWrapper<ED, Cxt>>;
|
|
15
|
-
}
|
|
16
|
-
export { RemotePushInfo, RemotePullInfo, SelfEncryptInfo, SyncConfig, };
|
|
1
|
+
import { EntityDict } from 'oak-domain/lib/types';
|
|
2
|
+
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
|
3
|
+
import { BackendRuntimeContext } from 'oak-frontend-base/lib/context/BackendRuntimeContext';
|
|
4
|
+
import { RemotePushInfo, RemotePullInfo, SelfEncryptInfo, SyncRemoteConfigBase, SyncSelfConfigBase, SyncConfig } from 'oak-domain/lib/types/Sync';
|
|
5
|
+
interface SyncRemoteConfigWrapper<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>> extends SyncRemoteConfigBase<ED, Cxt> {
|
|
6
|
+
getRemotePushInfo: (userId: string) => Promise<RemotePushInfo>;
|
|
7
|
+
getRemotePullInfo: (id: string) => Promise<RemotePullInfo>;
|
|
8
|
+
}
|
|
9
|
+
interface SyncSelfConfigWrapper<ED extends EntityDict & BaseEntityDict> extends SyncSelfConfigBase<ED> {
|
|
10
|
+
getSelfEncryptInfo: () => Promise<SelfEncryptInfo>;
|
|
11
|
+
}
|
|
12
|
+
export interface SyncConfigWrapper<ED extends EntityDict & BaseEntityDict, Cxt extends BackendRuntimeContext<ED>> {
|
|
13
|
+
self: SyncSelfConfigWrapper<ED>;
|
|
14
|
+
remotes: Array<SyncRemoteConfigWrapper<ED, Cxt>>;
|
|
15
|
+
}
|
|
16
|
+
export { RemotePushInfo, RemotePullInfo, SelfEncryptInfo, SyncConfig, };
|
package/lib/types/Sync.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
;
|
|
4
|
-
;
|
|
5
|
-
;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
;
|
|
4
|
+
;
|
|
5
|
+
;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oak-backend-base",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "oak-backend-base",
|
|
5
5
|
"main": "lib/index",
|
|
6
6
|
"author": {
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
"mysql": "^2.18.1",
|
|
21
21
|
"mysql2": "^2.3.3",
|
|
22
22
|
"node-schedule": "^2.1.0",
|
|
23
|
-
"oak-common-aspect": "^2.3.
|
|
24
|
-
"oak-db": "^3.2.
|
|
25
|
-
"oak-domain": "^4.
|
|
26
|
-
"oak-frontend-base": "^4.
|
|
23
|
+
"oak-common-aspect": "^2.3.1",
|
|
24
|
+
"oak-db": "^3.2.1",
|
|
25
|
+
"oak-domain": "^4.5.0",
|
|
26
|
+
"oak-frontend-base": "^4.5.0",
|
|
27
27
|
"socket.io": "^4.7.2",
|
|
28
28
|
"socket.io-client": "^4.7.2",
|
|
29
29
|
"uuid": "^8.3.2"
|