@aiao/rxdb-plugin-sync 0.0.0-stage → 0.0.28
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 +21 -0
- package/README.md +81 -2
- package/dist/SyncManager.d.ts +426 -0
- package/dist/SyncManager.d.ts.map +1 -0
- package/dist/branch-change-id.d.ts +31 -0
- package/dist/branch-change-id.d.ts.map +1 -0
- package/dist/branch-materialization-source.d.ts +22 -0
- package/dist/branch-materialization-source.d.ts.map +1 -0
- package/dist/branch-utils.d.ts +40 -0
- package/dist/branch-utils.d.ts.map +1 -0
- package/dist/bulk-sync.d.ts +117 -0
- package/dist/bulk-sync.d.ts.map +1 -0
- package/dist/cascade-blocking.d.ts +38 -0
- package/dist/cascade-blocking.d.ts.map +1 -0
- package/dist/check-repository-updates.d.ts +47 -0
- package/dist/check-repository-updates.d.ts.map +1 -0
- package/dist/cleanup-expired.d.ts +56 -0
- package/dist/cleanup-expired.d.ts.map +1 -0
- package/dist/dependency-graph.d.ts +128 -0
- package/dist/dependency-graph.d.ts.map +1 -0
- package/dist/get-all-repository-sync-status.d.ts +58 -0
- package/dist/get-all-repository-sync-status.d.ts.map +1 -0
- package/dist/get-repository-sync-status.d.ts +68 -0
- package/dist/get-repository-sync-status.d.ts.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3773 -0
- package/dist/plugin.d.ts +74 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/pull-ancestor-changes.d.ts +41 -0
- package/dist/pull-ancestor-changes.d.ts.map +1 -0
- package/dist/pull-batch.d.ts +16 -0
- package/dist/pull-batch.d.ts.map +1 -0
- package/dist/pull-conflict-utils.d.ts +43 -0
- package/dist/pull-conflict-utils.d.ts.map +1 -0
- package/dist/pull-repository.d.ts +55 -0
- package/dist/pull-repository.d.ts.map +1 -0
- package/dist/pull-round.d.ts +41 -0
- package/dist/pull-round.d.ts.map +1 -0
- package/dist/pull.d.ts +16 -0
- package/dist/pull.d.ts.map +1 -0
- package/dist/push-branch.d.ts +22 -0
- package/dist/push-branch.d.ts.map +1 -0
- package/dist/push-repository.d.ts +79 -0
- package/dist/push-repository.d.ts.map +1 -0
- package/dist/push.d.ts +14 -0
- package/dist/push.d.ts.map +1 -0
- package/dist/query-cache-outbox.d.ts +120 -0
- package/dist/query-cache-outbox.d.ts.map +1 -0
- package/dist/sync-branches.d.ts +81 -0
- package/dist/sync-branches.d.ts.map +1 -0
- package/dist/sync-listeners.d.ts +20 -0
- package/dist/sync-listeners.d.ts.map +1 -0
- package/dist/sync-manager.utils.d.ts +36 -0
- package/dist/sync-manager.utils.d.ts.map +1 -0
- package/dist/sync-repository.d.ts +64 -0
- package/dist/sync-repository.d.ts.map +1 -0
- package/dist/topological-sort.d.ts +126 -0
- package/dist/topological-sort.d.ts.map +1 -0
- package/package.json +60 -3
- package/src/SyncManager.ts +690 -0
- package/src/branch-change-id.ts +70 -0
- package/src/branch-materialization-source.ts +445 -0
- package/src/branch-utils.ts +74 -0
- package/src/bulk-sync.ts +349 -0
- package/src/cascade-blocking.ts +61 -0
- package/src/check-repository-updates.ts +143 -0
- package/src/cleanup-expired.ts +285 -0
- package/src/dependency-graph.ts +324 -0
- package/src/get-all-repository-sync-status.ts +115 -0
- package/src/get-repository-sync-status.ts +237 -0
- package/src/index.ts +58 -0
- package/src/plugin.ts +132 -0
- package/src/pull-ancestor-changes.ts +61 -0
- package/src/pull-batch.ts +386 -0
- package/src/pull-conflict-utils.ts +284 -0
- package/src/pull-repository.ts +700 -0
- package/src/pull-round.ts +103 -0
- package/src/pull.ts +204 -0
- package/src/push-branch.ts +62 -0
- package/src/push-repository.ts +1541 -0
- package/src/push.ts +106 -0
- package/src/query-cache-outbox.ts +939 -0
- package/src/sync-branches.ts +276 -0
- package/src/sync-listeners.ts +309 -0
- package/src/sync-manager.utils.ts +48 -0
- package/src/sync-repository.ts +307 -0
- package/src/topological-sort.ts +246 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { SyncManager } from './SyncManager.js';
|
|
2
|
+
/**
|
|
3
|
+
* {@link SyncManager.syncBranches} 一轮的结果。
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* `created + updated + skipped.length` 不一定等于 `total`:本地已有、且早已标了 `remote` 的
|
|
7
|
+
* 分支既不计 `updated`,也不进 `skipped`。
|
|
8
|
+
*/
|
|
9
|
+
export interface SyncBranchesResult {
|
|
10
|
+
/** 本轮在本地新建的远端分支数。 */
|
|
11
|
+
created: number;
|
|
12
|
+
/** 本地已有、本轮补上 `remote: true` 标记的分支数。 */
|
|
13
|
+
updated: number;
|
|
14
|
+
/** 远端本轮交回的分支总数,含被跳过的。 */
|
|
15
|
+
total: number;
|
|
16
|
+
/**
|
|
17
|
+
* 本轮**未创建**的远端分支 id —— 具体原因见同一个 id 在 {@link skipReasons} 里的条目。
|
|
18
|
+
*
|
|
19
|
+
* 一条分支被跳过,可能是它自己的问题(id 不可用、或分叉点变更还没拉到本地翻译不出本地
|
|
20
|
+
* id),也可能单纯因为它的父本轮被跳过——后一种情形下这条分支自身完全合格,但父本轮
|
|
21
|
+
* 不会落库,若仍然照常创建,它的 `parentId` 就是一条指向「本轮不存在的父」的悬空外键
|
|
22
|
+
* (`rxdb_branch.parentId` 是 `PRAGMA defer_foreign_keys` 延迟到 COMMIT 才检查的外键,
|
|
23
|
+
* 届时会回滚整个事务,连同本轮所有本该成功的分支)。三种成因统一走同一条 `skipped`
|
|
24
|
+
* 通道,因为对调用方而言处理方式是一样的:这个 id 本轮没有对应的本地分支,仅此而已。
|
|
25
|
+
*
|
|
26
|
+
* **跳过不留持久标记**:每轮都全量重拉远端分支、从头再判一遍,`skipped` 与
|
|
27
|
+
* {@link skipReasons} 只报这一轮。`unresolved-from-change-id` 在分叉点变更拉到本地后自愈,
|
|
28
|
+
* 挂在它下面的 `ancestor-skipped` 随之自愈;`invalid-id` 则远端不改就每轮重拉、重跳,
|
|
29
|
+
* 一直占位——调用方要区分这两类,看 {@link skipReasons}。要不要记一个持久的「已知坏行」
|
|
30
|
+
* 标记,登记在 `requirements/roadmap.md`「epic-006 评审顺延的架构项」。
|
|
31
|
+
*/
|
|
32
|
+
skipped: string[];
|
|
33
|
+
/**
|
|
34
|
+
* `skipped` 里每一个 id 对应的具体跳过原因;key 覆盖 `skipped` 的每一项,一一对应。
|
|
35
|
+
*
|
|
36
|
+
* 单开一个字段而不是把原因塞进 `skipped` 数组本身:`skipped: string[]` 这个形状已经被
|
|
37
|
+
* 外部当「id 列表」消费,改成对象数组是破坏性变更;`Record<id, reason>` 是纯增量,
|
|
38
|
+
* 只读 `skipped` 的既有调用方不受影响。
|
|
39
|
+
*/
|
|
40
|
+
skipReasons: Record<string, SyncBranchSkipReason>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 一条远端分支本轮被跳过的具体原因。
|
|
44
|
+
*
|
|
45
|
+
* @remarks
|
|
46
|
+
* 三种成因互斥——处理顺序保证每条被跳过的分支只会落进其中一种:
|
|
47
|
+
* - `invalid-id`:分支自己的 id 落不进本地 `rxdb_branch.id`(见 {@link isUsableBranchId})。
|
|
48
|
+
* - `unresolved-from-change-id`:分叉点变更还没拉到本地,`fromChangeId` 翻译不出本地 id。
|
|
49
|
+
* - `ancestor-skipped`:分支自身没有问题,但它的**直接父**本轮已经被跳过(不管父是因为
|
|
50
|
+
* 哪一种成因被跳的)。`ancestorId` 记的是那个直接父的 id,不是链路最顶端的根因——
|
|
51
|
+
* 要追根因,沿 `skipReasons[ancestorId]` 递归上溯,直到查到的原因不再是
|
|
52
|
+
* `ancestor-skipped` 为止。
|
|
53
|
+
*/
|
|
54
|
+
export type SyncBranchSkipReason = {
|
|
55
|
+
readonly cause: 'invalid-id';
|
|
56
|
+
} | {
|
|
57
|
+
readonly cause: 'unresolved-from-change-id';
|
|
58
|
+
} | {
|
|
59
|
+
readonly cause: 'ancestor-skipped';
|
|
60
|
+
readonly ancestorId: string;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* 从远程拉取所有分支信息并同步到本地
|
|
64
|
+
*
|
|
65
|
+
* 规则:
|
|
66
|
+
* 1. 远程新分支 → 在本地创建(local: false, remote: true)
|
|
67
|
+
* 2. 本地已有的远程分支 → 更新 remote 标记为 true
|
|
68
|
+
* 3. 纯本地分支(remote=false)→ 不受影响
|
|
69
|
+
*
|
|
70
|
+
* @remarks
|
|
71
|
+
* 读本地、排序、落库全部在**同一个事务窗口**内完成:
|
|
72
|
+
*
|
|
73
|
+
* - 无事务时中途失败会留下半批已提交的分支,下次重试撞主键,同步就此永久卡死;
|
|
74
|
+
* - 读若在事务外做,快照与写之间存在窗口,并发建分支会让「本地已有」的判断过时,
|
|
75
|
+
* 重复 create 同样撞主键。
|
|
76
|
+
*
|
|
77
|
+
* 事务体内只能用 `executor` 作用域的仓库。绑在适配器上的那一份走并发度 1 的写队列,
|
|
78
|
+
* 在事务体内调用会排到自己这个事务后面 —— 直接死锁。
|
|
79
|
+
*/
|
|
80
|
+
export declare function syncBranches(sm: SyncManager): Promise<SyncBranchesResult>;
|
|
81
|
+
//# sourceMappingURL=sync-branches.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-branches.d.ts","sourceRoot":"","sources":["../src/sync-branches.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,qBAAqB;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IAEd;;;;;;;;;;;;;;;OAeG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;IAElB;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;CACnD;AAED;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,oBAAoB,GAC5B;IAAE,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAA;CAAE,GAChC;IAAE,QAAQ,CAAC,KAAK,EAAE,2BAA2B,CAAA;CAAE,GAC/C;IAAE,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAgFxE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA4G/E"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Subscription } from 'rxjs';
|
|
2
|
+
import { SyncManager } from './SyncManager.js';
|
|
3
|
+
/**
|
|
4
|
+
* 设置 SyncManager 的同步监听器
|
|
5
|
+
*
|
|
6
|
+
* 包含两条 reactive 链路:
|
|
7
|
+
* 1. 「已连接且网络可达」→ 自动重放 QueryCache 出站队列,离线期间由退避节拍驱动重试,
|
|
8
|
+
* 每个仓库失败仅吞错。changelog 的 `push` 不在其中,见 {@link resumeSync}
|
|
9
|
+
* 2. Remote 实体事件 → 累计 `pullableCount`(仅统计当前激活分支)
|
|
10
|
+
*
|
|
11
|
+
* 调用方负责管理返回的 subscriptions / removers 生命周期(destroy 时清理)。
|
|
12
|
+
*
|
|
13
|
+
* @param sm - 当前同步管理器
|
|
14
|
+
* @returns 已注册的 rxjs subscriptions 和事件解绑闭包
|
|
15
|
+
*/
|
|
16
|
+
export declare function setupSyncListeners(sm: SyncManager): {
|
|
17
|
+
subscriptions: Subscription[];
|
|
18
|
+
removers: Array<() => void>;
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=sync-listeners.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-listeners.d.ts","sourceRoot":"","sources":["../src/sync-listeners.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAyC,YAAY,EAAE,MAAM,MAAM,CAAC;AAG3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAqNpD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,WAAW,GAAG;IACnD,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;CAC7B,CA4DA"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SyncRepositoryResult } from './sync-repository.js';
|
|
2
|
+
/**
|
|
3
|
+
* 「这次同步已经改写了本地数据」的共同判据形状。
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* 四个粒度的结果都满足它,所以判据只需要写一份:整库 / 单仓库的 `PullResult` 只有
|
|
7
|
+
* `historyInvalidated`,`SyncRepositoryResult` 还多一段 `pushResult`。两项都取可选,
|
|
8
|
+
* 缺哪一段就当那一段没有进度。
|
|
9
|
+
*/
|
|
10
|
+
interface SyncedProgress {
|
|
11
|
+
readonly historyInvalidated?: boolean;
|
|
12
|
+
readonly pushResult?: {
|
|
13
|
+
readonly pushed: number;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** 一次仓库同步是否改写了本地实体数据(undo 历史边界因此失效) */
|
|
17
|
+
export declare const hasSyncedData: (result: SyncedProgress | undefined) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* 中断的同步里是否带着「已经落库 / 已经上行」的进度。
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* 部分成功以 {@link RxDBPartialSyncError} 的形式抛出,进度只挂在它的 `result` 上。
|
|
23
|
+
* `pull` / `pullRepository` / `sync` / `syncRepository` 四个入口共用这一条判据 ——
|
|
24
|
+
* 各写各的 `instanceof` + 强转,迟早会有一个入口漏掉 `pushResult` 那一半。
|
|
25
|
+
*/
|
|
26
|
+
export declare const partialSyncInvalidatesHistory: (error: unknown) => boolean;
|
|
27
|
+
/**
|
|
28
|
+
* 取出失败项里携带的部分进度。
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* 仓库在失败前可能已经提交了部分结果,它只存在于 {@link RxDBPartialSyncError.result}。
|
|
32
|
+
* 忽略它会让「远端数据已落库但 undo 边界没推进」的状态逃过检查。
|
|
33
|
+
*/
|
|
34
|
+
export declare const partialResultOf: (error: Error | undefined) => SyncRepositoryResult | undefined;
|
|
35
|
+
export {};
|
|
36
|
+
//# sourceMappingURL=sync-manager.utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-manager.utils.d.ts","sourceRoot":"","sources":["../src/sync-manager.utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAEjE;;;;;;;GAOG;AACH,UAAU,cAAc;IACtB,QAAQ,CAAC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,UAAU,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACnD;AAED,uCAAuC;AACvC,eAAO,MAAM,aAAa,GAAI,QAAQ,cAAc,GAAG,SAAS,KAAG,OACW,CAAC;AAE/E;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,GAAI,OAAO,OAAO,KAAG,OACyB,CAAC;AAEzF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,KAAK,GAAG,SAAS,KAAG,oBAAoB,GAAG,SACU,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { SyncProgress, SyncRejection } from '@aiao/rxdb';
|
|
2
|
+
import { SyncManager } from './SyncManager.js';
|
|
3
|
+
import { PullRepositoryOptions, PullRepositoryResult } from './pull-repository.js';
|
|
4
|
+
import { PushRepositoryOptions, PushRepositoryResult } from './push-repository.js';
|
|
5
|
+
/**
|
|
6
|
+
* @fileoverview 仓库级别的同步操作
|
|
7
|
+
*
|
|
8
|
+
* 将仓库的拉取(pull)和推送(push)操作组合在一起,保证正确的执行顺序。
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* 仓库同步选项
|
|
12
|
+
*/
|
|
13
|
+
export interface SyncRepositoryOptions {
|
|
14
|
+
/**
|
|
15
|
+
* 同步方向
|
|
16
|
+
* @default 'sync'
|
|
17
|
+
*/
|
|
18
|
+
direction?: 'pull' | 'push' | 'sync';
|
|
19
|
+
/**
|
|
20
|
+
* 拉取(pull)选项
|
|
21
|
+
*/
|
|
22
|
+
pull?: PullRepositoryOptions;
|
|
23
|
+
/**
|
|
24
|
+
* 推送(push)选项
|
|
25
|
+
*/
|
|
26
|
+
push?: PushRepositoryOptions;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 仓库同步结果
|
|
30
|
+
*/
|
|
31
|
+
export interface SyncRepositoryResult extends SyncProgress {
|
|
32
|
+
/**
|
|
33
|
+
* 拉取结果
|
|
34
|
+
*/
|
|
35
|
+
pullResult: PullRepositoryResult;
|
|
36
|
+
/**
|
|
37
|
+
* 推送结果
|
|
38
|
+
*/
|
|
39
|
+
pushResult: PushRepositoryResult;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 同步一个仓库(先拉取再推送)
|
|
43
|
+
*
|
|
44
|
+
* @param sm - SyncManager 实例
|
|
45
|
+
* @param namespace - 实体命名空间
|
|
46
|
+
* @param entity - 实体名称
|
|
47
|
+
* @param options - 同步选项
|
|
48
|
+
* @param rejectionSink - 推送被拒清单收集器,语义同 {@link pushRepository} 的同名参数
|
|
49
|
+
* @returns 同步结果
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* // 同步 Todo 仓库(pull + push)
|
|
54
|
+
* const result = await syncRepository(sm, 'public', 'Todo');
|
|
55
|
+
*
|
|
56
|
+
* // 使用自定义选项同步
|
|
57
|
+
* const result = await syncRepository(sm, 'public', 'Todo', {
|
|
58
|
+
* pull: { limit: 500, fetchAll: true },
|
|
59
|
+
* push: { batchSize: 100 }
|
|
60
|
+
* });
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function syncRepository(sm: SyncManager, namespace: string, entity: string, options?: SyncRepositoryOptions, rejectionSink?: SyncRejection[]): Promise<SyncRepositoryResult>;
|
|
64
|
+
//# sourceMappingURL=sync-repository.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-repository.d.ts","sourceRoot":"","sources":["../src/sync-repository.ts"],"names":[],"mappings":"AAAA,OAAO,EASL,KAAK,YAAY,EACjB,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAGL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAGL,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAC9B;;;;GAIG;AAEH;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAErC;;OAEG;IACH,IAAI,CAAC,EAAE,qBAAqB,CAAC;IAE7B;;OAEG;IACH,IAAI,CAAC,EAAE,qBAAqB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,YAAY;IACxD;;OAEG;IACH,UAAU,EAAE,oBAAoB,CAAC;IAEjC;;OAEG;IACH,UAAU,EAAE,oBAAoB,CAAC;CAClC;AAmGD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,WAAW,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,qBAAqB,EAC/B,aAAa,CAAC,EAAE,aAAa,EAAE,GAC9B,OAAO,CAAC,oBAAoB,CAAC,CA+B/B"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { DependencyGraph, RepositoryIdentifier } from './dependency-graph.js';
|
|
2
|
+
/**
|
|
3
|
+
* 排序方向
|
|
4
|
+
*/
|
|
5
|
+
export type SortDirection = 'pull' | 'push';
|
|
6
|
+
/**
|
|
7
|
+
* 依赖图上的一条边。
|
|
8
|
+
*
|
|
9
|
+
* - `dependsOn`:本仓库**依赖**的仓库(父,外键指过去的那一端)
|
|
10
|
+
* - `requiredBy`:**依赖本仓库**的仓库(子,外键指过来的那一端)
|
|
11
|
+
*/
|
|
12
|
+
export type DependencyEdge = 'dependsOn' | 'requiredBy';
|
|
13
|
+
/**
|
|
14
|
+
* 排序方向沿依赖图上的哪条边展开。
|
|
15
|
+
*
|
|
16
|
+
* 这条对应关系是整个级联调度的枢纽,所以只在这里写一次:拓扑序沿哪条边建立,
|
|
17
|
+
* 「谁排在我前面」就是哪条边,级联的依赖闸门也必须看同一条边。
|
|
18
|
+
* 从前它以 `direction === 'pull' ? dep.dependsOn : dep.requiredBy` 的形式散在
|
|
19
|
+
* {@link topologicalSort} 里,闸门那一侧则各写各的,于是 DELETE 相位的闸门看错了边。
|
|
20
|
+
*/
|
|
21
|
+
export declare function dependencyEdgeOf(direction: SortDirection): DependencyEdge;
|
|
22
|
+
/**
|
|
23
|
+
* 本相位的依赖闸门该看哪条边 —— 也就是「本相位里谁排在我前面」。
|
|
24
|
+
*
|
|
25
|
+
* DELETE 相位子先父后,父被子阻断,看 `requiredBy`;
|
|
26
|
+
* INSERT/UPDATE 相位父先子后,子被父阻断,看 `dependsOn`。
|
|
27
|
+
*
|
|
28
|
+
* 与 {@link topologicalSortForAction} 共用 {@link sortDirectionForAction},
|
|
29
|
+
* 保证「执行顺序」和「阻断关系」不可能各说各话。
|
|
30
|
+
*
|
|
31
|
+
* @param action - 本相位提交的变更类型
|
|
32
|
+
* @returns 该相位下判定阻断所依据的依赖边
|
|
33
|
+
*/
|
|
34
|
+
export declare function dependencyEdgeForAction(action: SortActionKind): DependencyEdge;
|
|
35
|
+
/**
|
|
36
|
+
* 拓扑排序
|
|
37
|
+
*
|
|
38
|
+
* @param graph - 依赖图
|
|
39
|
+
* @param direction - 排序方向
|
|
40
|
+
* - 'pull': 父实体在前(User -> Todo -> Comment)
|
|
41
|
+
* - 'push': 子实体在前(Comment -> Todo -> User)
|
|
42
|
+
* @returns 排序后的 repository 列表
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* // Pull 顺序(父在前)
|
|
47
|
+
* const pullOrder = topologicalSort(graph, 'pull');
|
|
48
|
+
* // 返回: [User, Todo, Comment]
|
|
49
|
+
*
|
|
50
|
+
* // Push 顺序(子在前)
|
|
51
|
+
* const pushOrder = topologicalSort(graph, 'push');
|
|
52
|
+
* // 返回: [Comment, Todo, User]
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function topologicalSort(graph: DependencyGraph, direction: SortDirection): RepositoryIdentifier[];
|
|
56
|
+
/**
|
|
57
|
+
* 拓扑排序(Pull 方向)
|
|
58
|
+
*
|
|
59
|
+
* 确保父实体在前,适用于 Pull 同步
|
|
60
|
+
*
|
|
61
|
+
* @param graph - 依赖图
|
|
62
|
+
* @returns 排序后的 repository 列表
|
|
63
|
+
*/
|
|
64
|
+
export declare function topologicalSortForPull(graph: DependencyGraph): RepositoryIdentifier[];
|
|
65
|
+
/**
|
|
66
|
+
* 拓扑排序(Push 方向)
|
|
67
|
+
*
|
|
68
|
+
* 确保子实体在前,适用于 Push 同步
|
|
69
|
+
*
|
|
70
|
+
* @param graph - 依赖图
|
|
71
|
+
* @returns 排序后的 repository 列表
|
|
72
|
+
*/
|
|
73
|
+
export declare function topologicalSortForPush(graph: DependencyGraph): RepositoryIdentifier[];
|
|
74
|
+
/**
|
|
75
|
+
* 变更类型:决定安全的提交顺序
|
|
76
|
+
*/
|
|
77
|
+
export type SortActionKind = 'INSERT' | 'UPDATE' | 'DELETE';
|
|
78
|
+
/**
|
|
79
|
+
* 按变更类型选排序方向
|
|
80
|
+
*
|
|
81
|
+
* 同一张依赖图,INSERT 和 DELETE 需要的顺序**正好相反**,「push 就是子→父」这个说法
|
|
82
|
+
* 只对 DELETE 成立:
|
|
83
|
+
*
|
|
84
|
+
* - `INSERT` / `UPDATE` → **父先**。子行的外键指向父行,父行不先落库就是悬空引用,FK 失败。
|
|
85
|
+
* - `DELETE` → **子先**。父行还被子行引用着,先删父同样 FK 失败。
|
|
86
|
+
*
|
|
87
|
+
* 所以一次级联推送不可能靠单一顺序扫完,必须分相位:DELETE 走一遍子→父,
|
|
88
|
+
* INSERT/UPDATE 再走一遍父→子。
|
|
89
|
+
*
|
|
90
|
+
* @param graph - 依赖图
|
|
91
|
+
* @param action - 本相位要提交的变更类型
|
|
92
|
+
* @returns 该类型下安全的提交顺序
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* topologicalSortForAction(graph, 'INSERT'); // [User, Todo, Comment]
|
|
97
|
+
* topologicalSortForAction(graph, 'DELETE'); // [Comment, Todo, User]
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export declare function topologicalSortForAction(graph: DependencyGraph, action: SortActionKind): RepositoryIdentifier[];
|
|
101
|
+
/**
|
|
102
|
+
* 过滤并排序指定的 repository 列表
|
|
103
|
+
*
|
|
104
|
+
* 从依赖图中只选择指定的 repositories,并按拓扑顺序排序
|
|
105
|
+
*
|
|
106
|
+
* @param graph - 完整依赖图
|
|
107
|
+
* @param repositories - 要排序的 repository 列表
|
|
108
|
+
* @param direction - 排序方向
|
|
109
|
+
* @returns 排序后的 repository 列表
|
|
110
|
+
*
|
|
111
|
+
* @example
|
|
112
|
+
* ```ts
|
|
113
|
+
* // 只同步 Todo 和 Comment
|
|
114
|
+
* const filtered = filterAndSort(
|
|
115
|
+
* graph,
|
|
116
|
+
* [
|
|
117
|
+
* { namespace: 'public', entity: 'Todo' },
|
|
118
|
+
* { namespace: 'public', entity: 'Comment' }
|
|
119
|
+
* ],
|
|
120
|
+
* 'pull'
|
|
121
|
+
* );
|
|
122
|
+
* // 返回: [Todo, Comment](按依赖顺序)
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
export declare function filterAndSort(graph: DependencyGraph, repositories: RepositoryIdentifier[], direction: SortDirection): RepositoryIdentifier[];
|
|
126
|
+
//# sourceMappingURL=topological-sort.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topological-sort.d.ts","sourceRoot":"","sources":["../src/topological-sort.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAEnF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,YAAY,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,aAAa,GAAG,cAAc,CAEzE;AAWD;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,cAAc,GAAG,cAAc,CAE9E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,aAAa,GAAG,oBAAoB,EAAE,CAiDxG;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,eAAe,GAAG,oBAAoB,EAAE,CAErF;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,eAAe,GAAG,oBAAoB,EAAE,CAErF;AAED;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,eAAe,EAAE,MAAM,EAAE,cAAc,GAAG,oBAAoB,EAAE,CAE/G;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,eAAe,EACtB,YAAY,EAAE,oBAAoB,EAAE,EACpC,SAAS,EAAE,aAAa,GACvB,oBAAoB,EAAE,CA8BxB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,63 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiao/rxdb-plugin-sync",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.28",
|
|
4
|
+
"description": "Push/pull synchronization, conflict resolution and offline outbox for Aiao RxDB.",
|
|
5
|
+
"homepage": "https://rxdb.aiao.io/docs/plugins",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/aiao-io/rxdb/issues"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [
|
|
10
|
+
"aiao",
|
|
11
|
+
"rxdb",
|
|
12
|
+
"sync",
|
|
13
|
+
"push",
|
|
14
|
+
"pull",
|
|
15
|
+
"conflict",
|
|
16
|
+
"offline-first",
|
|
17
|
+
"typescript"
|
|
18
|
+
],
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/aiao-io/rxdb.git",
|
|
23
|
+
"directory": "packages/rxdb-plugin-sync"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"main": "./dist/index.js",
|
|
28
|
+
"module": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
"./package.json": "./package.json",
|
|
32
|
+
".": {
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"import": "./dist/index.js",
|
|
35
|
+
"default": "./dist/index.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"src",
|
|
41
|
+
"!src/**/*.spec.*",
|
|
42
|
+
"!src/**/*.test.*",
|
|
43
|
+
"!src/**/__tests__/**",
|
|
44
|
+
"!**/*.tsbuildinfo"
|
|
45
|
+
],
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"nx": {
|
|
50
|
+
"name": "rxdb-plugin-sync",
|
|
51
|
+
"tags": [
|
|
52
|
+
"js-lib"
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"rxjs": "^7.8.2",
|
|
57
|
+
"@aiao/utils": "^0.0.28"
|
|
58
|
+
},
|
|
59
|
+
"peerDependencies": {
|
|
60
|
+
"@aiao/rxdb": "^0.0.28",
|
|
61
|
+
"@aiao/rxdb-plugin-history": "^0.0.28"
|
|
62
|
+
}
|
|
6
63
|
}
|