@aiao/rxdb-adapter-electron 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.
Files changed (70) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +394 -2
  3. package/dist/RxDBAdapterElectron.d.ts +61 -0
  4. package/dist/RxDBAdapterElectron.d.ts.map +1 -0
  5. package/dist/electron-adapter.interface.d.ts +23 -0
  6. package/dist/electron-adapter.interface.d.ts.map +1 -0
  7. package/dist/electron-file-host.d.ts +52 -0
  8. package/dist/electron-file-host.d.ts.map +1 -0
  9. package/dist/electron-sqlite-host.d.ts +65 -0
  10. package/dist/electron-sqlite-host.d.ts.map +1 -0
  11. package/dist/host.d.ts +19 -0
  12. package/dist/host.d.ts.map +1 -0
  13. package/dist/host.js +768 -0
  14. package/dist/index.d.ts +22 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +36 -0
  17. package/dist/node-sqlite-engine.d.ts +97 -0
  18. package/dist/node-sqlite-engine.d.ts.map +1 -0
  19. package/dist/pglite/RxDBAdapterElectronPGlite.d.ts +96 -0
  20. package/dist/pglite/RxDBAdapterElectronPGlite.d.ts.map +1 -0
  21. package/dist/pglite/desktop-pglite-client.d.ts +144 -0
  22. package/dist/pglite/desktop-pglite-client.d.ts.map +1 -0
  23. package/dist/pglite/desktop-pglite-results.d.ts +14 -0
  24. package/dist/pglite/desktop-pglite-results.d.ts.map +1 -0
  25. package/dist/pglite/electron-pglite-backup-error.d.ts +32 -0
  26. package/dist/pglite/electron-pglite-backup-error.d.ts.map +1 -0
  27. package/dist/pglite/pglite-adapter.interface.d.ts +68 -0
  28. package/dist/pglite/pglite-adapter.interface.d.ts.map +1 -0
  29. package/dist/pglite/restore-electron-pglite-database.d.ts +68 -0
  30. package/dist/pglite/restore-electron-pglite-database.d.ts.map +1 -0
  31. package/dist/pglite-host/electron-pglite-host.d.ts +129 -0
  32. package/dist/pglite-host/electron-pglite-host.d.ts.map +1 -0
  33. package/dist/pglite-host/pglite-host-data-dir.d.ts +75 -0
  34. package/dist/pglite-host/pglite-host-data-dir.d.ts.map +1 -0
  35. package/dist/pglite-host/pglite-host-lock.d.ts +48 -0
  36. package/dist/pglite-host/pglite-host-lock.d.ts.map +1 -0
  37. package/dist/pglite-host/pglite-host-restore.d.ts +38 -0
  38. package/dist/pglite-host/pglite-host-restore.d.ts.map +1 -0
  39. package/dist/pglite-host/pglite-host-runtime.d.ts +90 -0
  40. package/dist/pglite-host/pglite-host-runtime.d.ts.map +1 -0
  41. package/dist/pglite-host.d.ts +17 -0
  42. package/dist/pglite-host.d.ts.map +1 -0
  43. package/dist/pglite-host.js +738 -0
  44. package/dist/pglite.d.ts +22 -0
  45. package/dist/pglite.d.ts.map +1 -0
  46. package/dist/pglite.js +493 -0
  47. package/dist/sqlite-script.d.ts +26 -0
  48. package/dist/sqlite-script.d.ts.map +1 -0
  49. package/package.json +94 -3
  50. package/src/RxDBAdapterElectron.ts +105 -0
  51. package/src/electron-adapter.interface.ts +25 -0
  52. package/src/electron-file-host.ts +758 -0
  53. package/src/electron-sqlite-host.ts +301 -0
  54. package/src/host.ts +64 -0
  55. package/src/index.ts +71 -0
  56. package/src/node-sqlite-engine.ts +631 -0
  57. package/src/pglite/RxDBAdapterElectronPGlite.ts +152 -0
  58. package/src/pglite/desktop-pglite-client.ts +614 -0
  59. package/src/pglite/desktop-pglite-results.ts +24 -0
  60. package/src/pglite/electron-pglite-backup-error.ts +128 -0
  61. package/src/pglite/pglite-adapter.interface.ts +78 -0
  62. package/src/pglite/restore-electron-pglite-database.ts +429 -0
  63. package/src/pglite-host/electron-pglite-host.ts +829 -0
  64. package/src/pglite-host/pglite-host-data-dir.ts +224 -0
  65. package/src/pglite-host/pglite-host-lock.ts +154 -0
  66. package/src/pglite-host/pglite-host-restore.ts +460 -0
  67. package/src/pglite-host/pglite-host-runtime.ts +166 -0
  68. package/src/pglite-host.ts +50 -0
  69. package/src/pglite.ts +51 -0
  70. package/src/sqlite-script.ts +134 -0
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `@aiao/rxdb-adapter-electron` 的 **renderer 侧**入口。
3
+ *
4
+ * @remarks
5
+ * 本入口只含跨传输层说话所需的东西,**不引用 `node:sqlite`**,因此可以安全地打进
6
+ * 浏览器上下文的 renderer bundle。特权侧(Electron 主进程或它拥有的 worker)请改用
7
+ * `@aiao/rxdb-adapter-electron/host`。
8
+ *
9
+ * 协议、renderer client、存储联合与错误类型的**实现**已下沉到
10
+ * `@aiao/rxdb-adapter-sqlite-core/desktop-host`(US-207 E1),两个桌面运行时共用一份。
11
+ * 本入口原样转出它们:下游按名字 import,实现搬到哪个包不该让用户改行。
12
+ *
13
+ * @module @aiao/rxdb-adapter-electron
14
+ */
15
+ export { ADAPTER_NAME as ELECTRON_ADAPTER_NAME } from './electron-adapter.interface.js';
16
+ export { RxDBAdapterElectron } from './RxDBAdapterElectron.js';
17
+ export { DEFAULT_DATABASE_SUFFIX as DESKTOP_DEFAULT_DATABASE_SUFFIX, type DesktopOptions } from '@aiao/rxdb-adapter-sqlite-core/desktop-host';
18
+ export { RxDBAdapterDesktopError, type RxDBAdapterDesktopErrorCode } from '@aiao/rxdb-adapter-sqlite-core/desktop-host';
19
+ export { DESKTOP_HOST_TRANSPORT_KEY, DesktopSqliteClient, resolveDesktopHostTransport, type DesktopHostTransport, type DesktopSqliteClientOptions } from '@aiao/rxdb-adapter-sqlite-core/desktop-host';
20
+ export { assertDesktopSqliteStorage, assertValidDesktopDatabaseName, isDesktopPgliteDirectoryStorage, isDesktopSqliteFileStorage, type DesktopPgliteDirectoryStorage, type DesktopSqliteFileStorage, type DesktopStorage } from '@aiao/rxdb-adapter-sqlite-core/desktop-host';
21
+ export { DESKTOP_HOST_MAX_BINDINGS, DESKTOP_HOST_MAX_BLOB_BYTES, DESKTOP_HOST_MAX_FILE_CHUNK_BYTES, DESKTOP_HOST_MAX_SQL_LENGTH, DESKTOP_HOST_PROTOCOL_VERSION, assertDesktopHostResponse, parseDesktopHostChangeEvent, parseDesktopHostHandshakeResult, parseDesktopHostOpenResult, type DesktopHostChangeEventMessage, type DesktopHostCloseRequest, type DesktopHostExecuteRequest, type DesktopHostFileEntry, type DesktopHostFileLockMode, type DesktopHostFileReadResult, type DesktopHostFileRequest, type DesktopHostFileResponse, type DesktopHostFileStat, type DesktopHostHandshakeRequest, type DesktopHostHandshakeResult, type DesktopHostMuteRequest, type DesktopHostOpenRequest, type DesktopHostOpenResult, type DesktopHostRequest, type DesktopHostResponse, type DesktopHostVersionRequest } from '@aiao/rxdb-adapter-sqlite-core/desktop-host';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,YAAY,IAAI,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EACL,uBAAuB,IAAI,+BAA+B,EAC1D,KAAK,cAAc,EACpB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EAAE,uBAAuB,EAAE,KAAK,2BAA2B,EAAE,MAAM,6CAA6C,CAAC;AAExH,OAAO,EACL,0BAA0B,EAC1B,mBAAmB,EACnB,2BAA2B,EAC3B,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAChC,MAAM,6CAA6C,CAAC;AAErD,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,EAC9B,+BAA+B,EAC/B,0BAA0B,EAC1B,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC7B,KAAK,cAAc,EACpB,MAAM,6CAA6C,CAAC;AAErD,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,iCAAiC,EACjC,2BAA2B,EAC3B,6BAA6B,EAC7B,yBAAyB,EACzB,2BAA2B,EAC3B,+BAA+B,EAC/B,0BAA0B,EAC1B,KAAK,6BAA6B,EAClC,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC/B,MAAM,6CAA6C,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,36 @@
1
+ import { RxDBAdapterSqliteBase as e } from "@aiao/rxdb-adapter-sqlite-core";
2
+ import { DEFAULT_DATABASE_SUFFIX as t, DEFAULT_DATABASE_SUFFIX as n, DESKTOP_HOST_MAX_BINDINGS as r, DESKTOP_HOST_MAX_BLOB_BYTES as i, DESKTOP_HOST_MAX_FILE_CHUNK_BYTES as a, DESKTOP_HOST_MAX_SQL_LENGTH as o, DESKTOP_HOST_PROTOCOL_VERSION as s, DESKTOP_HOST_TRANSPORT_KEY as c, DesktopSqliteClient as l, DesktopSqliteClient as u, RxDBAdapterDesktopError as d, assertDesktopHostResponse as f, assertDesktopSqliteStorage as p, assertValidDesktopDatabaseName as m, assertValidDesktopDatabaseName as h, connectDesktopRestoreTarget as g, isDesktopPgliteDirectoryStorage as _, isDesktopSqliteFileStorage as v, parseDesktopHostChangeEvent as y, parseDesktopHostHandshakeResult as b, parseDesktopHostOpenResult as x, resolveDesktopHostTransport as S, resolveDesktopHostTransport as C } from "@aiao/rxdb-adapter-sqlite-core/desktop-host";
3
+ //#region src/electron-adapter.interface.ts
4
+ var w = "sqlite-electron", T = class extends e {
5
+ options;
6
+ #e;
7
+ #t;
8
+ name = w;
9
+ get databaseName() {
10
+ return this.#e;
11
+ }
12
+ constructor(e, n = {}) {
13
+ super(e, n), this.options = n, this.#e = n.databaseName ?? `${e.config.dbName}${t}`, h(this.#e), this.#t = `${this.name}:file:${this.#e}`;
14
+ }
15
+ async createClient() {
16
+ return u.connect(this.options.transport ?? C(), {
17
+ engine: "sqlite",
18
+ databaseName: this.#e
19
+ }, { batchTimeout: this.options.batchTimeout });
20
+ }
21
+ backupStorage() {
22
+ return {
23
+ kind: "persistent",
24
+ label: "file",
25
+ storageKey: this.#t
26
+ };
27
+ }
28
+ shadowTablesWritable() {
29
+ return !1;
30
+ }
31
+ createRestoreTargetClient() {
32
+ return g(() => this.createClient(), this.#t);
33
+ }
34
+ };
35
+ //#endregion
36
+ export { n as DESKTOP_DEFAULT_DATABASE_SUFFIX, r as DESKTOP_HOST_MAX_BINDINGS, i as DESKTOP_HOST_MAX_BLOB_BYTES, a as DESKTOP_HOST_MAX_FILE_CHUNK_BYTES, o as DESKTOP_HOST_MAX_SQL_LENGTH, s as DESKTOP_HOST_PROTOCOL_VERSION, c as DESKTOP_HOST_TRANSPORT_KEY, l as DesktopSqliteClient, w as ELECTRON_ADAPTER_NAME, d as RxDBAdapterDesktopError, T as RxDBAdapterElectron, f as assertDesktopHostResponse, p as assertDesktopSqliteStorage, m as assertValidDesktopDatabaseName, _ as isDesktopPgliteDirectoryStorage, v as isDesktopSqliteFileStorage, y as parseDesktopHostChangeEvent, b as parseDesktopHostHandshakeResult, x as parseDesktopHostOpenResult, S as resolveDesktopHostTransport };
@@ -0,0 +1,97 @@
1
+ import { SqliteChangeEvent, SQLiteCompatibleType, SqliteResult } from '@aiao/rxdb-adapter-sqlite-core';
2
+ /** {@link NodeSqliteEngine.open} 的入参。 */
3
+ export interface NodeSqliteEngineOptions {
4
+ /** 数据库文件的绝对物理路径,由 host 在应用数据目录内解析得出。 */
5
+ readonly filePath: string;
6
+ /** 逻辑数据库名,仅用于变更事件的诊断字段。 */
7
+ readonly dbName: string;
8
+ /**
9
+ * 变更事件回调。
10
+ *
11
+ * @remarks
12
+ * 在产生变更的语句返回**之后**的任务里调用(批处理见 {@link NodeSqliteEngineOptions.batchTimeout}),
13
+ * 唯一的例外是 {@link NodeSqliteEngine.close} 里的收尾 flush。实现方不该抛错——
14
+ * 此刻写入早已落库,没有任何调用方还能对失败做出反应;真抛了也只会被隔离并 log,
15
+ * 既不会中断同批次的其余分组,也不会传播给写入方。
16
+ */
17
+ readonly onChange: (event: SqliteChangeEvent) => void;
18
+ /** SQLite page cache 大小(KB),默认 {@link DEFAULT_CACHE_SIZE_KB}。 */
19
+ readonly cacheSizeKb?: number;
20
+ /**
21
+ * 变更事件的防抖窗口(毫秒),默认 {@link DEFAULT_BATCH_TIMEOUT}。
22
+ *
23
+ * @remarks
24
+ * 与 wasm 后端的同名选项同义:窗口内的连续写入合并成一次派发。0 表示下一个宏任务立即派发。
25
+ */
26
+ readonly batchTimeout?: number;
27
+ }
28
+ /**
29
+ * 单个数据库连接。
30
+ *
31
+ * @remarks
32
+ * 一个会话一个连接,不共享:两个窗口若共用一条连接,它们的 `BEGIN` 块会互相穿插,
33
+ * 事务隔离直接失效。各自持有连接后,跨窗口的并发交给 SQLite 自己的文件锁与写者租约处理。
34
+ */
35
+ export declare class NodeSqliteEngine {
36
+ #private;
37
+ private constructor();
38
+ /**
39
+ * 打开(必要时创建)一个数据库文件。
40
+ *
41
+ * @remarks
42
+ * 打不开就抛错,**绝不**回退到内存库或另一个位置:用户必须能确信数据确实写进了
43
+ * 他指定的那个文件(AC#4)。初始化中途失败时会把已开的句柄关掉,不留悬挂连接。
44
+ *
45
+ * @param options - 引擎配置
46
+ * @returns 已完成初始化、已装好变更通知的引擎
47
+ * @throws {@link RxDBAdapterDesktopError} code 为 `open_failed` / `permission_denied` / `database_corrupted`
48
+ */
49
+ static open(options: NodeSqliteEngineOptions): NodeSqliteEngine;
50
+ /**
51
+ * 执行一条或一组 SQL。
52
+ *
53
+ * @remarks
54
+ * 结果形状与 `executeOo1Helper` 逐字对齐(AC#2):至多一个结果集,且只在语句真的产出列时才有;
55
+ * 只读语句的 `rowsAffected` 恒为 0,不泄漏上一条写语句遗留的计数。
56
+ *
57
+ * 多语句脚本逐条 prepare 执行(切分见 {@link splitSqliteScript}),但**不接受绑定参数**:
58
+ * 参数属于其中某一条语句,静默绑到第一条只会把数据写错位;wasm 后端同样拒绝这个组合。
59
+ *
60
+ * @param sql - 待执行的 SQL
61
+ * @param bindings - 位置绑定参数
62
+ * @returns 与 sqlite 核心一致的执行结果
63
+ * @throws {@link RxDBAdapterDesktopError} 会话已关闭、多语句带参、或 SQL 执行失败时
64
+ */
65
+ execute(sql: string, bindings?: readonly SQLiteCompatibleType[]): SqliteResult;
66
+ /**
67
+ * 报告底层 SQLite 引擎版本。
68
+ *
69
+ * @returns 形如 `3.50.4` 的版本串
70
+ */
71
+ version(): string;
72
+ /**
73
+ * 暂停 / 恢复变更事件采集。
74
+ *
75
+ * @remarks
76
+ * 恢复整库时静音(US-217):恢复写进去的系统表行不是新变更。静音前已经攒下的批次不丢,
77
+ * 照常按定时器发出——它们记录的是静音前真实发生的写入。
78
+ *
79
+ * @param muted - `true` 时触发器报上来的变更直接丢弃,不入批也不派发
80
+ */
81
+ setChangeEventsMuted(muted: boolean): void;
82
+ /**
83
+ * 断开连接并释放文件句柄。
84
+ *
85
+ * @remarks
86
+ * 关闭前回滚尚未提交的事务并做一次 TRUNCATE checkpoint(AC#7):前者避免把半截状态留给下次启动,
87
+ * 后者把 WAL 内容并回主库文件,使调用方随后可以直接重命名/备份这个 `.sqlite3`,
88
+ * 而不必额外搬运 `-wal` / `-shm` 旁文件。
89
+ *
90
+ * 还攒在批次里的变更事件在这里**同步**发掉,与 `Oo1ClientBase.disconnect` 一致:
91
+ * 定时器随连接一起消失,不发就等于把最后一批写入的通知悄悄吞掉。
92
+ *
93
+ * 重复调用是安全的。
94
+ */
95
+ close(): void;
96
+ }
97
+ //# sourceMappingURL=node-sqlite-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-sqlite-engine.d.ts","sourceRoot":"","sources":["../src/node-sqlite-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EASL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EAEzB,KAAK,YAAY,EAClB,MAAM,gCAAgC,CAAC;AAKxC,yCAAyC;AACzC,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2BAA2B;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;;;;;;OAQG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACtD,iEAAiE;IACjE,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAyJD;;;;;;GAMG;AACH,qBAAa,gBAAgB;;IAiB3B,OAAO;IASP;;;;;;;;;;OAUG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,uBAAuB,GAAG,gBAAgB;IA6B/D;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAE,SAAS,oBAAoB,EAAO,GAAG,YAAY;IAkBlF;;;;OAIG;IACH,OAAO,IAAI,MAAM;IAMjB;;;;;;;;OAQG;IACH,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAK1C;;;;;;;;;;;;OAYG;IACH,KAAK,IAAI,IAAI;CAwRd"}
@@ -0,0 +1,96 @@
1
+ import { RxDB, RxDBBackupOptions, RxDBBackupResult } from '@aiao/rxdb';
2
+ import { RxDBAdapterPGlite, IPGliteClient } from '@aiao/rxdb-adapter-pglite';
3
+ import { ADAPTER_NAME, ElectronPGliteOptions } from './pglite-adapter.interface.js';
4
+ /**
5
+ * 把 RxDB 接到 Electron 主进程持有的那个唯一 PGlite 实例上。
6
+ *
7
+ * @remarks
8
+ * 数据落在主进程的应用数据目录里,renderer 只通过一条窄传输层发 `pg.*` 请求,
9
+ * 因此它既拿不到 OPFS 句柄,也拿不到物理路径(AC#5)。
10
+ *
11
+ * 适配器本身没有自己的查询实现:SQL 生成、迁移、变更管线、加密全部复用
12
+ * {@link RxDBAdapterPGlite},只把 {@link RxDBAdapterPGlite.createClient} 这一个接缝
13
+ * 换成了 {@link DesktopPGliteClient}。这是刻意的——桌面与浏览器共用一份行为,
14
+ * 分叉出去的每一行都会变成「只在 Electron 下复现」的 bug。
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * rxdb.registerAdapter(new RxDBAdapterElectronPGlite(rxdb));
19
+ * ```
20
+ */
21
+ export declare class RxDBAdapterElectronPGlite extends RxDBAdapterPGlite {
22
+ #private;
23
+ name: string;
24
+ /** 解析出的逻辑数据目录名,与 host 侧的物理目录一一对应。 */
25
+ get dataDirectoryName(): string;
26
+ /**
27
+ * @param rxdb - 绑定的 RxDB 实例
28
+ * @param options - 传输层、逻辑数据目录名与两个超时窗口
29
+ * @throws {@link RxDBAdapterDesktopError} 逻辑数据目录名越出应用作用域时抛 `invalid_database_name`
30
+ */
31
+ constructor(rxdb: RxDB, options?: ElectronPGliteOptions);
32
+ /**
33
+ * 把 host 上的整个数据目录写成一份可恢复的归档(US-217)。
34
+ *
35
+ * @remarks
36
+ * 快照由 host 取:它在本会话那条唯一的连接上挂起一个空事务并 `CHECKPOINT`,写出期间别的窗口、
37
+ * 别的会话都改不动文件,归档因此对应一个已提交事务边界,快照边界前 WAL 里已提交的数据也都
38
+ * 已落进数据文件。数据块按 renderer 的读取节奏逐块过 IPC,host 不预读,内存占用与库大小无关。
39
+ *
40
+ * 与浏览器端的差异:
41
+ * - 等连接空闲的上限是构造参数里的 `beginTimeout`,不是 `options.lockTimeoutMs`(后者只管本
42
+ * adapter 内部队列的排队)。另一个窗口长期占着事务时报 `lock_timeout`。
43
+ * - manifest 的元数据(引擎版本、系统表版本)在快照开始之前读取,这两次读取与普通语句一样排在
44
+ * 别的窗口的事务后面。
45
+ * - 主进程创建 host 时没有传 `backup` 选项(未接入 US-217)时报 `unsupported_combination`,
46
+ * 此时不获取输出流的 writer,也不 abort 它。
47
+ *
48
+ * 任何失败都归一成 {@link RxDBBackupError}:桌面错误码按
49
+ * {@link toElectronPGliteBackupError} 的映射表转换,host 不可达等其余失败报 `io_error`,
50
+ * 原始错误留在 `cause` 上。
51
+ *
52
+ * @param sink - 输出流;成功时被 close,快照开始后的失败会 abort 它
53
+ * @param options - 取消信号与排队时限
54
+ * @returns 结束标记(条目数、字节数、SHA-256)、manifest 与范围;输出流 close 已完成
55
+ * @throws RxDBBackupError `unsupported_combination` / `lock_timeout` / `aborted` / `invalid_state` /
56
+ * `io_error` / `storage_full`
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * // sink 由宿主应用提供:沙箱里的 renderer 没有 node:fs,常见做法是 preload 暴露一条
61
+ * // 只能写进应用备份目录的 WritableStream
62
+ * const result = await adapter.backup(sink);
63
+ * console.log(result.sha256);
64
+ * ```
65
+ */
66
+ backup(sink: WritableStream<Uint8Array>, options?: RxDBBackupOptions): Promise<RxDBBackupResult>;
67
+ /**
68
+ * 建出转发到主进程的客户端。
69
+ *
70
+ * @returns 尚未 `init()` 的桌面客户端;基类随后用 `rxdb.config.dbName` 初始化它
71
+ */
72
+ protected createClient(): IPGliteClient;
73
+ /**
74
+ * 备份 manifest 记录的存储后端:host 上的一棵数据目录。
75
+ *
76
+ * @returns 固定为 `directory`
77
+ */
78
+ protected backupStorage(): string;
79
+ /**
80
+ * 备份 manifest 记录的扩展名:host 运行时实际加载的那一组(已去重、排序)。
81
+ *
82
+ * @remarks
83
+ * renderer 侧的 PGlite 选项全部为空,只有 host 知道每个实例装了哪些扩展;恢复时目标 host 必须
84
+ * 全部提供。host 未启用备份时 `pg.engine` 报 `unsupported_operation`,于是在排队、取 writer 之前
85
+ * 就拒绝。
86
+ *
87
+ * @returns 扩展名
88
+ */
89
+ protected backupExtensions(): Promise<readonly string[]>;
90
+ }
91
+ declare module '@aiao/rxdb' {
92
+ interface RxDBAdapters {
93
+ [ADAPTER_NAME]: RxDBAdapterElectronPGlite;
94
+ }
95
+ }
96
+ //# sourceMappingURL=RxDBAdapterElectronPGlite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RxDBAdapterElectronPGlite.d.ts","sourceRoot":"","sources":["../../src/pglite/RxDBAdapterElectronPGlite.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAUlF,OAAO,EAAE,YAAY,EAA4B,KAAK,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEnH;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,yBAA0B,SAAQ,iBAAiB;;IAGrD,IAAI,EAAE,MAAM,CAAgB;IAErC,qCAAqC;IACrC,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED;;;;OAIG;gBACS,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE,qBAA0B;IAU3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACY,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAQnH;;;;OAIG;cACgB,YAAY,IAAI,aAAa;IAShD;;;;OAIG;cACgB,aAAa,IAAI,MAAM;IAI1C;;;;;;;;;OASG;cACsB,gBAAgB,IAAI,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC;CASxE;AAED,OAAO,QAAQ,YAAY,CAAC;IAC1B,UAAU,YAAY;QACpB,CAAC,YAAY,CAAC,EAAE,yBAAyB,CAAC;KAC3C;CACF"}
@@ -0,0 +1,144 @@
1
+ import { IPGliteClient, PGliteClientEvents, PGliteClientOptions, PGliteDataDirItem } from '@aiao/rxdb-adapter-pglite';
2
+ import { DesktopHostTransport } from '@aiao/rxdb-adapter-sqlite-core/desktop-host';
3
+ import { EventDispatcher } from '@aiao/utils';
4
+ import { QueryOptions, Results, Transaction } from '@electric-sql/pglite';
5
+ /** {@link DesktopPGliteClient} 的构造参数。 */
6
+ export interface DesktopPGliteClientOptions {
7
+ /** preload 或 worker 桥接提供的传输层。 */
8
+ readonly transport: DesktopHostTransport;
9
+ /** 应用作用域内的逻辑数据目录名;host 在自己的应用数据目录里解析它。 */
10
+ readonly dataDirectoryName: string;
11
+ /** `pg.begin` 的等待上限(毫秒);省略时由 host 用协议默认值。 */
12
+ readonly beginTimeout?: number;
13
+ /** NOTIFY 批量窗口(毫秒);省略时用 {@link DEFAULT_NOTIFY_BATCH_TIMEOUT_MS}。 */
14
+ readonly batchTimeout?: number;
15
+ }
16
+ /**
17
+ * 通过桌面 host 访问主进程 PGlite 实例的客户端。
18
+ *
19
+ * @remarks
20
+ * 两条串行化链各管一件事:
21
+ * - {@link DesktopPGliteClient.#tail} 是**会话内 FIFO**,保证发出顺序即执行顺序;
22
+ * - {@link DesktopPGliteClient.#lock} 是**本地互斥**,让事务独占整段时间。
23
+ *
24
+ * 后者不是可有可无的谨慎:主进程只有一条 PGlite 连接,一条事务开着时它被挂起的
25
+ * callback 攥着。没有本地互斥的话,第二条事务的 `pg.begin`(或一条自动提交语句)会排在
26
+ * 会话队列里等那条连接,而连接又要等第一条事务把剩下的语句发完——双方互相等,
27
+ * 表现为几秒后一句 `transaction_unavailable`,看上去像 host 有 bug。浏览器路径上
28
+ * PGlite 自己的 mutex 做的正是同一件事,这里只是把它挪到了进程边界的这一侧。
29
+ *
30
+ * @public
31
+ */
32
+ export declare class DesktopPGliteClient extends EventDispatcher<PGliteClientEvents> implements IPGliteClient {
33
+ #private;
34
+ /** 本客户端在 host 上的会话 ID,用于把推送过来的 NOTIFY 对号入座。 */
35
+ get sessionId(): string;
36
+ /** host 解析出的逻辑位置,仅供诊断(AC#5)。 */
37
+ get resolvedLocation(): string;
38
+ /** 尚未分发的 NOTIFY 行事件数量。 */
39
+ get pendingNotificationCount(): number;
40
+ constructor(options: DesktopPGliteClientOptions);
41
+ /**
42
+ * 握手、打开会话并订阅变更推送。
43
+ *
44
+ * @remarks
45
+ * 握手排在 `pg.open` 之前是 AC#11 的全部内容:`pg.open` 会 `mkdir` 出数据目录并在里面
46
+ * 跑 initdb,等 renderer 从 open 应答里读出版本不匹配时,磁盘上已经多了一整棵目录树,
47
+ * 而调用方拿不到 client,也就没有把手去收拾它。
48
+ *
49
+ * @param dbName - RxDB 逻辑库名;只用于变更事件的 `dbName` 字段,不参与落盘位置解析
50
+ * @param options - PGlite 选项;**不得**含 `store` 或 `dataDir`
51
+ * @throws `RxDBBackupError` 数据目录正在被恢复(`restore_in_progress`)或留着未完成的恢复
52
+ * (`restore_incomplete`)时,见 {@link DesktopPGliteClient.#assertOpened}
53
+ * @throws {@link RxDBAdapterDesktopError} 指定了落盘位置、协议版本不匹配或 host 打不开数据目录时
54
+ */
55
+ init(dbName: string, options: PGliteClientOptions): Promise<void>;
56
+ /**
57
+ * 执行一条带参数的语句(扩展查询协议)。
58
+ *
59
+ * @param query - SQL
60
+ * @param params - 位置参数
61
+ * @param options - **必须省略**,见 {@link assertNoQueryOptions}
62
+ * @returns 与浏览器路径同形状的结果
63
+ * @throws {@link RxDBAdapterDesktopError} 会话已关闭、传了 `options`,或 host 报告执行失败时
64
+ */
65
+ query<T>(query: string, params?: unknown[], options?: QueryOptions): Promise<Results<T>>;
66
+ /**
67
+ * 以标签模板执行一条语句,参数自动参数化。
68
+ *
69
+ * @param sqlStrings - 模板字面量片段
70
+ * @param params - 插值;`identifier` / `raw` / 嵌套 `sql` 辅助器按原语义处理
71
+ * @returns 与浏览器路径同形状的结果
72
+ * @throws {@link RxDBAdapterDesktopError} 会话已关闭,或 host 报告执行失败时
73
+ */
74
+ sql<T>(sqlStrings: TemplateStringsArray, ...params: unknown[]): Promise<Results<T>>;
75
+ /**
76
+ * 执行一段多语句脚本(简单查询协议)。
77
+ *
78
+ * @param query - 一条或多条以 `;` 分隔的语句
79
+ * @param options - **必须省略**,见 {@link assertNoQueryOptions}
80
+ * @returns 每条语句一个结果
81
+ * @throws {@link RxDBAdapterDesktopError} 会话已关闭、传了 `options`,或 host 报告执行失败时
82
+ */
83
+ exec(query: string, options?: QueryOptions): Promise<Results[]>;
84
+ /**
85
+ * 在主进程那条唯一连接上开一条真事务。
86
+ *
87
+ * @remarks
88
+ * 回调拿到的 `tx` 是个代理:它的每条语句都带着 host 签发的事务 ID 过去,因此确实落在
89
+ * 同一条 PostgreSQL 事务里,而不是被包装成「看起来像事务」的独立请求(AC#2)。
90
+ * 回调正常返回即 `pg.commit`,抛出即 `pg.rollback`——与 PGlite 自己的语义一致。
91
+ *
92
+ * @param callback - 事务体
93
+ * @returns 回调的返回值
94
+ * @throws 回调抛出的原始异常(事务已回滚),或 {@link RxDBAdapterDesktopError}
95
+ */
96
+ transaction<T>(callback: (tx: Transaction) => Promise<T>): Promise<T>;
97
+ /**
98
+ * 报告 host 侧 PostgreSQL 的版本串。
99
+ *
100
+ * @returns 形如 `PostgreSQL 17.x ...` 的版本串
101
+ */
102
+ version(): Promise<string>;
103
+ /**
104
+ * 在 host 的一致快照上逐项读取数据目录(US-217)。
105
+ *
106
+ * @remarks
107
+ * host 在本会话那条唯一连接上开事务并 `CHECKPOINT`,`fn` 返回之前一直占着它:没有写入能落进
108
+ * 正在读的文件,快照边界前已提交的 WAL 也都已落进数据文件(AC#16)。
109
+ *
110
+ * - **独占**:整段排在本地互斥里,同一客户端的其他语句等快照结束再发。否则它们在 host 上
111
+ * 排在快照后面,而快照又在等 renderer 来取下一块——两边互等。
112
+ * - **背压**:`items` 每被取一项才发一次 `pg.backup.next`,同一时刻至多一个在途请求,
113
+ * renderer 不取,host 就不读下一块(AC#21)。
114
+ * - **收尾**:无论 `fn` 读完、提前返回还是抛出,都发 `pg.backup.end` 交还连接(AC#19)。
115
+ * `fn` 失败时收尾失败不覆盖原始错误;`fn` 成功而收尾失败则整体失败——快照没结束的
116
+ * 备份不能报成功。
117
+ *
118
+ * 等连接空闲的上限沿用构造参数里的 `beginTimeout`(与 `pg.begin` 同档):契约方法不带
119
+ * 备份选项,`lockTimeoutMs` 传不到这里;到期由 host 以 `transaction_unavailable` 拒绝。
120
+ *
121
+ * @param fn - 消费快照的回调;`items` 只在回调返回之前有效
122
+ * @returns 回调的返回值
123
+ * @throws {@link RxDBAdapterDesktopError} 会话已关闭、host 不带备份能力(`unsupported_operation`)、
124
+ * 等不到连接或收尾失败时;`fn` 抛出的错误原样重抛
125
+ */
126
+ snapshotDataDir<T>(fn: (items: AsyncIterable<PGliteDataDirItem>) => Promise<T>): Promise<T>;
127
+ /**
128
+ * 断开会话。
129
+ *
130
+ * @remarks
131
+ * 等在途请求与开着的事务跑完再关,因此调用方返回时 host 上确实已经没有本会话的
132
+ * 任何残留。并发调用共享同一个关闭流程。
133
+ */
134
+ disconnect(): Promise<void>;
135
+ /**
136
+ * 不等在途请求,直接让 host 释放本会话。
137
+ *
138
+ * @remarks
139
+ * host 收到 `pg.close` 会把本会话仍开着的事务全部回滚,因此「不等」丢掉的只是那些
140
+ * 未提交的写——这正是 `forceClose` 与 {@link DesktopPGliteClient.disconnect} 的区别。
141
+ */
142
+ forceClose(): Promise<void>;
143
+ }
144
+ //# sourceMappingURL=desktop-pglite-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"desktop-pglite-client.d.ts","sourceRoot":"","sources":["../../src/pglite/desktop-pglite-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAQL,KAAK,oBAAoB,EAK1B,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAQ/E,yCAAyC;AACzC,MAAM,WAAW,0BAA0B;IACzC,iCAAiC;IACjC,QAAQ,CAAC,SAAS,EAAE,oBAAoB,CAAC;IACzC,0CAA0C;IAC1C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,6CAA6C;IAC7C,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAgED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,mBAAoB,SAAQ,eAAe,CAAC,kBAAkB,CAAE,YAAW,aAAa;;IAcnG,+CAA+C;IAC/C,IAAI,SAAS,IAAI,MAAM,CAKtB;IAED,gCAAgC;IAChC,IAAI,gBAAgB,IAAI,MAAM,CAK7B;IAED,0BAA0B;IAC1B,IAAI,wBAAwB,IAAI,MAAM,CAErC;gBAEW,OAAO,EAAE,0BAA0B;IAW/C;;;;;;;;;;;;;OAaG;IACG,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BvE;;;;;;;;OAQG;IACG,KAAK,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAM9F;;;;;;;OAOG;IACG,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAMzF;;;;;;;OAOG;IACG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAMrE;;;;;;;;;;;OAWG;IACG,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAK3E;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAShC;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACG,eAAe,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,aAAa,CAAC,iBAAiB,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAgCjG;;;;;;OAMG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAKjC;;;;;;OAMG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAiPlC"}
@@ -0,0 +1,14 @@
1
+ import { DesktopPgliteQueryResult } from '@aiao/rxdb-adapter-sqlite-core/desktop-host';
2
+ import { Results } from '@electric-sql/pglite';
3
+ /**
4
+ * 把 host 的应答还原成 PGlite 的 `Results`。
5
+ *
6
+ * @remarks
7
+ * `rows` 里的值已经是 PG 的原生 JS 表示(bigint / `Uint8Array` / `Date` / 普通对象),
8
+ * 结构化克隆逐值搬过来,这里不做任何再解析——多一层转换就多一处能悄悄丢精度的地方。
9
+ *
10
+ * @param result - 已通过协议校验的查询结果
11
+ * @returns 与浏览器路径同形状的结果
12
+ */
13
+ export declare const toDesktopPGliteResults: <T>(result: DesktopPgliteQueryResult) => Results<T>;
14
+ //# sourceMappingURL=desktop-pglite-results.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"desktop-pglite-results.d.ts","sourceRoot":"","sources":["../../src/pglite/desktop-pglite-results.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AAC5F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD;;;;;;;;;GASG;AACH,eAAO,MAAM,sBAAsB,GAAI,CAAC,EAAE,QAAQ,wBAAwB,KAAG,OAAO,CAAC,CAAC,CAIpF,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { RxDBBackupError } from '@aiao/rxdb';
2
+ /** 备份读源库,恢复写目标库;同一个桌面错误码在两个方向上的归因不同。 */
3
+ export type ElectronPGliteBackupDirection = 'backup' | 'restore';
4
+ /**
5
+ * 把桌面 PGlite 备份 / 恢复途中的任意失败归一成 {@link RxDBBackupError}。
6
+ *
7
+ * @remarks
8
+ * 备份与恢复的公共契约只认 `RxDBBackupError.code`;桌面错误码属于 host 线协议,漏到调用方手里,
9
+ * 按契约写的 `switch (error.code)` 就会静默落进 default。已经是 `RxDBBackupError` 的原样返回;
10
+ * 其余一律带着原始错误作为 `cause`:
11
+ *
12
+ * | 桌面错误码 | 备份契约 |
13
+ * | --- | --- |
14
+ * | `database_busy` | `target_busy` |
15
+ * | `restore_in_progress` / `restore_incomplete` / `target_not_empty` / `cleanup_pending` | 同名码 |
16
+ * | `protocol_violation` | `unsupported_combination`(`details.field` 为 `protocolVersion`) |
17
+ * | `unsupported_operation` / `unsupported_runtime_engine` / `invalid_database_name` | `unsupported_combination` |
18
+ * | `disk_full` | `storage_full` |
19
+ * | `transaction_unavailable` | `lock_timeout` |
20
+ * | `session_closed` | `invalid_state` |
21
+ * | `database_corrupted` | 恢复为 `corrupt_archive`,备份为 `io_error` |
22
+ * | 其余桌面错误及非桌面错误 | `io_error` |
23
+ *
24
+ * 目标状态类的码(前两行)`details` 为 `{ field: 'dataDirectoryName', actual: 目录名 }`。
25
+ *
26
+ * @param error - 捕获到的任意值
27
+ * @param dataDirectoryName - 本次操作的数据目录名
28
+ * @param direction - 发生在备份还是恢复
29
+ * @returns 归一后的备份错误
30
+ */
31
+ export declare const toElectronPGliteBackupError: (error: unknown, dataDirectoryName: string, direction: ElectronPGliteBackupDirection) => RxDBBackupError;
32
+ //# sourceMappingURL=electron-pglite-backup-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"electron-pglite-backup-error.d.ts","sourceRoot":"","sources":["../../src/pglite/electron-pglite-backup-error.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAyD,MAAM,YAAY,CAAC;AAOpG,wCAAwC;AACxC,MAAM,MAAM,6BAA6B,GAAG,QAAQ,GAAG,SAAS,CAAC;AA8EjE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,2BAA2B,GACtC,OAAO,OAAO,EACd,mBAAmB,MAAM,EACzB,WAAW,6BAA6B,KACvC,eAIF,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { DesktopHostTransport } from '@aiao/rxdb-adapter-sqlite-core/desktop-host';
2
+ /**
3
+ * 适配器在 `RxDBAdapters` 注册表中的名字。
4
+ *
5
+ * @remarks
6
+ * 与 `sqlite-electron` 并列,同一个 Electron 运行时上两个适配器可以同时注册
7
+ * (US-207 已为此把 SQLite 侧的名字从 `electron` 改成了 `sqlite-electron`)。
8
+ *
9
+ * 这里**刻意不写** `satisfies DesktopHostAdapterName`:那份登记表是「走 SQLite host
10
+ * 协议的适配器」的清单,PGlite 走的是另一族协议(`pg.*`)。硬套上去会让共享层的
11
+ * 存储联合把 `pglite-electron` 也当成能接受 `DesktopSqliteFileStorage` 的适配器。
12
+ */
13
+ export declare const ADAPTER_NAME: "pglite-electron";
14
+ /**
15
+ * 逻辑数据目录名的默认后缀。
16
+ *
17
+ * @remarks
18
+ * 与 SQLite 侧的 `DEFAULT_DATABASE_SUFFIX` 同构,但后缀不同:PGlite 落盘的是一棵
19
+ * initdb 生成的**目录树**而不是单个文件,用 `.db` 之类的文件后缀命名只会误导运维。
20
+ */
21
+ export declare const DEFAULT_DATA_DIRECTORY_SUFFIX = "-pgdata";
22
+ /** {@link RxDBAdapterElectronPGlite} 的构造选项。 */
23
+ export interface ElectronPGliteOptions {
24
+ /**
25
+ * 传输层;省略时从 `globalThis` 上读取 preload 注入的那一份。
26
+ *
27
+ * @remarks
28
+ * 显式传入主要供测试与非 Electron 宿主使用,见
29
+ * {@link @aiao/rxdb-adapter-sqlite-core/desktop-host#resolveDesktopHostTransport}。
30
+ */
31
+ readonly transport?: DesktopHostTransport;
32
+ /**
33
+ * 应用作用域内的逻辑数据目录名;省略时为 `<dbName>-pgdata`。
34
+ *
35
+ * @remarks
36
+ * 只能是名字,不能是路径:物理根目录由主进程决定,renderer 既拿不到也不需要
37
+ * (AC#5)。含路径分隔符时在构造期就抛 `invalid_database_name`。
38
+ */
39
+ readonly dataDirectoryName?: string;
40
+ /**
41
+ * `pg.begin` 等待主进程那条唯一连接的上限(毫秒)。
42
+ *
43
+ * @remarks
44
+ * 省略时用协议默认值 `DESKTOP_PGLITE_DEFAULT_BEGIN_TIMEOUT_MS`。它约束的是**跨窗口**
45
+ * 的竞争:同一个客户端内部的事务由本地互斥串行化,根本不会互相超时。
46
+ */
47
+ readonly beginTimeout?: number;
48
+ /**
49
+ * NOTIFY 批量窗口(毫秒);省略时用 `DEFAULT_NOTIFY_BATCH_TIMEOUT_MS`。
50
+ *
51
+ * @remarks
52
+ * 与浏览器路径同义、同实现——批量发生在渲染进程,主进程只转发裸 NOTIFY。
53
+ */
54
+ readonly batchTimeout?: number;
55
+ }
56
+ /**
57
+ * 解析实例对应的逻辑数据目录名。
58
+ *
59
+ * @remarks
60
+ * 适配器连接与恢复入口必须算出同一个名字:恢复写进的目录就是之后 `connect` 打开的目录,两处各写一遍
61
+ * 默认规则迟早会分叉。
62
+ *
63
+ * @param dbName - `rxdb.config.dbName`
64
+ * @param options - 适配器选项;只读取 `dataDirectoryName`
65
+ * @returns 显式给出的名字,否则为 `<dbName>-pgdata`;不做校验
66
+ */
67
+ export declare const resolveDataDirectoryName: (dbName: string, options: ElectronPGliteOptions) => string;
68
+ //# sourceMappingURL=pglite-adapter.interface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pglite-adapter.interface.d.ts","sourceRoot":"","sources":["../../src/pglite/pglite-adapter.interface.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6CAA6C,CAAC;AAExF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,EAAG,iBAA0B,CAAC;AAEvD;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,YAAY,CAAC;AAEvD,+CAA+C;AAC/C,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,oBAAoB,CAAC;IAC1C;;;;;;OAMG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GAAI,QAAQ,MAAM,EAAE,SAAS,qBAAqB,KAAG,MAChB,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { RxDB, RxDBRestoreResult } from '@aiao/rxdb';
2
+ import { PGliteRestoreOptions } from '@aiao/rxdb-adapter-pglite';
3
+ import { ElectronPGliteOptions } from './pglite-adapter.interface.js';
4
+ /**
5
+ * 恢复目标:一个**尚未连接**的 RxDB 实例,加上它将来连接时交给
6
+ * {@link RxDBAdapterElectronPGlite} 的同一份选项。
7
+ *
8
+ * @remarks
9
+ * 数据目录名、传输层、实体结构指纹与加密认证域都按这份配置判定;与之后连接时的选项不一致,
10
+ * 恢复出来的库就会落在另一个目录,或者被判成不兼容。
11
+ */
12
+ export interface ElectronPGliteRestoreTarget {
13
+ readonly rxdb: RxDB;
14
+ readonly options: ElectronPGliteOptions;
15
+ }
16
+ /**
17
+ * 把 {@link RxDBAdapterElectronPGlite.backup} 产出的归档恢复进 host 上的一个新数据目录。
18
+ *
19
+ * @remarks
20
+ * 只写入**空**目标,不做合并或覆盖。步骤:
21
+ *
22
+ * 1. 在读取归档之前拒绝已连接的目标实例(`target_busy`,`details.field` 为 `rxdb`)、协议版本不一致
23
+ * 或未启用备份的 host(`unsupported_combination`)。
24
+ * 2. host **先**取得目录的独占权,**再**检查未完成标记与空状态;独占一直保持到提交或失败处理结束,
25
+ * 期间其他窗口的 `connect`、其他恢复与清理请求都被拒绝。
26
+ * 3. 读 manifest,在写入第一个字节之前判定兼容性:适配器、引擎大版本、扩展(目标 host 必须全部提供)、
27
+ * 系统表 / 变更编码版本、实体结构指纹与加密认证域(`incompatible_archive` /
28
+ * `auth_domain_mismatch`)。
29
+ * 4. host 持久化未完成标记,归档逐项写进目录;读到结尾、摘要通过后才在私有实例上启动 PostgreSQL,
30
+ * 核对引擎与系统表水位,关闭实例并逐一 fsync,最后删除标记、交还独占。
31
+ *
32
+ * 任一步失败都由 host 删除目录与标记,目标回到从未恢复过的状态;连这一步也失败时报
33
+ * `cleanup_pending`,调 {@link cleanupIncompleteElectronPGliteRestore} 重试。恢复途中窗口或进程
34
+ * 退出时标记留在盘上,下一次连接以 `restore_incomplete` 拒绝,同样用它清理后再恢复。
35
+ *
36
+ * 归档只含数据库:结果与 manifest 的 `scope.externalFiles` 恒为 `excluded`,外置文件须另行备份恢复。
37
+ * 输入流在失败时被取消,成功时只释放读锁。桌面错误码按 {@link toElectronPGliteBackupError} 归一。
38
+ *
39
+ * @param source - 归档字节流
40
+ * @param target - 尚未连接的目标实例与其 adapter 选项
41
+ * @param options - 取消信号与阶段回调;四个阶段都会触发
42
+ * @returns 结束标记(条目数、字节数、SHA-256)、manifest 与范围
43
+ * @throws RxDBBackupError `target_busy` / `target_not_empty` / `restore_in_progress` / `restore_incomplete` /
44
+ * `unsupported_combination` / `incompatible_archive` / `auth_domain_mismatch` / `corrupt_archive` /
45
+ * `truncated_archive` / `aborted` / `io_error` / `storage_full` / `cleanup_pending`
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const target = { rxdb, options: {} };
50
+ * await restoreElectronPGliteDatabase(file.stream(), target);
51
+ * rxdb.adapter(ELECTRON_PGLITE_ADAPTER_NAME, db => new RxDBAdapterElectronPGlite(db, target.options));
52
+ * await rxdb.connect(ELECTRON_PGLITE_ADAPTER_NAME);
53
+ * ```
54
+ */
55
+ export declare const restoreElectronPGliteDatabase: (source: ReadableStream<Uint8Array>, target: ElectronPGliteRestoreTarget, options?: PGliteRestoreOptions) => Promise<RxDBRestoreResult>;
56
+ /**
57
+ * 清理一次没做完的恢复(窗口或进程在恢复中途退出、或恢复失败后清理本身也失败)。
58
+ *
59
+ * @remarks
60
+ * host 先取目录的独占权:目录正被打开或正在恢复时报 `target_busy`,从不删别人正在用的库。
61
+ * 没有未完成标记时什么都不做——一个正常的库永远不会被这里删掉。
62
+ *
63
+ * @param target - 恢复时使用的同一个目标
64
+ * @returns 确实清理了残留时为 `true`
65
+ * @throws RxDBBackupError `target_busy` / `unsupported_combination` / `cleanup_pending`
66
+ */
67
+ export declare const cleanupIncompleteElectronPGliteRestore: (target: ElectronPGliteRestoreTarget) => Promise<boolean>;
68
+ //# sourceMappingURL=restore-electron-pglite-database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restore-electron-pglite-database.d.ts","sourceRoot":"","sources":["../../src/pglite/restore-electron-pglite-database.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAQL,KAAK,IAAI,EAKT,KAAK,iBAAiB,EACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAKL,KAAK,oBAAoB,EAC1B,MAAM,2BAA2B,CAAC;AAkBnC,OAAO,EAA0C,KAAK,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEnH;;;;;;;GAOG;AACH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;CACzC;AAqRD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,6BAA6B,GACxC,QAAQ,cAAc,CAAC,UAAU,CAAC,EAClC,QAAQ,2BAA2B,EACnC,UAAS,oBAAyB,KACjC,OAAO,CAAC,iBAAiB,CAc3B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,sCAAsC,GAAU,QAAQ,2BAA2B,KAAG,OAAO,CAAC,OAAO,CAuBjH,CAAC"}