@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
package/src/pglite.ts ADDED
@@ -0,0 +1,51 @@
1
+ /**
2
+ * `@aiao/rxdb-adapter-electron` 的 **PGlite renderer 侧**入口。
3
+ *
4
+ * @remarks
5
+ * 与默认入口分开而不是并进去,理由是依赖:默认入口只要共享层,本入口却要
6
+ * `@aiao/rxdb-adapter-pglite` 这个可选 peer。合并的话,任何一个只用 SQLite 的应用
7
+ * 都会在 import 适配器时撞上「找不到 `@aiao/rxdb-adapter-pglite`」——而它压根没打算用 PGlite。
8
+ *
9
+ * 本入口**不引用 PostgreSQL 运行时**:WASM 实例活在主进程,renderer 这边只有一层协议
10
+ * 代理,从 `@electric-sql/pglite` 拿的只有类型和 `/template` 那个约 2 KB 的模板编译子路径,
11
+ * 因此 bundle 里不会多出几十兆的 PostgreSQL。特权侧请用
12
+ * `@aiao/rxdb-adapter-electron/pglite-host`。
13
+ *
14
+ * @module @aiao/rxdb-adapter-electron/pglite
15
+ */
16
+
17
+ export {
18
+ DEFAULT_DATA_DIRECTORY_SUFFIX as DESKTOP_DEFAULT_DATA_DIRECTORY_SUFFIX,
19
+ ADAPTER_NAME as ELECTRON_PGLITE_ADAPTER_NAME,
20
+ type ElectronPGliteOptions
21
+ } from './pglite/pglite-adapter.interface.js';
22
+
23
+ export { RxDBAdapterElectronPGlite } from './pglite/RxDBAdapterElectronPGlite.js';
24
+
25
+ export { DesktopPGliteClient, type DesktopPGliteClientOptions } from './pglite/desktop-pglite-client.js';
26
+
27
+ // 备份在 adapter 上;恢复的目标还没连接、没有 adapter 可调,只能是自由函数。
28
+ // 选项与阶段沿用浏览器 PGlite 的类型,一并转出,调用方不必为签名再去 import 那个 peer。
29
+ export type { PGliteRestoreOptions, PGliteRestoreStage } from '@aiao/rxdb-adapter-pglite';
30
+ export {
31
+ cleanupIncompleteElectronPGliteRestore,
32
+ restoreElectronPGliteDatabase,
33
+ type ElectronPGliteRestoreTarget
34
+ } from './pglite/restore-electron-pglite-database.js';
35
+
36
+ // 协议常量与错误类型原样转出,理由与默认入口一致:下游按名字 import,
37
+ // 实现搬到哪个共享包不该让用户改行。
38
+ export {
39
+ DESKTOP_HOST_TRANSPORT_KEY,
40
+ DESKTOP_PGLITE_DEFAULT_BEGIN_TIMEOUT_MS,
41
+ DESKTOP_PGLITE_MAX_BEGIN_TIMEOUT_MS,
42
+ DESKTOP_PGLITE_PROTOCOL_VERSION,
43
+ RxDBAdapterDesktopError,
44
+ resolveDesktopHostTransport,
45
+ type DesktopHostTransport,
46
+ type DesktopPgliteNotifyMessage,
47
+ type DesktopPgliteQueryResult,
48
+ type DesktopPgliteRequest,
49
+ type DesktopPgliteResponse,
50
+ type RxDBAdapterDesktopErrorCode
51
+ } from '@aiao/rxdb-adapter-sqlite-core/desktop-host';
@@ -0,0 +1,134 @@
1
+ /**
2
+ * SQL 脚本切分。
3
+ *
4
+ * @remarks
5
+ * wasm 后端能拿到 `sqlite3_prepare_v3` 的 `pzTail`,由 SQLite 自己逐条吐出语句;`node:sqlite`
6
+ * 没有对应出口——`prepare()` 只编译第一条语句并**静默丢掉**后面所有语句,`exec()` 跑完整个脚本
7
+ * 却不返回任何结果集。多语句脚本里带 `RETURNING` 的那条因此会人间蒸发(分支切换正是这个形状)。
8
+ *
9
+ * 所以切分只能自己做。状态机逐字搬自 SQLite 的 `complete.c`(即 `sqlite3_complete()` 的实现),
10
+ * 与 SQLite 对「一条语句到哪里结束」的判断同源;自己发明规则迟早会在触发器体或字符串字面量上分叉。
11
+ *
12
+ * @module sqlite-script
13
+ */
14
+
15
+ const TOKEN_SEMI = 0;
16
+ const TOKEN_WS = 1;
17
+ const TOKEN_OTHER = 2;
18
+ const TOKEN_EXPLAIN = 3;
19
+ const TOKEN_CREATE = 4;
20
+ const TOKEN_TEMP = 5;
21
+ const TOKEN_TRIGGER = 6;
22
+ const TOKEN_END = 7;
23
+
24
+ /** 「刚好读完一条完整语句」的状态,即 `sqlite3_complete()` 的返回条件。 */
25
+ const STATE_COMPLETE = 1;
26
+
27
+ /**
28
+ * `complete.c` 的状态转移表。
29
+ *
30
+ * @remarks
31
+ * 行是状态(0 INVALID / 1 START / 2 NORMAL / 3 EXPLAIN / 4 CREATE / 5 TRIGGER / 6 SEMI / 7 END),
32
+ * 列是记号(SEMI / WS / OTHER / EXPLAIN / CREATE / TEMP / TRIGGER / END)。
33
+ * 状态 5、6 是 `CREATE [TEMP] TRIGGER` 的体内:这两行的 SEMI 列不回到 1,
34
+ * 触发器体内的分号因此不会被当成语句边界。
35
+ */
36
+ const TRANSITIONS: readonly (readonly number[])[] = [
37
+ [1, 0, 2, 3, 4, 2, 2, 2],
38
+ [1, 1, 2, 3, 4, 2, 2, 2],
39
+ [1, 2, 2, 2, 2, 2, 2, 2],
40
+ [1, 3, 3, 2, 4, 2, 2, 2],
41
+ [1, 4, 2, 2, 2, 4, 5, 2],
42
+ [6, 5, 5, 5, 5, 5, 5, 5],
43
+ [6, 6, 5, 5, 5, 5, 5, 7],
44
+ [1, 7, 5, 5, 5, 5, 5, 5]
45
+ ];
46
+
47
+ /** 只有这几个关键字会影响状态机,其余标识符一律是 OTHER。 */
48
+ const KEYWORD_TOKENS = new Map<string, number>([
49
+ ['create', TOKEN_CREATE],
50
+ ['temp', TOKEN_TEMP],
51
+ ['temporary', TOKEN_TEMP],
52
+ ['trigger', TOKEN_TRIGGER],
53
+ ['end', TOKEN_END],
54
+ ['explain', TOKEN_EXPLAIN]
55
+ ]);
56
+
57
+ const WHITESPACE = new Set([' ', '\t', '\n', '\r', '\f']);
58
+
59
+ /** 与 `complete.c` 的 `IdChar` 同集合:字母数字、`_`、`$`,以及一切非 ASCII 字符。 */
60
+ const ID_CHAR = /[A-Za-z0-9_$\u0080-\uFFFF]/u;
61
+
62
+ interface Lexeme {
63
+ readonly token: number;
64
+ /** 该记号之后的下一个下标。 */
65
+ readonly next: number;
66
+ }
67
+
68
+ /**
69
+ * 读出 `index` 处的记号。
70
+ *
71
+ * @remarks
72
+ * 引号不做转义处理,与 `complete.c` 一致:`'a''b'` 会被读成两个相邻的字符串记号,
73
+ * 落到状态机上与读成一个完全等价,因此不必额外分支。
74
+ * 未闭合的引号 / 注释 / 方括号一路吃到串尾,让 SQLite 在 prepare 时报语法错。
75
+ */
76
+ const readToken = (sql: string, index: number): Lexeme => {
77
+ const char = sql[index];
78
+ if (char === ';') return { token: TOKEN_SEMI, next: index + 1 };
79
+ if (WHITESPACE.has(char)) return { token: TOKEN_WS, next: index + 1 };
80
+ if (char === '/' && sql[index + 1] === '*') return { token: TOKEN_WS, next: closingIndex(sql, index + 2, '*/') };
81
+ if (char === '-' && sql[index + 1] === '-') return { token: TOKEN_WS, next: closingIndex(sql, index + 2, '\n') };
82
+ if (char === '[') return { token: TOKEN_OTHER, next: closingIndex(sql, index + 1, ']') };
83
+ if (char === '"' || char === "'" || char === '`') {
84
+ return { token: TOKEN_OTHER, next: closingIndex(sql, index + 1, char) };
85
+ }
86
+ if (!ID_CHAR.test(char)) return { token: TOKEN_OTHER, next: index + 1 };
87
+ const end = identifierEnd(sql, index + 1);
88
+ return { token: KEYWORD_TOKENS.get(sql.slice(index, end).toLowerCase()) ?? TOKEN_OTHER, next: end };
89
+ };
90
+
91
+ /** 闭合符之后的下标;没有闭合符时返回串尾。 */
92
+ const closingIndex = (sql: string, from: number, closing: string): number => {
93
+ const found = sql.indexOf(closing, from);
94
+ return found === -1 ? sql.length : found + closing.length;
95
+ };
96
+
97
+ const identifierEnd = (sql: string, from: number): number => {
98
+ let end = from;
99
+ while (end < sql.length && ID_CHAR.test(sql[end])) end++;
100
+ return end;
101
+ };
102
+
103
+ /**
104
+ * 把一段可能含多条语句的 SQL 脚本切成单条语句。
105
+ *
106
+ * @remarks
107
+ * 切片保留原文(含语句间的空白与注释),因此把结果按顺序拼回去与原串等价,
108
+ * 报错信息里的 SQL 也仍是调用方写的那一份。只含空白或注释的片段不会成为语句——
109
+ * 它们 prepare 出来是空语句,`node:sqlite` 会直接抛错。
110
+ *
111
+ * @param sql - 一条或多条 SQL 组成的脚本
112
+ * @returns 按出现顺序排列的语句原文;脚本里没有实质语句时为空数组
113
+ */
114
+ export function splitSqliteScript(sql: string): string[] {
115
+ const statements: string[] = [];
116
+ let state = 0;
117
+ let start = 0;
118
+ let index = 0;
119
+ let meaningful = false;
120
+
121
+ while (index < sql.length) {
122
+ const { token, next } = readToken(sql, index);
123
+ state = TRANSITIONS[state][token];
124
+ index = next;
125
+ if (token !== TOKEN_WS && token !== TOKEN_SEMI) meaningful = true;
126
+ if (token !== TOKEN_SEMI || state !== STATE_COMPLETE) continue;
127
+ if (meaningful) statements.push(sql.slice(start, index));
128
+ meaningful = false;
129
+ start = index;
130
+ }
131
+
132
+ if (meaningful) statements.push(sql.slice(start));
133
+ return statements;
134
+ }