@aiao/rxdb-plugin-history 0.0.0-stage → 0.0.26

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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -2
  3. package/dist/HistoryManager.d.ts +79 -0
  4. package/dist/HistoryManager.d.ts.map +1 -0
  5. package/dist/VersionManager.d.ts +233 -0
  6. package/dist/VersionManager.d.ts.map +1 -0
  7. package/dist/create-branch.d.ts +29 -0
  8. package/dist/create-branch.d.ts.map +1 -0
  9. package/dist/detached-event-error.d.ts +28 -0
  10. package/dist/detached-event-error.d.ts.map +1 -0
  11. package/dist/find-switch-branch-step.d.ts +45 -0
  12. package/dist/find-switch-branch-step.d.ts.map +1 -0
  13. package/dist/history-filters.d.ts +78 -0
  14. package/dist/history-filters.d.ts.map +1 -0
  15. package/dist/history-item-builder.d.ts +25 -0
  16. package/dist/history-item-builder.d.ts.map +1 -0
  17. package/dist/history-scope-api.d.ts +41 -0
  18. package/dist/history-scope-api.d.ts.map +1 -0
  19. package/dist/history-undo-session.types.d.ts +32 -0
  20. package/dist/history-undo-session.types.d.ts.map +1 -0
  21. package/dist/index.d.ts +35 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +1480 -0
  24. package/dist/merge-branch.d.ts +22 -0
  25. package/dist/merge-branch.d.ts.map +1 -0
  26. package/dist/plugin.d.ts +58 -0
  27. package/dist/plugin.d.ts.map +1 -0
  28. package/dist/pullable-count.d.ts +37 -0
  29. package/dist/pullable-count.d.ts.map +1 -0
  30. package/dist/push-inflight.d.ts +60 -0
  31. package/dist/push-inflight.d.ts.map +1 -0
  32. package/dist/redo-stack.d.ts +56 -0
  33. package/dist/redo-stack.d.ts.map +1 -0
  34. package/dist/remove-branch.d.ts +16 -0
  35. package/dist/remove-branch.d.ts.map +1 -0
  36. package/dist/restore-entity.d.ts +15 -0
  37. package/dist/restore-entity.d.ts.map +1 -0
  38. package/dist/scope-selection.d.ts +55 -0
  39. package/dist/scope-selection.d.ts.map +1 -0
  40. package/dist/switch-branch-actions.d.ts +16 -0
  41. package/dist/switch-branch-actions.d.ts.map +1 -0
  42. package/dist/sync-history-bridge.d.ts +87 -0
  43. package/dist/sync-history-bridge.d.ts.map +1 -0
  44. package/dist/undo-redo-apply.d.ts +47 -0
  45. package/dist/undo-redo-apply.d.ts.map +1 -0
  46. package/dist/version-manager.utils.d.ts +30 -0
  47. package/dist/version-manager.utils.d.ts.map +1 -0
  48. package/package.json +57 -3
  49. package/src/HistoryManager.ts +770 -0
  50. package/src/VersionManager.ts +451 -0
  51. package/src/create-branch.ts +154 -0
  52. package/src/detached-event-error.ts +43 -0
  53. package/src/find-switch-branch-step.ts +277 -0
  54. package/src/history-filters.ts +157 -0
  55. package/src/history-item-builder.ts +101 -0
  56. package/src/history-scope-api.ts +189 -0
  57. package/src/history-undo-session.types.ts +37 -0
  58. package/src/index.ts +46 -0
  59. package/src/merge-branch.ts +153 -0
  60. package/src/plugin.ts +93 -0
  61. package/src/pullable-count.ts +67 -0
  62. package/src/push-inflight.ts +91 -0
  63. package/src/redo-stack.ts +79 -0
  64. package/src/remove-branch.ts +89 -0
  65. package/src/restore-entity.ts +97 -0
  66. package/src/scope-selection.ts +132 -0
  67. package/src/switch-branch-actions.ts +238 -0
  68. package/src/sync-history-bridge.ts +131 -0
  69. package/src/undo-redo-apply.ts +260 -0
  70. 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
