@aiao/rxdb-plugin-history 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 +70 -2
- package/dist/HistoryManager.d.ts +87 -0
- package/dist/HistoryManager.d.ts.map +1 -0
- package/dist/VersionManager.d.ts +243 -0
- package/dist/VersionManager.d.ts.map +1 -0
- package/dist/create-branch.d.ts +35 -0
- package/dist/create-branch.d.ts.map +1 -0
- package/dist/detached-event-error.d.ts +28 -0
- package/dist/detached-event-error.d.ts.map +1 -0
- package/dist/find-switch-branch-step.d.ts +94 -0
- package/dist/find-switch-branch-step.d.ts.map +1 -0
- package/dist/history-filters.d.ts +78 -0
- package/dist/history-filters.d.ts.map +1 -0
- package/dist/history-item-builder.d.ts +25 -0
- package/dist/history-item-builder.d.ts.map +1 -0
- package/dist/history-scope-api.d.ts +41 -0
- package/dist/history-scope-api.d.ts.map +1 -0
- package/dist/history-undo-session.types.d.ts +32 -0
- package/dist/history-undo-session.types.d.ts.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1565 -0
- package/dist/merge-branch.d.ts +22 -0
- package/dist/merge-branch.d.ts.map +1 -0
- package/dist/plugin.d.ts +58 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/pullable-count.d.ts +37 -0
- package/dist/pullable-count.d.ts.map +1 -0
- package/dist/push-inflight.d.ts +60 -0
- package/dist/push-inflight.d.ts.map +1 -0
- package/dist/redo-stack.d.ts +56 -0
- package/dist/redo-stack.d.ts.map +1 -0
- package/dist/remove-branch.d.ts +16 -0
- package/dist/remove-branch.d.ts.map +1 -0
- package/dist/restore-entity.d.ts +15 -0
- package/dist/restore-entity.d.ts.map +1 -0
- package/dist/scope-selection.d.ts +56 -0
- package/dist/scope-selection.d.ts.map +1 -0
- package/dist/switch-branch-actions.d.ts +87 -0
- package/dist/switch-branch-actions.d.ts.map +1 -0
- package/dist/sync-history-bridge.d.ts +87 -0
- package/dist/sync-history-bridge.d.ts.map +1 -0
- package/dist/undo-redo-apply.d.ts +47 -0
- package/dist/undo-redo-apply.d.ts.map +1 -0
- package/dist/version-manager.utils.d.ts +30 -0
- package/dist/version-manager.utils.d.ts.map +1 -0
- package/package.json +59 -3
- package/src/HistoryManager.ts +800 -0
- package/src/VersionManager.ts +617 -0
- package/src/create-branch.ts +178 -0
- package/src/detached-event-error.ts +43 -0
- package/src/find-switch-branch-step.ts +313 -0
- package/src/history-filters.ts +157 -0
- package/src/history-item-builder.ts +101 -0
- package/src/history-scope-api.ts +189 -0
- package/src/history-undo-session.types.ts +37 -0
- package/src/index.ts +61 -0
- package/src/merge-branch.ts +192 -0
- package/src/plugin.ts +93 -0
- package/src/pullable-count.ts +67 -0
- package/src/push-inflight.ts +91 -0
- package/src/redo-stack.ts +79 -0
- package/src/remove-branch.ts +100 -0
- package/src/restore-entity.ts +124 -0
- package/src/scope-selection.ts +133 -0
- package/src/switch-branch-actions.ts +319 -0
- package/src/sync-history-bridge.ts +131 -0
- package/src/undo-redo-apply.ts +270 -0
- package/src/version-manager.utils.ts +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Aiao Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,71 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @aiao/rxdb-plugin-history
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Implements: [US-025 核心插件化外移](https://github.com/aiao-io/rxdb/blob/main/requirements/stories/core/US-025-core-plugin-extraction.md)
|
|
4
|
+
|
|
5
|
+
历史、撤销重做与分支。装上它,`rxdb.versionManager` 才存在。
|
|
6
|
+
|
|
7
|
+
核心 `@aiao/rxdb` 保留的是**原语**:三张系统表(`RxDBBranch` / `RxDBChange` / `RxDBSync`)、变更编解码、冲突模型、同步资格判定,以及 `getCurrentBranch()`。这些东西并不专属历史子系统——变更日志触发器直接写 `branchId`,`RxDBChange.branch` 会生成真实的 `REFERENCES rxdb$rxdb_branch(id)` 外键,整条响应式增量链路都跑在 `rxdb_change` 上。搬进本包的是**消费者**:读历史、撤销重做、建/切/合/删分支。
|
|
8
|
+
|
|
9
|
+
推拉同步的调度**不在这里**,它住在 [`@aiao/rxdb-plugin-sync`](../rxdb-plugin-sync/README.md):`rxdb.syncManager.push()` / `.pull()` / `.sync()`。那个插件 `inject: ['plugin:history']`,反向没有依赖——本包不认识同步包。
|
|
10
|
+
|
|
11
|
+
## 安装
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @aiao/rxdb @aiao/rxdb-plugin-history
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 使用
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { RxDB, SyncType } from '@aiao/rxdb';
|
|
21
|
+
import { rxDBPluginHistory } from '@aiao/rxdb-plugin-history';
|
|
22
|
+
|
|
23
|
+
const rxdb = new RxDB({
|
|
24
|
+
dbName: 'notes',
|
|
25
|
+
entities: [Note],
|
|
26
|
+
sync: { type: SyncType.Full, local: { adapter: 'wa-sqlite' }, remote: { adapter: 'supabase' } }
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// 传工厂函数本身,不要调用它;必须早于 connect()——connect() 内部就会调 init()
|
|
30
|
+
rxdb.use(rxDBPluginHistory).adapter('wa-sqlite' /* … */);
|
|
31
|
+
|
|
32
|
+
await rxdb.connect('wa-sqlite');
|
|
33
|
+
|
|
34
|
+
// 撤销重做
|
|
35
|
+
await rxdb.versionManager.history().undo();
|
|
36
|
+
await rxdb.versionManager.history(Note).redo(2);
|
|
37
|
+
|
|
38
|
+
// 分支
|
|
39
|
+
await rxdb.versionManager.createBranch('feature-a');
|
|
40
|
+
await rxdb.versionManager.switchBranch('feature-a');
|
|
41
|
+
await rxdb.versionManager.mergeBranch('feature-a');
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`use()` 的时机是有意义的:`use()` 在 `init()` 之前调用则插件在 `init()` 时装上,之后调用则立即装上,而 `connect()` 内部会调 `init()`。写在 `connect()` 后面,第一批变更已经错过了历史订阅。
|
|
45
|
+
|
|
46
|
+
## 主要能力
|
|
47
|
+
|
|
48
|
+
| 分组 | 入口 |
|
|
49
|
+
| ---- | ------------------------------------------------------------------------------------------------------- |
|
|
50
|
+
| 历史 | `history(scope?)` → `histories$` / `undoHistories$` / `redoHistories$` / `count$` / `undo()` / `redo()` |
|
|
51
|
+
| 分支 | `createBranch()` / `switchBranch()` / `mergeBranch()` / `removeBranch()` |
|
|
52
|
+
| 计数 | `pushableCount$` / `pullableCount$` |
|
|
53
|
+
| 恢复 | `restoreEntity()` |
|
|
54
|
+
|
|
55
|
+
`history()` 的作用域按入参解析:无参 = 整库,传实体类 = 该仓储,传实例 = 该行。撤销一个跨作用域事务时抛 `RxDBCrossScopeTransactionError`,而不是只撤一半——半个事务比失败难查得多。
|
|
56
|
+
|
|
57
|
+
## 没装插件时
|
|
58
|
+
|
|
59
|
+
`rxdb.versionManager` **不存在**(读到 `undefined`),核心不给一个什么都不做的空壳。这对下游是可见的契约而非退化路径:
|
|
60
|
+
|
|
61
|
+
- **DevTools**:`DevToolsRxDB.versionManager` 是可选成员,连接器据实报「分支能力不可用」,不会把它谎报成「一个分支都没有」。
|
|
62
|
+
- **同步状态枢纽**:`SyncStateHub` 留在核心,但可推送计数由本插件经 `bindPushableCount()` 接上。没装插件,那个读数就是无人维护——这正是实情。待拉数归 `@aiao/rxdb-plugin-sync`:它接住远端适配器发出的 `requestPullableRefresh()`。
|
|
63
|
+
- **类型**:`versionManager` 由本包的 `declare module '@aiao/rxdb'` 声明。只消费、不负责安装的模块(框架组件、共享 UI)应写 `import type {} from '@aiao/rxdb-plugin-history';`——它把类型声明拉进编译单元,同时在 emit 时整句擦除,不产生运行时依赖。
|
|
64
|
+
|
|
65
|
+
## 连接纪元
|
|
66
|
+
|
|
67
|
+
插件声明 `lifecycle: 'scoped'`,三处宿主改动全部登记在 `install(scope)` 收到的作用域上,`disconnectAll()` 时逆序释放,宿主不调用 `destroy()`:`VersionManager` 实例本身(连同 `destroy()`)、`rxdb.versionManager` 槽位、`syncState.bindPushableCount()` 订阅。重新 `connect()` 装的是一个全新的管理器,而不是复活上一纪元那个——后者指向的事件总线已经拆了。
|
|
68
|
+
|
|
69
|
+
本包**不声明 `inject`**,所以它在 `init()` 里就装完;`@aiao/rxdb-plugin-sync` 声明了 `inject: ['plugin:history']`,要等本包装好才轮到它,那个槽位得 `await connect()` 之后才在。
|
|
70
|
+
|
|
71
|
+
插件**不声明 `inject`**:`VersionManager.init()` 只挂监听与订阅,一条适配器读写都不发。声明 `adapter:local` 会把安装推到引导链之后,而分支流必须在第一条 `rxdb_change` 事件到达之前就订阅上。
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { EntityType, HistoryItem, HistoryScope, HistoryScopeAPI, RxDB } from '@aiao/rxdb';
|
|
2
|
+
import { Observable, Subject } from 'rxjs';
|
|
3
|
+
import { UndoSessionEvent } from './history-undo-session.types.js';
|
|
4
|
+
export { filterHistoriesByScope, filterUndoableHistories, getScopeKey } from './history-filters.js';
|
|
5
|
+
export { generateHistoryDescription } from './history-item-builder.js';
|
|
6
|
+
/**
|
|
7
|
+
* 历史记录管理器:变更历史、内存 redo 栈、多作用域 undo/redo API。
|
|
8
|
+
*
|
|
9
|
+
* 数据流:`RxDBChange[] → #all_changes$ → histories$ → undoHistories$ / redoHistories$`
|
|
10
|
+
*/
|
|
11
|
+
export declare class HistoryManager {
|
|
12
|
+
#private;
|
|
13
|
+
private rxdb;
|
|
14
|
+
private isUndoRedoInProgress;
|
|
15
|
+
private isInvalidatingRedo;
|
|
16
|
+
/** 进行中的 pull/push 深度(可重入,避免并发同步提前清标志) */
|
|
17
|
+
private syncDepth;
|
|
18
|
+
private readonly redoStack;
|
|
19
|
+
private history_cache;
|
|
20
|
+
private history_ref_counts;
|
|
21
|
+
histories$: Observable<HistoryItem[]>;
|
|
22
|
+
undoHistories$: Observable<HistoryItem[]>;
|
|
23
|
+
redoHistories$: Observable<HistoryItem[]>;
|
|
24
|
+
undoCount$: Observable<number>;
|
|
25
|
+
redoCount$: Observable<number>;
|
|
26
|
+
/** 内部错误流:派生流降级的同时把错误推给订阅者 */
|
|
27
|
+
readonly errors$: Subject<Error>;
|
|
28
|
+
pushableCount$: Observable<number>;
|
|
29
|
+
pullableCount$: Observable<number>;
|
|
30
|
+
count$: Observable<number>;
|
|
31
|
+
/**
|
|
32
|
+
* 当前撤销 session generation。
|
|
33
|
+
*
|
|
34
|
+
* @internal 供 VersionManager 在事务开始时捕获事件所属 session
|
|
35
|
+
*/
|
|
36
|
+
get undoSessionGeneration(): number;
|
|
37
|
+
constructor(rxdb: RxDB);
|
|
38
|
+
destroy(): void;
|
|
39
|
+
/** 增加远程待 pull 计数 */
|
|
40
|
+
incrementPullableCount(count: number): void;
|
|
41
|
+
/** session 重置时清零 pullable;pull 结束结算走 {@link settlePullableCount} */
|
|
42
|
+
resetPullableCount(): void;
|
|
43
|
+
/** pull 开始前签发结算令牌,必须在真正发起 pull 之前取 */
|
|
44
|
+
beginPullableSettlement(): number;
|
|
45
|
+
/** 用远端水位线校准待拉计数 */
|
|
46
|
+
reconcilePullableCount(token: number, count: number): void;
|
|
47
|
+
/** 按一次 pull 的实际覆盖范围结算待拉计数 */
|
|
48
|
+
settlePullableCount(token: number, settlement: {
|
|
49
|
+
complete: boolean;
|
|
50
|
+
pulled: number;
|
|
51
|
+
}): void;
|
|
52
|
+
/** 推入 redo 栈(新项在前,超容量丢尾) */
|
|
53
|
+
pushToRedoStack(items: HistoryItem[]): void;
|
|
54
|
+
/** 按身份从 redo 栈移除已应用项(作用域 redo 未必在栈顶) */
|
|
55
|
+
removeFromRedoStack(items: HistoryItem[]): HistoryItem[];
|
|
56
|
+
/** 清空 redo 栈 */
|
|
57
|
+
clearRedoStack(): void;
|
|
58
|
+
/** switchBranch 提交后同步切 undo session,避免 await 中间引用比对失配 */
|
|
59
|
+
setUndoBranch(branchId: string): void;
|
|
60
|
+
/** 清空当前分支 undo/redo;连接级重置用 {@link clearAllUndoHistory} */
|
|
61
|
+
clearUndoHistory(): void;
|
|
62
|
+
/** 清空所有分支 undo/redo,并推进 {@link #undoSessionFloor} */
|
|
63
|
+
clearAllUndoHistory(): void;
|
|
64
|
+
/** 用属于当前 clear session 的本地写入事件恢复 undo */
|
|
65
|
+
resetSyncCleared(changeIds?: readonly number[], event?: UndoSessionEvent): void;
|
|
66
|
+
/** 正在执行 undo/redo 或同步 */
|
|
67
|
+
isExecutingUndoRedo(): boolean;
|
|
68
|
+
/** 在可重入同步上下文中执行:期间变更不影响 undo/redo 栈 */
|
|
69
|
+
syncing<T>(fn: () => Promise<T>): Promise<T>;
|
|
70
|
+
/**
|
|
71
|
+
* 使 redo 栈失效。全部 trigger id ≤ {@link #redoInvalidationFloor} 视为迟到通知,跳过。
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
* 这里**不查** `isUndoRedoInProgress` / `isInvalidatingRedo`:undo、redo 与本方法三个入口
|
|
75
|
+
* 全部排进 {@link HistoryManager.#runSerialized},两个标志又只在同一个序列化任务内部置起
|
|
76
|
+
* 再复位,因此轮到本任务时它们必然已复位——查了也是一条走不到的分支。下面那句
|
|
77
|
+
* `isInvalidatingRedo = true` 留着是给 {@link HistoryManager.isExecutingUndoRedo} 读的,
|
|
78
|
+
* 真正生效的守卫在调用方 `VersionManager` 的 `if (!historyManager.isExecutingUndoRedo())`,
|
|
79
|
+
* 它连 `syncDepth` 一起看,覆盖比这里严。
|
|
80
|
+
*
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
invalidateRedoStack(triggerChangeIds?: readonly number[]): Promise<void>;
|
|
84
|
+
/** 创建(或取出缓存的)作用域历史 API */
|
|
85
|
+
history<T extends EntityType>(options?: T | InstanceType<T> | HistoryScope): HistoryScopeAPI;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=HistoryManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HistoryManager.d.ts","sourceRoot":"","sources":["../src/HistoryManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { EntityType, HistoryScopeAPI, MergeBranchOptions, MergeBranchResult, RestoreEntityOptions, RxDB, RxDBBranch, RxDBBranchSwitchPreconditions } from '@aiao/rxdb';
|
|
2
|
+
import { PushInFlightRegistry } from './push-inflight.js';
|
|
3
|
+
import { SyncHistoryBridge } from './sync-history-bridge.js';
|
|
4
|
+
/**
|
|
5
|
+
* 版本管理器
|
|
6
|
+
*
|
|
7
|
+
* 负责管理数据库的分支、撤销/重做与版本历史:
|
|
8
|
+
* - 分支管理(创建、删除、切换、合并)
|
|
9
|
+
* - 撤销/重做操作(数据库级别)
|
|
10
|
+
* - Redo 栈的自动失效(当有新操作时)
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
* 推拉同步**不在**这里。US-025 阶段 D 之后它住在 `@aiao/rxdb-plugin-sync` 的
|
|
14
|
+
* `SyncManager` 上,两边只经 {@link VersionManager.syncBridge} 这一张窄接口相遇。
|
|
15
|
+
*/
|
|
16
|
+
export declare class VersionManager {
|
|
17
|
+
#private;
|
|
18
|
+
readonly rxdb: RxDB;
|
|
19
|
+
/**
|
|
20
|
+
* 撤销/重做辅助类
|
|
21
|
+
* 管理历史记录和内存 redo 栈
|
|
22
|
+
*/
|
|
23
|
+
private historyManager;
|
|
24
|
+
/**
|
|
25
|
+
* 「哪些变更此刻正在飞往远端」的登记处。
|
|
26
|
+
*
|
|
27
|
+
* @remarks
|
|
28
|
+
* push 与 undo 唯一的会合点。push 在远端往返之前认领区间,undo 把认领区间当成已推 ——
|
|
29
|
+
* 没有它,往返窗口内的一次撤销会造成本地与远端永久分叉,见 {@link PushInFlightRegistry}。
|
|
30
|
+
*
|
|
31
|
+
* 挂在 `VersionManager` 上是因为两边都只经它相遇:`pushRepository(vm, …)` 直接拿到它,
|
|
32
|
+
* `HistoryManager` 经 `rxdb.versionManager` 拿到它。生命周期跟随实例,不跨实例共享。
|
|
33
|
+
*
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
readonly pushInFlight: PushInFlightRegistry;
|
|
37
|
+
/**
|
|
38
|
+
* 交给同步插件的那一小块历史能力。
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* 传闭包而不是 `this.historyManager`:`init()` 会在断连重连后重建管理器,
|
|
42
|
+
* 桥必须每次现取,见 {@link createSyncHistoryBridge}。
|
|
43
|
+
*
|
|
44
|
+
* @internal
|
|
45
|
+
*/
|
|
46
|
+
readonly syncBridge: SyncHistoryBridge;
|
|
47
|
+
/**
|
|
48
|
+
* 可 push 的变更数量流
|
|
49
|
+
*
|
|
50
|
+
* 实时追踪本地未推送的有效变更数量:
|
|
51
|
+
* - 排除已撤销的变更(revertChangeId != null)
|
|
52
|
+
* - 排除从远程 pull 来的变更(remoteId != null)
|
|
53
|
+
*/
|
|
54
|
+
get pushableCount$(): import('rxjs').Observable<number>;
|
|
55
|
+
/**
|
|
56
|
+
* 远程待 pull 的变更数量流
|
|
57
|
+
*
|
|
58
|
+
* 通过监听远程事件(INSERT/UPDATE/DELETE)累计:
|
|
59
|
+
* - 收到远程变更事件时计数+1
|
|
60
|
+
* - pull 完成后计数重置为 0
|
|
61
|
+
*
|
|
62
|
+
* 用于 UI 显示"有 N 条远程更新可拉取"
|
|
63
|
+
*/
|
|
64
|
+
get pullableCount$(): import('rxjs').Observable<number>;
|
|
65
|
+
/**
|
|
66
|
+
* @param rxdb - 宿主实例
|
|
67
|
+
*
|
|
68
|
+
* @remarks
|
|
69
|
+
* 构造即建 {@link HistoryManager},而它在自己的构造器里就订阅了活跃分支流 ——
|
|
70
|
+
* 所以「造出来」本身已经是一次资源获取,调用方必须把 {@link VersionManager.destroy}
|
|
71
|
+
* 登记在作用域上,哪怕后面的 {@link VersionManager.init} 还没跑。
|
|
72
|
+
*/
|
|
73
|
+
constructor(rxdb: RxDB);
|
|
74
|
+
/**
|
|
75
|
+
* 挂上事务与本地写入的事件监听,开始记历史。
|
|
76
|
+
*
|
|
77
|
+
* @remarks
|
|
78
|
+
* 与 {@link VersionManager.destroy} 成对,可重入:上一轮 `destroy()` 过的
|
|
79
|
+
* `HistoryManager` 已经拆掉了订阅,这里重建一个而不是复用 —— 复用等于把新纪元的
|
|
80
|
+
* 变更喂给一条已 complete 的流。
|
|
81
|
+
*
|
|
82
|
+
* 不发任何适配器读写,也不会把实例连起来(分支流等 `connected$` 为真才查),因此可以
|
|
83
|
+
* (也必须)早于引导链跑:`HistoryManager` 的分支流要赶在第一条 `rxdb_change` 事件之前
|
|
84
|
+
* 订阅上,装晚了那一批变更就不进历史。
|
|
85
|
+
*/
|
|
86
|
+
init(): void;
|
|
87
|
+
/**
|
|
88
|
+
* 摘掉全部事件监听与订阅,并销毁 {@link HistoryManager}。
|
|
89
|
+
*
|
|
90
|
+
* @remarks
|
|
91
|
+
* 幂等。事务深度与代次一并清零:拆卸可能发生在事务中途,留着计数会让下一个纪元
|
|
92
|
+
* 以为自己开局就在一笔未结的事务里。
|
|
93
|
+
*/
|
|
94
|
+
destroy(): void;
|
|
95
|
+
/**
|
|
96
|
+
* 作废本连接积累的历史上下文:清空全部分支的 undo 会话与待拉计数。
|
|
97
|
+
*
|
|
98
|
+
* @remarks
|
|
99
|
+
* 供切库 / 重连这类「本地数据整体换了一份」的场景调用。清的是**全部**分支而不只是
|
|
100
|
+
* 当前分支 —— 换掉的是整个数据源,其它分支上那些 undo 条目指向的行同样已经不在了。
|
|
101
|
+
*/
|
|
102
|
+
resetSessionState(): void;
|
|
103
|
+
/**
|
|
104
|
+
* 创建新分支
|
|
105
|
+
* @param branchId 分支 id
|
|
106
|
+
* @param fromChangeId 从哪个 changeId 创建新分支
|
|
107
|
+
*/
|
|
108
|
+
createBranch(branchId: string, fromChangeId?: number): Promise<InstanceType<typeof RxDBBranch>>;
|
|
109
|
+
/**
|
|
110
|
+
* 删除分支
|
|
111
|
+
* @param branchId 分支 id
|
|
112
|
+
*/
|
|
113
|
+
removeBranch(branchId: string): Promise<void>;
|
|
114
|
+
/**
|
|
115
|
+
* 切换到指定分支
|
|
116
|
+
*
|
|
117
|
+
* @param branchId - 目标分支 ID
|
|
118
|
+
* @param preconditions - 【可选】切换前要成立的条件;不传时行为与以往逐字节一致
|
|
119
|
+
*
|
|
120
|
+
* @remarks
|
|
121
|
+
* 切换分支后会自动清空 redo 栈,因为 redo 历史在新分支中不再有效。
|
|
122
|
+
* 如果目标分支与当前分支相同,则直接返回,避免不必要的操作。
|
|
123
|
+
*
|
|
124
|
+
* 第二形参是**纯扩展**:既有调用点一个都不用改,不传即不表态。做成默认开启的话,
|
|
125
|
+
* `switchBranch(id)` 会在任何有未提交改动的库上开始抛错——而历史子系统自己就在调它
|
|
126
|
+
* (undo/redo 回放、redo 失效),那些路径上工作树恒非空,默认开启等于让 undo 在有改动时不可用。
|
|
127
|
+
*
|
|
128
|
+
* 条件由**能力插件**校验,本方法一个字段都不读:判据是
|
|
129
|
+
* `@aiao/rxdb-plugin-working-tree` 贡献的那几张表,这里既不认识也不该认识它们。
|
|
130
|
+
* 反方向(本包 import 那个插件)是条依赖环,nx 的图插件会把 `run-many` 当场拒掉。
|
|
131
|
+
*/
|
|
132
|
+
switchBranch(branchId: string, preconditions?: RxDBBranchSwitchPreconditions): Promise<void>;
|
|
133
|
+
/**
|
|
134
|
+
* 合并分支
|
|
135
|
+
*
|
|
136
|
+
* 将源分支的变更合并到当前激活分支(目标分支)。
|
|
137
|
+
*
|
|
138
|
+
* @param sourceBranchId - 源分支 ID
|
|
139
|
+
* @param options - 合并选项
|
|
140
|
+
* @returns 合并结果
|
|
141
|
+
*
|
|
142
|
+
* @remarks
|
|
143
|
+
* 支持两种策略:
|
|
144
|
+
* - `squash`(默认):将源分支所有变更压缩为最小操作集后一次性应用,目标分支只产生一组变更记录
|
|
145
|
+
* - `normal`:逐条应用源分支变更,每条变更在目标分支产生独立的变更记录(保留历史细节)
|
|
146
|
+
*
|
|
147
|
+
* 合并后会清空 undo/redo 历史,因为合并操作不可逆。
|
|
148
|
+
* 可选通过 `deleteSource: true` 在合并后删除源分支。
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* // 压缩合并(默认)
|
|
153
|
+
* const result = await rxdb.versionManager.mergeBranch('feature-x');
|
|
154
|
+
* console.log(`Merged ${result.merged} changes`);
|
|
155
|
+
*
|
|
156
|
+
* // 普通合并
|
|
157
|
+
* const result = await rxdb.versionManager.mergeBranch('feature-x', {
|
|
158
|
+
* strategy: 'normal'
|
|
159
|
+
* });
|
|
160
|
+
*
|
|
161
|
+
* // 合并后删除源分支
|
|
162
|
+
* const result = await rxdb.versionManager.mergeBranch('feature-x', {
|
|
163
|
+
* deleteSource: true
|
|
164
|
+
* });
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
mergeBranch(sourceBranchId: string, options?: MergeBranchOptions): Promise<MergeBranchResult>;
|
|
168
|
+
/**
|
|
169
|
+
* 获取特定作用域的历史记录 API
|
|
170
|
+
*
|
|
171
|
+
* @param options - 作用域选项:
|
|
172
|
+
* - 不传参数 → database 作用域(整个数据库)
|
|
173
|
+
* - EntityType 类 → repository 作用域(该实体的所有记录)
|
|
174
|
+
* - 实体实例 → entity 作用域(该实例的历史)
|
|
175
|
+
* @returns 统一的历史记录 API 接口
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* ```ts
|
|
179
|
+
* // 数据库级别
|
|
180
|
+
* const dbHistory = versionManager.history();
|
|
181
|
+
*
|
|
182
|
+
* // 仓库级别(所有 User 记录)
|
|
183
|
+
* const userHistory = versionManager.history(User);
|
|
184
|
+
*
|
|
185
|
+
* // 实体级别(单个用户)
|
|
186
|
+
* const entityHistory = versionManager.history(userInstance);
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
history<T extends EntityType>(options?: T | InstanceType<T>): HistoryScopeAPI;
|
|
190
|
+
/**
|
|
191
|
+
* 恢复被删除的实体
|
|
192
|
+
*
|
|
193
|
+
* 根据 RxDBChange 记录中的 inversePatch 重新插入实体,
|
|
194
|
+
* 恢复操作本身会生成新的 RxDBChange 记录(可被 push 到远程)。
|
|
195
|
+
*
|
|
196
|
+
* @param entity - 被删除的实体实例(需要包含 metadata 信息)
|
|
197
|
+
* @param options - 恢复选项,包含 changeId(DELETE 类型的 RxDBChange 记录 ID)
|
|
198
|
+
* @returns 恢复后的实体实例
|
|
199
|
+
*/
|
|
200
|
+
restoreEntity<T extends EntityType>(entity: InstanceType<T>, options: RestoreEntityOptions): Promise<InstanceType<T>>;
|
|
201
|
+
/**
|
|
202
|
+
* 取本地适配器上的系统表仓库。
|
|
203
|
+
*
|
|
204
|
+
* @returns `branchRepository` / `changeRepository` 与它们所属的本地适配器
|
|
205
|
+
*
|
|
206
|
+
* @remarks
|
|
207
|
+
* 每次都经 `localAdapter$` 重新解析,不缓存:适配器随连接纪元换,缓下来的那一份
|
|
208
|
+
* 会在重连之后指向已拆的旧实例。
|
|
209
|
+
*/
|
|
210
|
+
getLocalRepositories(): Promise<{
|
|
211
|
+
branchRepository: import('@aiao/rxdb').LocalRxDBBranchRepository;
|
|
212
|
+
changeRepository: import('@aiao/rxdb').LocalRxDBChangeRepository;
|
|
213
|
+
adapter: import('@aiao/rxdb').LocalRxDBAdapter;
|
|
214
|
+
}>;
|
|
215
|
+
/**
|
|
216
|
+
* 取远端适配器上的系统表仓库。
|
|
217
|
+
*
|
|
218
|
+
* @returns `branchRepository` / `changeRepository` 与它们所属的远端适配器
|
|
219
|
+
*
|
|
220
|
+
* @remarks
|
|
221
|
+
* 未配置远端时 `remoteAdapter$` 不发值,调用会一直挂着 —— 这是有意的:同步路径
|
|
222
|
+
* 本来就只在配了远端时才走,返回一个空壳只会把「没配远端」推迟到更深的地方才报。
|
|
223
|
+
*/
|
|
224
|
+
getRemoteRepositories(): Promise<{
|
|
225
|
+
branchRepository: import('@aiao/rxdb').RemoteRxDBBranchRepository;
|
|
226
|
+
changeRepository: import('@aiao/rxdb').RemoteRxDBChangeRepository;
|
|
227
|
+
adapter: import('@aiao/rxdb').RemoteRxDBAdapter;
|
|
228
|
+
}>;
|
|
229
|
+
/**
|
|
230
|
+
* 取当前分支;没有激活分支时激活(或新建)`main`。
|
|
231
|
+
*
|
|
232
|
+
* @remarks
|
|
233
|
+
* 分两段是有意的:
|
|
234
|
+
*
|
|
235
|
+
* - **热路径**(已有激活分支)不开事务。同步插件的远端事件链路里每条事件都要调它
|
|
236
|
+
* (`sync-listeners` 的 `filterByBranch`),把整段包进事务能修好并发,
|
|
237
|
+
* 但会让每次读都去抢并发度 1 的写队列槽位。
|
|
238
|
+
* - **冷路径**(查不到激活分支)才开事务,并在事务内**重做一遍检查**(双重检查)。
|
|
239
|
+
* 否则两个并发调用会双双走到 `create`,第二个撞主键报错。
|
|
240
|
+
*/
|
|
241
|
+
getCurrentBranch(): Promise<RxDBBranch>;
|
|
242
|
+
}
|
|
243
|
+
//# sourceMappingURL=VersionManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VersionManager.d.ts","sourceRoot":"","sources":["../src/VersionManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,UAAU,EAIV,eAAe,EAIf,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,IAAI,EACJ,UAAU,EAWV,KAAK,6BAA6B,EAEnC,MAAM,YAAY,CAAC;AAKpB,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAI1D,OAAO,EAA2B,KAAK,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE3F;;;;;;;;;;;GAWG;AAEH,qBAAa,cAAc;;aAsEG,IAAI,EAAE,IAAI;IA/DtC;;;OAGG;IACH,OAAO,CAAC,cAAc,CAAiB;IAEvC;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,YAAY,uBAA8B;IAEnD;;;;;;;;OAQG;IACH,QAAQ,CAAC,UAAU,EAAE,iBAAiB,CAAyE;IAE/G;;;;;;OAMG;IACH,IAAI,cAAc,sCAEjB;IAED;;;;;;;;OAQG;IACH,IAAI,cAAc,sCAEjB;IAED;;;;;;;OAOG;gBACyB,IAAI,EAAE,IAAI;IAItC;;;;;;;;;;;OAWG;IACH,IAAI;IAwEJ;;;;;;OAMG;IACH,OAAO;IAaP;;;;;;OAMG;IACH,iBAAiB;IAMjB;;;;OAIG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,OAAO,UAAU,CAAC,CAAC;IAIrG;;;OAGG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInD;;;;;;;;;;;;;;;;;OAiBG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC;IA6ElG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACG,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAwBnG;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,CAAC,SAAS,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,eAAe;IAI7E;;;;;;;;;OASG;IACG,aAAa,CAAC,CAAC,SAAS,UAAU,EACtC,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EACvB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAI3B;;;;;;;;OAQG;IACG,oBAAoB;;;;;IAI1B;;;;;;;;OAQG;IACG,qBAAqB;;;;;IAI3B;;;;;;;;;;;OAWG;IACG,gBAAgB;CA0HvB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { LocalRxDBChangeRepository, RxDBBranch, RxDBChange } from '@aiao/rxdb';
|
|
2
|
+
import { VersionManager } from './VersionManager.js';
|
|
3
|
+
/**
|
|
4
|
+
* 创建一个新分支
|
|
5
|
+
* @param version
|
|
6
|
+
* @param branchId
|
|
7
|
+
* @param fromChangeId
|
|
8
|
+
* @returns
|
|
9
|
+
*
|
|
10
|
+
* @remarks
|
|
11
|
+
* 「查重 → 解析分叉点 → 写入」在一个事务窗口内完成。只把 `remove_branch`
|
|
12
|
+
* 包进事务是不够的:一个在删除之前就解析完父分支的 `create_branch`,仍会在删除之后
|
|
13
|
+
* 把子分支写进去,留下孤儿。两侧同处一个写队列窗口,「只能有一方成功」才成立。
|
|
14
|
+
*
|
|
15
|
+
* 远端 `branchExists` 那一趟**留在事务外**:它是网络往返,放进事务会让并发度 1 的
|
|
16
|
+
* 写队列被一次 RTT 堵住。它本来也只是尽力而为的预检,真正的互斥由本地主键约束兜底。
|
|
17
|
+
*
|
|
18
|
+
* **一条分支未必只有一行。** 贡献系统能力的插件可以在同一个事务里追写自己那几行
|
|
19
|
+
* ({@link RxDBSystemContribution.writeBranchRows})——装了 `@aiao/rxdb-plugin-working-tree`
|
|
20
|
+
* 时是 `CommitBranchRef` 与 `WorkingTreeState` 两行。同属一个事务,正是为了不让
|
|
21
|
+
* 「建了分支却没有对应视图」这种半成品状态存在:那样一条分支与一条正常的老分支
|
|
22
|
+
* 在形状上分辨不出来,只会在下一次用到它时抛一句读不出主语的错。
|
|
23
|
+
*/
|
|
24
|
+
export declare const create_branch: (version: VersionManager, branchId: string, fromChangeId?: number) => Promise<RxDBBranch>;
|
|
25
|
+
/**
|
|
26
|
+
* 获取分支最新一笔可作为分叉点的变更记录
|
|
27
|
+
*
|
|
28
|
+
* @param changeRepository - 变更仓库。由调用方决定它属于哪个事务 ——
|
|
29
|
+
* `create_branch` 传的是事务内的那一份,不能在这里自己去 `getLocalRepositories()`。
|
|
30
|
+
* @param currentBranchId - 分支 ID;不传则按「当前激活分支」查
|
|
31
|
+
*
|
|
32
|
+
* 独立导出而非内联,是为了被 `__tests__/version/create-branch.spec.ts` 单独测试。
|
|
33
|
+
*/
|
|
34
|
+
export declare const get_current_branch_last_change: (changeRepository: LocalRxDBChangeRepository, currentBranchId?: string) => Promise<RxDBChange>;
|
|
35
|
+
//# sourceMappingURL=create-branch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-branch.d.ts","sourceRoot":"","sources":["../src/create-branch.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,yBAAyB,EAE9B,UAAU,EACV,UAAU,EAEX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,aAAa,GAAU,SAAS,cAAc,EAAE,UAAU,MAAM,EAAE,eAAe,MAAM,wBA+GnG,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,8BAA8B,GACzC,kBAAkB,yBAAyB,EAC3C,kBAAkB,MAAM,wBAqBzB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview 游离事件任务的错误判据
|
|
3
|
+
*
|
|
4
|
+
* 事件监听器里发起的异步任务没有调用方接得住错误({@link VersionManager} 的
|
|
5
|
+
* `#runDetachedEventTask`、{@link setupSyncListeners} 的远端事件处理器都是即发即忘)。
|
|
6
|
+
* 连接正在拆除时这些任务必然撞上一批「适配器已经走了」的错误,它们是拆除过程的正常噪音,
|
|
7
|
+
* 不该打进控制台当故障看。
|
|
8
|
+
*
|
|
9
|
+
* 判据留在历史插件、由同步插件经 `@aiao/rxdb-plugin-history` 引用:同步插件本就
|
|
10
|
+
* `inject: ['plugin:history']`,这条 import 不新增依赖边;放进核心则要为一个纯谓词
|
|
11
|
+
* 再撑大一圈公共表面,与 US-025「核心只留原语」的方向相反。
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* 判断游离事件任务的错误是否可忽略
|
|
15
|
+
*
|
|
16
|
+
* @param error - 任务抛出的错误
|
|
17
|
+
* @returns 属于连接拆除噪音时返回 `true`
|
|
18
|
+
*
|
|
19
|
+
* @remarks
|
|
20
|
+
* 包括:
|
|
21
|
+
* - errno 44 = ENODEV(Emscripten IDBFS 连接关闭)
|
|
22
|
+
* - name === 'AbortError'
|
|
23
|
+
* - adapter shutdown 错误(统一字符串匹配模式)
|
|
24
|
+
*
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare const isIgnorableDetachedVersionEventError: (error: unknown) => boolean;
|
|
28
|
+
//# sourceMappingURL=detached-event-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detached-event-error.d.ts","sourceRoot":"","sources":["../src/detached-event-error.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oCAAoC,GAAI,OAAO,OAAO,KAAG,OAarE,CAAC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { RxDBBranch } from '@aiao/rxdb';
|
|
2
|
+
/**
|
|
3
|
+
* 分支切换步骤
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
*/
|
|
7
|
+
export interface SwitchBranchStep {
|
|
8
|
+
/**
|
|
9
|
+
* 分支对象
|
|
10
|
+
*/
|
|
11
|
+
branch: RxDBBranch;
|
|
12
|
+
/**
|
|
13
|
+
* 开始变更 ID
|
|
14
|
+
*/
|
|
15
|
+
fromChangeId: number;
|
|
16
|
+
/**
|
|
17
|
+
* 目标变更 ID
|
|
18
|
+
*/
|
|
19
|
+
toChangeId: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 查找分支切换路径的参数
|
|
23
|
+
*/
|
|
24
|
+
export interface FindBranchPathOptions {
|
|
25
|
+
/**
|
|
26
|
+
* 所需分支列表
|
|
27
|
+
*/
|
|
28
|
+
branches: RxDBBranch[];
|
|
29
|
+
/**
|
|
30
|
+
* 当前分支
|
|
31
|
+
*/
|
|
32
|
+
currentBranch: RxDBBranch;
|
|
33
|
+
/**
|
|
34
|
+
* 当前分支的变更 ID
|
|
35
|
+
*/
|
|
36
|
+
currentChangeId: number | null;
|
|
37
|
+
/**
|
|
38
|
+
* 目标分支
|
|
39
|
+
*/
|
|
40
|
+
nextBranch: RxDBBranch;
|
|
41
|
+
/**
|
|
42
|
+
* 目标分支的变更 ID
|
|
43
|
+
*/
|
|
44
|
+
nextChangeId: number | null;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 沿 `parentId` 从一条分支走到它所在树的根,返回途经的全部分支(含自己,根在最后)。
|
|
48
|
+
*
|
|
49
|
+
* 断链(`parentId` 指不到分支)与成环都是**持久化完整性错误**:调用方传进来的分支集合
|
|
50
|
+
* 是全量无过滤查询的结果,不存在「父分支被过滤掉了」这种正常情况。
|
|
51
|
+
* 曾经这两种情况都是 `break` —— 相当于把坏数据当成「已经到根」,继续算出一条通往
|
|
52
|
+
* 并不存在的根的完整 action 序列,调用方照单全收地写库,半条路径被应用而没有任何报错。
|
|
53
|
+
* 切分支失败远好过静默切错,因此这里必须终止且不产生任何 action。
|
|
54
|
+
*
|
|
55
|
+
* 从 {@link find_switch_branch_step} 的闭包里提出来成为模块级导出,是因为
|
|
56
|
+
* 「父链自不自洽」这一问的答案必须**全局只有一个**:`enable-migration.ts` 的
|
|
57
|
+
* 「分支可否完整物化」判定用的就是它(research.md R11)。留在闭包里够不着,
|
|
58
|
+
* 调用方只能另写一套遍历,于是迁移期与运行期会对同一个库给出两种答案。
|
|
59
|
+
*
|
|
60
|
+
* 它**够不到** {@link find_switch_branch_step} 的两处提前返回:变更 id 相同(含两边
|
|
61
|
+
* 都没有变更、都落在根上)时那个函数直接返回空步骤,根本走不到这里。所以要检查父链
|
|
62
|
+
* 完整性的调用方必须**自己**调它一次,不能指望 `find_switch_branch_step` 顺带检查。
|
|
63
|
+
*
|
|
64
|
+
* @param branch - 起点分支
|
|
65
|
+
* @param branchMap - 分支 id → 分支;必须是全量集合
|
|
66
|
+
* @returns 从 `branch` 到根的路径,`branch` 在第 0 位
|
|
67
|
+
* @throws {@link RxDBError} 父链成环或指向不存在的分支时
|
|
68
|
+
*
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
export declare const find_branch_path_to_root: (branch: RxDBBranch, branchMap: ReadonlyMap<string, RxDBBranch>) => RxDBBranch[];
|
|
72
|
+
/**
|
|
73
|
+
* 算出树上两个节点之间的切换路径
|
|
74
|
+
*
|
|
75
|
+
* @param options - 起点分支、目标分支、两侧当前变更 id,以及**全量**分支集合
|
|
76
|
+
* @returns 按执行顺序排好的步骤;两侧停在同一个变更 id 时为空数组
|
|
77
|
+
* @throws {@link RxDBError} 父链成环或指向不存在的分支时(经 {@link find_branch_path_to_root})
|
|
78
|
+
*
|
|
79
|
+
* @remarks
|
|
80
|
+
* 规则四条:
|
|
81
|
+
*
|
|
82
|
+
* 1. 两个节点有共同祖先时,路径是「当前节点 → 共同祖先 → 目标节点」
|
|
83
|
+
* 2. 没有共同祖先时,路径是「当前节点 → 根 → 目标节点」
|
|
84
|
+
* 3. 路径里每个节点都要算出自己那一段的变更区间,即 `fromChangeId → toChangeId`
|
|
85
|
+
* 4. `changeId` 在每条分支上都递增,所以**逆向还原**的那些步骤 `fromChangeId > toChangeId`,
|
|
86
|
+
* 正向应用的则相反——方向由这两个数的大小关系表达,步骤上没有第二个方向字段
|
|
87
|
+
*
|
|
88
|
+
* 有两处**提前返回**会跳过父链遍历——变更 id 相同时返回空步骤,同分支不同变更 id 时返回
|
|
89
|
+
* 单步——因此本函数不是父链完整性的检查点,理由见 {@link find_branch_path_to_root}。
|
|
90
|
+
*
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
export declare const find_switch_branch_step: (options: FindBranchPathOptions) => SwitchBranchStep[];
|
|
94
|
+
//# sourceMappingURL=find-switch-branch-step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"find-switch-branch-step.d.ts","sourceRoot":"","sources":["../src/find-switch-branch-step.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,YAAY,CAAC;AACnD;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,MAAM,EAAE,UAAU,CAAC;IACnB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,QAAQ,EAAE,UAAU,EAAE,CAAC;IAEvB;;OAEG;IACH,aAAa,EAAE,UAAU,CAAC;IAE1B;;OAEG;IACH,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B;;OAEG;IACH,UAAU,EAAE,UAAU,CAAC;IAEvB;;OAEG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAiBD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,wBAAwB,GACnC,QAAQ,UAAU,EAClB,WAAW,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,KACzC,UAAU,EAqBZ,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB,GAAI,SAAS,qBAAqB,KAAG,gBAAgB,EA6KxF,CAAC"}
|