- # Temporary Holding Version
1
+ # @aiao/rxdb-plugin-history
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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/):`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,79 @@
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
+ * @internal
74
+ */
75
+ invalidateRedoStack(triggerChangeIds?: readonly number[]): Promise<void>;
76
+ /** 创建(或取出缓存的)作用域历史 API */
77
+ history<T extends EntityType>(options?: T | InstanceType<T> | HistoryScope): HistoryScopeAPI;
78
+ }
79
+ //# 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,233 @@
1
+ import { EntityType, HistoryScopeAPI, MergeBranchOptions, MergeBranchResult, RestoreEntityOptions, RxDB, RxDBBranch } 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
+ * 不发任何适配器读写,因此可以(也必须)早于引导链跑:`HistoryManager` 的分支流
83
+ * 要赶在第一条 `rxdb_change` 事件之前订阅上,装晚了那一批变更就不进历史。
84
+ */
85
+ init(): void;
86
+ /**
87
+ * 摘掉全部事件监听与订阅,并销毁 {@link HistoryManager}。
88
+ *
89
+ * @remarks
90
+ * 幂等。事务深度与代次一并清零:拆卸可能发生在事务中途,留着计数会让下一个纪元
91
+ * 以为自己开局就在一笔未结的事务里。
92
+ */
93
+ destroy(): void;
94
+ /**
95
+ * 作废本连接积累的历史上下文:清空全部分支的 undo 会话与待拉计数。
96
+ *
97
+ * @remarks
98
+ * 供切库 / 重连这类「本地数据整体换了一份」的场景调用。清的是**全部**分支而不只是
99
+ * 当前分支 —— 换掉的是整个数据源,其它分支上那些 undo 条目指向的行同样已经不在了。
100
+ */
101
+ resetSessionState(): void;
102
+ /**
103
+ * 创建新分支
104
+ * @param branchId 分支 id
105
+ * @param fromChangeId 从哪个 changeId 创建新分支
106
+ */
107
+ createBranch(branchId: string, fromChangeId?: number): Promise<InstanceType<typeof RxDBBranch>>;
108
+ /**
109
+ * 删除分支
110
+ * @param branchId 分支 id
111
+ */
112
+ removeBranch(branchId: string): Promise<void>;
113
+ /**
114
+ * 切换到指定分支
115
+ *
116
+ * @param branchId - 目标分支 ID
117
+ *
118
+ * @remarks
119
+ * 切换分支后会自动清空 redo 栈,因为 redo 历史在新分支中不再有效。
120
+ * 如果目标分支与当前分支相同,则直接返回,避免不必要的操作。
121
+ */
122
+ switchBranch(branchId: string): Promise<void>;
123
+ /**
124
+ * 合并分支
125
+ *
126
+ * 将源分支的变更合并到当前激活分支(目标分支)。
127
+ *
128
+ * @param sourceBranchId - 源分支 ID
129
+ * @param options - 合并选项
130
+ * @returns 合并结果
131
+ *
132
+ * @remarks
133
+ * 支持两种策略:
134
+ * - `squash`(默认):将源分支所有变更压缩为最小操作集后一次性应用,目标分支只产生一组变更记录
135
+ * - `normal`:逐条应用源分支变更,每条变更在目标分支产生独立的变更记录(保留历史细节)
136
+ *
137
+ * 合并后会清空 undo/redo 历史,因为合并操作不可逆。
138
+ * 可选通过 `deleteSource: true` 在合并后删除源分支。
139
+ *
140
+ * @example
141
+ * ```typescript
142
+ * // 压缩合并(默认)
143
+ * const result = await rxdb.versionManager.mergeBranch('feature-x');
144
+ * console.log(`Merged ${result.merged} changes`);
145
+ *
146
+ * // 普通合并
147
+ * const result = await rxdb.versionManager.mergeBranch('feature-x', {
148
+ * strategy: 'normal'
149
+ * });
150
+ *
151
+ * // 合并后删除源分支
152
+ * const result = await rxdb.versionManager.mergeBranch('feature-x', {
153
+ * deleteSource: true
154
+ * });
155
+ * ```
156
+ */
157
+ mergeBranch(sourceBranchId: string, options?: MergeBranchOptions): Promise<MergeBranchResult>;
158
+ /**
159
+ * 获取特定作用域的历史记录 API
160
+ *
161
+ * @param options - 作用域选项:
162
+ * - 不传参数 → database 作用域(整个数据库)
163
+ * - EntityType 类 → repository 作用域(该实体的所有记录)
164
+ * - 实体实例 → entity 作用域(该实例的历史)
165
+ * @returns 统一的历史记录 API 接口
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * // 数据库级别
170
+ * const dbHistory = versionManager.history();
171
+ *
172
+ * // 仓库级别(所有 User 记录)
173
+ * const userHistory = versionManager.history(User);
174
+ *
175
+ * // 实体级别(单个用户)
176
+ * const entityHistory = versionManager.history(userInstance);
177
+ * ```
178
+ */
179
+ history<T extends EntityType>(options?: T | InstanceType<T>): HistoryScopeAPI;
180
+ /**
181
+ * 恢复被删除的实体
182
+ *
183
+ * 根据 RxDBChange 记录中的 inversePatch 重新插入实体,
184
+ * 恢复操作本身会生成新的 RxDBChange 记录(可被 push 到远程)。
185
+ *
186
+ * @param entity - 被删除的实体实例(需要包含 metadata 信息)
187
+ * @param options - 恢复选项,包含 changeId(DELETE 类型的 RxDBChange 记录 ID)
188
+ * @returns 恢复后的实体实例
189
+ */
190
+ restoreEntity<T extends EntityType>(entity: InstanceType<T>, options: RestoreEntityOptions): Promise<InstanceType<T>>;
191
+ /**
192
+ * 取本地适配器上的系统表仓库。
193
+ *
194
+ * @returns `branchRepository` / `changeRepository` 与它们所属的本地适配器
195
+ *
196
+ * @remarks
197
+ * 每次都经 `localAdapter$` 重新解析,不缓存:适配器随连接纪元换,缓下来的那一份
198
+ * 会在重连之后指向已拆的旧实例。
199
+ */
200
+ getLocalRepositories(): Promise<{
201
+ branchRepository: import('@aiao/rxdb').LocalRxDBBranchRepository;
202
+ changeRepository: import('@aiao/rxdb').LocalRxDBChangeRepository;
203
+ adapter: import('@aiao/rxdb').IRxDBAdapter & import('@aiao/rxdb').RxDBAdapterLocalBase;
204
+ }>;
205
+ /**
206
+ * 取远端适配器上的系统表仓库。
207
+ *
208
+ * @returns `branchRepository` / `changeRepository` 与它们所属的远端适配器
209
+ *
210
+ * @remarks
211
+ * 未配置远端时 `remoteAdapter$` 不发值,调用会一直挂着 —— 这是有意的:同步路径
212
+ * 本来就只在配了远端时才走,返回一个空壳只会把「没配远端」推迟到更深的地方才报。
213
+ */
214
+ getRemoteRepositories(): Promise<{
215
+ branchRepository: import('@aiao/rxdb').RemoteRxDBBranchRepository;
216
+ changeRepository: import('@aiao/rxdb').RemoteRxDBChangeRepository;
217
+ adapter: import('@aiao/rxdb').IRxDBAdapter & import('@aiao/rxdb').RxDBAdapterRemoteBase;
218
+ }>;
219
+ /**
220
+ * 取当前分支;没有激活分支时激活(或新建)`main`。
221
+ *
222
+ * @remarks
223
+ * 分两段是有意的:
224
+ *
225
+ * - **热路径**(已有激活分支)不开事务。同步插件的远端事件链路里每条事件都要调它
226
+ * (`sync-listeners` 的 `filterByBranch`),把整段包进事务能修好并发,
227
+ * 但会让每次读都去抢并发度 1 的写队列槽位。
228
+ * - **冷路径**(查不到激活分支)才开事务,并在事务内**重做一遍检查**(双重检查)。
229
+ * 否则两个并发调用会双双走到 `create`,第二个撞主键报错。
230
+ */
231
+ getCurrentBranch(): Promise<RxDBBranch>;
232
+ }
233
+ //# sourceMappingURL=VersionManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VersionManager.d.ts","sourceRoot":"","sources":["../src/VersionManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,UAAU,EAIV,eAAe,EAIf,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,IAAI,EACJ,UAAU,EAQX,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;;;;;;;;;;OAUG;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;;;;;;;;OAQG;IACG,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAqCnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;CAYvB"}
@@ -0,0 +1,29 @@
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
+ export declare const create_branch: (version: VersionManager, branchId: string, fromChangeId?: number) => Promise<RxDBBranch>;
19
+ /**
20
+ * 获取分支最新一笔可作为分叉点的变更记录
21
+ *
22
+ * @param changeRepository - 变更仓库。由调用方决定它属于哪个事务 ——
23
+ * `create_branch` 传的是事务内的那一份,不能在这里自己去 `getLocalRepositories()`。
24
+ * @param currentBranchId - 分支 ID;不传则按「当前激活分支」查
25
+ *
26
+ * 独立导出而非内联,是为了被 `__tests__/version/create-branch.spec.ts` 单独测试。
27
+ */
28
+ export declare const get_current_branch_last_change: (changeRepository: LocalRxDBChangeRepository, currentBranchId?: string) => Promise<RxDBChange>;
29
+ //# 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,EAEL,KAAK,yBAAyB,EAE9B,UAAU,EACV,UAAU,EAEX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa,GAAU,SAAS,cAAc,EAAE,UAAU,MAAM,EAAE,eAAe,MAAM,wBA8FnG,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,45 @@
1
+ import { RxDBBranch } from '@aiao/rxdb';
2
+ /**
3
+ * 分支切换步骤
4
+ */
5
+ export interface SwitchBranchStep {
6
+ /**
7
+ * 分支对象
8
+ */
9
+ branch: RxDBBranch;
10
+ /**
11
+ * 开始变更 ID
12
+ */
13
+ fromChangeId: number;
14
+ /**
15
+ * 目标变更 ID
16
+ */
17
+ toChangeId: number;
18
+ }
19
+ /**
20
+ * 查找分支切换路径的参数
21
+ */
22
+ export interface FindBranchPathOptions {
23
+ /**
24
+ * 所需分支列表
25
+ */
26
+ branches: RxDBBranch[];
27
+ /**
28
+ * 当前分支
29
+ */
30
+ currentBranch: RxDBBranch;
31
+ /**
32
+ * 当前分支的变更 ID
33
+ */
34
+ currentChangeId: number | null;
35
+ /**
36
+ * 目标分支
37
+ */
38
+ nextBranch: RxDBBranch;
39
+ /**
40
+ * 目标分支的变更 ID
41
+ */
42
+ nextChangeId: number | null;
43
+ }
44
+ export declare const find_switch_branch_step: (options: FindBranchPathOptions) => SwitchBranchStep[];
45
+ //# 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;;GAEG;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;AAyBD,eAAO,MAAM,uBAAuB,GAAI,SAAS,qBAAqB,KAAG,gBAAgB,EA2MxF,CAAC"}
@@ -0,0 +1,78 @@
1
+ import { HistoryItem, HistoryScope } from '@aiao/rxdb';
2
+ /**
3
+ * 生成 repository 的缓存键(纯函数)
4
+ *
5
+ * @param repository - 带 namespace / entity 的仓储标识
6
+ * @returns 'namespace:entity' 形式的缓存键
7
+ *
8
+ * @internal 供 HistoryManager 与同文件的过滤函数使用
9
+ */
10
+ export declare const getRepositoryKey: (repository: {
11
+ namespace: string;
12
+ entity: string;
13
+ }) => string;
14
+ /**
15
+ * 合成「每个仓库推到哪了」的水位线映射:已提交的 `RxDBSync` 水位线与正在飞的认领取较大者。
16
+ *
17
+ * @param repoSyncs - 当前分支下的 `RxDBSync` 行
18
+ * @param inFlight - `PushInFlightRegistry.snapshot()`,`namespace:entity` -> 正在飞的最大 change id
19
+ * @returns `namespace:entity` -> 该仓库「视同已推」的最大 change id
20
+ *
21
+ * @remarks
22
+ * `undoHistories$` 与 `fetchLatestHistories` 两条路径都要这份映射,此前各写一份循环。
23
+ * 两份必须逐字一致:一边认在飞、另一边不认,反应式的「可撤销」列表就会和真正执行撤销时
24
+ * 的判定分家 —— UI 上还亮着的那一项点下去什么也不会发生,或者更糟,真的撤销了一条
25
+ * 已经在飞的变更。
26
+ *
27
+ * 取最大值而不是「有在飞就用在飞」:上一轮推到 30、这一轮只在飞到 20 时,
28
+ * 水位线不许倒退。
29
+ *
30
+ * 在飞认领先进 map,因此**没有** `RxDBSync` 行的仓库也报得出来:`RxDBSync` 行由
31
+ * `planRepositoryPush` 现建,行还没落到本次查询的结果集里时,认领仍然必须生效。
32
+ */
33
+ export declare function buildLastPushedMap(repoSyncs: readonly {
34
+ namespace: string;
35
+ entity: string;
36
+ lastPushedChangeId: number | null;
37
+ }[], inFlight: ReadonlyMap<string, number>): Map<string, number>;
38
+ /**
39
+ * 按作用域过滤历史记录(纯函数)
40
+ *
41
+ * @param histories - 原始历史记录数组
42
+ * @param scope - 作用域配置
43
+ * @returns 过滤后的历史记录数组
44
+ *
45
+ * @internal 供 HistoryManager 和单元测试使用
46
+ */
47
+ export declare function filterHistoriesByScope(histories: HistoryItem[], scope: HistoryScope): HistoryItem[];
48
+ /**
49
+ * 过滤出可撤销的历史记录(纯函数)
50
+ *
51
+ * @param histories - 原始历史记录数组
52
+ * @param lastPushedMap - namespace:entity -> lastPushedChangeId 的 repository 级水位线映射
53
+ * @param undoBoundaryChangeId - 同步清空后的永久撤销边界
54
+ * @param undoBoundaryCreatedAfter - 无数字 change id 时使用的严格时间边界
55
+ * @returns 可撤销的历史记录数组
56
+ *
57
+ * @remarks
58
+ * undoHistories$(UI 展示)与 undo()(实际执行)共用同一套规则,
59
+ * 保证 UI 上看不到的历史不会被 undo() 撤销:
60
+ * 1. history.reverted == false(按 updatedAt 水位合并持久态与本地态,未被撤销)
61
+ * 2. remoteId == null(只有本地创建的变更才能撤销)
62
+ * 3. id > 该 repository 的 lastPushedChangeId(未推送到远程;按 repository 独立判断)
63
+ * 4. id > undoBoundaryChangeId(同步清空前的历史永久不可撤销)
64
+ * 5. createdAt > undoBoundaryCreatedAfter(无数字 id 时保守隔离旧 session)
65
+ *
66
+ * @internal 供 HistoryManager 和单元测试使用
67
+ */
68
+ export declare function filterUndoableHistories(histories: HistoryItem[], lastPushedMap: Map<string, number>, undoBoundaryChangeId?: number, undoBoundaryCreatedAfter?: Date | null): HistoryItem[];
69
+ /**
70
+ * 生成作用域缓存键(纯函数)
71
+ *
72
+ * @param scope - 作用域配置
73
+ * @returns 缓存键字符串:'database' | 'namespace:entity' | 'namespace:entity:id'
74
+ *
75
+ * @internal 供 HistoryManager 和单元测试使用
76
+ */
77
+ export declare function getScopeKey(scope: HistoryScope): string;
78
+ //# sourceMappingURL=history-filters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-filters.d.ts","sourceRoot":"","sources":["../src/history-filters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAA4B,KAAK,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAE3F;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,GAAI,YAAY;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,KAAG,MACrC,CAAC;AAEjD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,EAC9F,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAYrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,YAAY,GAAG,WAAW,EAAE,CA2BnG;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,WAAW,EAAE,EACxB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAClC,oBAAoB,SAAI,EACxB,wBAAwB,GAAE,IAAI,GAAG,IAAW,GAC3C,WAAW,EAAE,CAcf;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,MAAM,CAQvD"}
@@ -0,0 +1,25 @@
1
+ import { HistoryItem, RxDBChange } from '@aiao/rxdb';
2
+ /**
3
+ * 生成历史项的描述文本
4
+ *
5
+ * 规则:
6
+ * - 单条 INSERT/UPDATE/DELETE → 「创建 Foo」「更新 Foo」「删除 Foo」
7
+ * - 事务(多条变更)→ 「事务: 创建2条, 更新3条」
8
+ */
9
+ export declare function generateHistoryDescription(changes: RxDBChange[]): string;
10
+ /**
11
+ * 从一组同事务的变更构造单个 HistoryItem
12
+ *
13
+ * @param changes - 属于同一事务的变更记录(至少一条)
14
+ * @returns 结构化的历史项,包含描述、类型、状态等信息
15
+ */
16
+ export declare function createHistoryItem(changes: RxDBChange[]): HistoryItem;
17
+ /**
18
+ * 把按 id 降序排列的变更列表,转换为按事务分组的 HistoryItem 数组
19
+ *
20
+ * 转换逻辑:
21
+ * - 相同 transactionId 的连续变更合并为一个 HistoryItem
22
+ * - 无 transactionId 的变更单独成为一个 HistoryItem
23
+ */
24
+ export declare function convertChangesToHistories(changes: RxDBChange[]): HistoryItem[];
25
+ //# sourceMappingURL=history-item-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-item-builder.d.ts","sourceRoot":"","sources":["../src/history-item-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,WAAW,EAAE,UAAU,EAAQ,MAAM,YAAY,CAAC;AAErF;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAsBxE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,WAAW,CA0BpE;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,WAAW,EAAE,CA0B9E"}