@framers/sql-storage-adapter 0.7.2 → 0.7.4

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 (194) hide show
  1. package/README.md +41 -0
  2. package/dist/adapters/electron/preload.cjs +289 -0
  3. package/dist/adapters/electron/renderer.d.ts +9 -0
  4. package/dist/adapters/electron/renderer.d.ts.map +1 -0
  5. package/dist/adapters/electron/renderer.js +8 -0
  6. package/dist/adapters/electron/renderer.js.map +1 -0
  7. package/dist/cjs/adapters/__tests__/indexedDbAdapter.spec.d.ts +2 -0
  8. package/dist/cjs/adapters/__tests__/indexedDbAdapter.spec.js +133 -0
  9. package/dist/cjs/adapters/baseStorageAdapter.d.ts +368 -0
  10. package/dist/cjs/adapters/baseStorageAdapter.js +744 -0
  11. package/dist/cjs/adapters/betterSqliteAdapter.d.ts +124 -0
  12. package/dist/cjs/adapters/betterSqliteAdapter.js +334 -0
  13. package/dist/cjs/adapters/capacitorSqliteAdapter.d.ts +83 -0
  14. package/dist/cjs/adapters/capacitorSqliteAdapter.js +250 -0
  15. package/dist/cjs/adapters/electron/electronMainAdapter.d.ts +251 -0
  16. package/dist/cjs/adapters/electron/electronMainAdapter.js +392 -0
  17. package/dist/cjs/adapters/electron/electronRendererAdapter.d.ts +177 -0
  18. package/dist/cjs/adapters/electron/electronRendererAdapter.js +283 -0
  19. package/dist/cjs/adapters/electron/index.d.ts +74 -0
  20. package/dist/cjs/adapters/electron/index.js +86 -0
  21. package/dist/cjs/adapters/electron/ipc/channels.d.ts +196 -0
  22. package/dist/cjs/adapters/electron/ipc/channels.js +127 -0
  23. package/dist/cjs/adapters/electron/ipc/index.d.ts +11 -0
  24. package/dist/cjs/adapters/electron/ipc/index.js +38 -0
  25. package/dist/cjs/adapters/electron/ipc/protocol.d.ts +78 -0
  26. package/dist/cjs/adapters/electron/ipc/protocol.js +341 -0
  27. package/dist/cjs/adapters/electron/ipc/types.d.ts +248 -0
  28. package/dist/cjs/adapters/electron/ipc/types.js +15 -0
  29. package/dist/cjs/adapters/electron/migration/autoMigrator.d.ts +184 -0
  30. package/dist/cjs/adapters/electron/migration/autoMigrator.js +441 -0
  31. package/dist/cjs/adapters/electron/migration/index.d.ts +9 -0
  32. package/dist/cjs/adapters/electron/migration/index.js +29 -0
  33. package/dist/cjs/adapters/electron/preload.d.ts +126 -0
  34. package/dist/cjs/adapters/electron/preload.js +233 -0
  35. package/dist/cjs/adapters/electron/recovery/corruptionDetector.d.ts +214 -0
  36. package/dist/cjs/adapters/electron/recovery/corruptionDetector.js +359 -0
  37. package/dist/cjs/adapters/electron/recovery/index.d.ts +11 -0
  38. package/dist/cjs/adapters/electron/recovery/index.js +34 -0
  39. package/dist/cjs/adapters/electron/recovery/walCheckpoint.d.ts +186 -0
  40. package/dist/cjs/adapters/electron/recovery/walCheckpoint.js +263 -0
  41. package/dist/cjs/adapters/electron/renderer.d.ts +9 -0
  42. package/dist/cjs/adapters/electron/renderer.js +33 -0
  43. package/dist/cjs/adapters/electron/window/index.d.ts +9 -0
  44. package/dist/cjs/adapters/electron/window/index.js +29 -0
  45. package/dist/cjs/adapters/electron/window/windowManager.d.ts +190 -0
  46. package/dist/cjs/adapters/electron/window/windowManager.js +321 -0
  47. package/dist/cjs/adapters/indexedDbAdapter.d.ts +490 -0
  48. package/dist/cjs/adapters/indexedDbAdapter.js +993 -0
  49. package/dist/cjs/adapters/postgresAdapter.d.ts +424 -0
  50. package/dist/cjs/adapters/postgresAdapter.js +889 -0
  51. package/dist/cjs/adapters/sqlJsAdapter.d.ts +64 -0
  52. package/dist/cjs/adapters/sqlJsAdapter.js +268 -0
  53. package/dist/cjs/adapters/supabase.d.ts +58 -0
  54. package/dist/cjs/adapters/supabase.js +401 -0
  55. package/dist/cjs/codecs/BrowserBlobCodec.d.ts +14 -0
  56. package/dist/cjs/codecs/BrowserBlobCodec.js +57 -0
  57. package/dist/cjs/codecs/NodeBlobCodec.d.ts +14 -0
  58. package/dist/cjs/codecs/NodeBlobCodec.js +59 -0
  59. package/dist/cjs/core/contracts/blobCodec.d.ts +15 -0
  60. package/dist/cjs/core/contracts/blobCodec.js +15 -0
  61. package/dist/cjs/core/contracts/context.d.ts +221 -0
  62. package/dist/cjs/core/contracts/context.js +15 -0
  63. package/dist/cjs/core/contracts/dialect.d.ts +154 -0
  64. package/dist/cjs/core/contracts/dialect.js +15 -0
  65. package/dist/cjs/core/contracts/events.d.ts +225 -0
  66. package/dist/cjs/core/contracts/events.js +15 -0
  67. package/dist/cjs/core/contracts/exporter.d.ts +13 -0
  68. package/dist/cjs/core/contracts/exporter.js +15 -0
  69. package/dist/cjs/core/contracts/extensions.d.ts +73 -0
  70. package/dist/cjs/core/contracts/extensions.js +15 -0
  71. package/dist/cjs/core/contracts/features.d.ts +25 -0
  72. package/dist/cjs/core/contracts/features.js +61 -0
  73. package/dist/cjs/core/contracts/fts.d.ts +66 -0
  74. package/dist/cjs/core/contracts/fts.js +15 -0
  75. package/dist/cjs/core/contracts/hooks.d.ts +481 -0
  76. package/dist/cjs/core/contracts/hooks.js +140 -0
  77. package/dist/cjs/core/contracts/index.d.ts +260 -0
  78. package/dist/cjs/core/contracts/index.js +41 -0
  79. package/dist/cjs/core/contracts/limitations.d.ts +46 -0
  80. package/dist/cjs/core/contracts/limitations.js +218 -0
  81. package/dist/cjs/core/contracts/performance.d.ts +308 -0
  82. package/dist/cjs/core/contracts/performance.js +144 -0
  83. package/dist/cjs/core/database.d.ts +220 -0
  84. package/dist/cjs/core/database.js +136 -0
  85. package/dist/cjs/core/portable.d.ts +24 -0
  86. package/dist/cjs/core/portable.js +68 -0
  87. package/dist/cjs/core/resolver.d.ts +77 -0
  88. package/dist/cjs/core/resolver.js +235 -0
  89. package/dist/cjs/dialects/PostgresDialect.d.ts +35 -0
  90. package/dist/cjs/dialects/PostgresDialect.js +143 -0
  91. package/dist/cjs/dialects/SqliteDialect.d.ts +35 -0
  92. package/dist/cjs/dialects/SqliteDialect.js +142 -0
  93. package/dist/cjs/dialects/shared.d.ts +17 -0
  94. package/dist/cjs/dialects/shared.js +90 -0
  95. package/dist/cjs/exporters/PostgresExporter.d.ts +14 -0
  96. package/dist/cjs/exporters/PostgresExporter.js +61 -0
  97. package/dist/cjs/exporters/SqliteFileExporter.d.ts +16 -0
  98. package/dist/cjs/exporters/SqliteFileExporter.js +43 -0
  99. package/dist/cjs/features/auth/authJsAdapter.d.ts +110 -0
  100. package/dist/cjs/features/auth/authJsAdapter.js +251 -0
  101. package/dist/cjs/features/backup/cloudBackup.d.ts +219 -0
  102. package/dist/cjs/features/backup/cloudBackup.js +209 -0
  103. package/dist/cjs/features/kv/idb.d.ts +79 -0
  104. package/dist/cjs/features/kv/idb.js +32 -0
  105. package/dist/cjs/features/kv/index.d.ts +14 -0
  106. package/dist/cjs/features/kv/index.js +40 -0
  107. package/dist/cjs/features/kv/indexedDbKeyValueStore.d.ts +77 -0
  108. package/dist/cjs/features/kv/indexedDbKeyValueStore.js +116 -0
  109. package/dist/cjs/features/kv/keyValueStore.d.ts +48 -0
  110. package/dist/cjs/features/kv/keyValueStore.js +67 -0
  111. package/dist/cjs/features/kv/sqlKeyValueStore.d.ts +34 -0
  112. package/dist/cjs/features/kv/sqlKeyValueStore.js +81 -0
  113. package/dist/cjs/features/kv/valueCodec.d.ts +35 -0
  114. package/dist/cjs/features/kv/valueCodec.js +426 -0
  115. package/dist/cjs/features/migrations/dataExport.d.ts +77 -0
  116. package/dist/cjs/features/migrations/dataExport.js +194 -0
  117. package/dist/cjs/features/migrations/dataImport.d.ts +54 -0
  118. package/dist/cjs/features/migrations/dataImport.js +300 -0
  119. package/dist/cjs/features/migrations/migration.d.ts +89 -0
  120. package/dist/cjs/features/migrations/migration.js +187 -0
  121. package/dist/cjs/features/migrations/schemaMigrations.d.ts +93 -0
  122. package/dist/cjs/features/migrations/schemaMigrations.js +220 -0
  123. package/dist/cjs/features/sync/conflicts/conflictResolver.d.ts +222 -0
  124. package/dist/cjs/features/sync/conflicts/conflictResolver.js +366 -0
  125. package/dist/cjs/features/sync/conflicts/index.d.ts +9 -0
  126. package/dist/cjs/features/sync/conflicts/index.js +21 -0
  127. package/dist/cjs/features/sync/crossPlatformSync.d.ts +281 -0
  128. package/dist/cjs/features/sync/crossPlatformSync.js +551 -0
  129. package/dist/cjs/features/sync/devices/deviceManager.d.ts +243 -0
  130. package/dist/cjs/features/sync/devices/deviceManager.js +450 -0
  131. package/dist/cjs/features/sync/devices/index.d.ts +10 -0
  132. package/dist/cjs/features/sync/devices/index.js +21 -0
  133. package/dist/cjs/features/sync/index.d.ts +37 -0
  134. package/dist/cjs/features/sync/index.js +111 -0
  135. package/dist/cjs/features/sync/protocol/index.d.ts +11 -0
  136. package/dist/cjs/features/sync/protocol/index.js +23 -0
  137. package/dist/cjs/features/sync/protocol/messages.d.ts +348 -0
  138. package/dist/cjs/features/sync/protocol/messages.js +215 -0
  139. package/dist/cjs/features/sync/protocol/vectorClock.d.ts +164 -0
  140. package/dist/cjs/features/sync/protocol/vectorClock.js +256 -0
  141. package/dist/cjs/features/sync/syncManager.d.ts +348 -0
  142. package/dist/cjs/features/sync/syncManager.js +455 -0
  143. package/dist/cjs/features/sync/tables/index.d.ts +10 -0
  144. package/dist/cjs/features/sync/tables/index.js +21 -0
  145. package/dist/cjs/features/sync/tables/syncLogManager.d.ts +216 -0
  146. package/dist/cjs/features/sync/tables/syncLogManager.js +423 -0
  147. package/dist/cjs/features/sync/transport/httpTransport.d.ts +123 -0
  148. package/dist/cjs/features/sync/transport/httpTransport.js +346 -0
  149. package/dist/cjs/features/sync/transport/index.d.ts +12 -0
  150. package/dist/cjs/features/sync/transport/index.js +25 -0
  151. package/dist/cjs/features/sync/transport/transport.d.ts +259 -0
  152. package/dist/cjs/features/sync/transport/transport.js +163 -0
  153. package/dist/cjs/features/sync/transport/websocketTransport.d.ts +126 -0
  154. package/dist/cjs/features/sync/transport/websocketTransport.js +342 -0
  155. package/dist/cjs/fts/PostgresFts.d.ts +29 -0
  156. package/dist/cjs/fts/PostgresFts.js +77 -0
  157. package/dist/cjs/fts/SqliteFts5.d.ts +22 -0
  158. package/dist/cjs/fts/SqliteFts5.js +58 -0
  159. package/dist/cjs/index.d.ts +31 -0
  160. package/dist/cjs/index.js +103 -0
  161. package/dist/cjs/package.json +3 -0
  162. package/dist/cjs/shared/connectionGate.d.ts +94 -0
  163. package/dist/cjs/shared/connectionGate.js +77 -0
  164. package/dist/cjs/shared/errors.d.ts +23 -0
  165. package/dist/cjs/shared/errors.js +45 -0
  166. package/dist/cjs/shared/logger.d.ts +26 -0
  167. package/dist/cjs/shared/logger.js +40 -0
  168. package/dist/cjs/shared/parameterUtils.d.ts +16 -0
  169. package/dist/cjs/shared/parameterUtils.js +59 -0
  170. package/dist/cjs/shared/postgresTarget.d.ts +11 -0
  171. package/dist/cjs/shared/postgresTarget.js +30 -0
  172. package/dist/cjs/shared/segment.d.ts +43 -0
  173. package/dist/cjs/shared/segment.js +63 -0
  174. package/dist/cjs/shared/serializedTransaction.d.ts +14 -0
  175. package/dist/cjs/shared/serializedTransaction.js +74 -0
  176. package/dist/cjs/shared/splitSqlStatements.d.ts +27 -0
  177. package/dist/cjs/shared/splitSqlStatements.js +163 -0
  178. package/dist/cjs/shared/sqlPlaceholders.d.ts +48 -0
  179. package/dist/cjs/shared/sqlPlaceholders.js +263 -0
  180. package/dist/cjs/types/index.d.ts +29 -0
  181. package/dist/cjs/types/index.js +33 -0
  182. package/dist/core/portable.d.ts +24 -0
  183. package/dist/core/portable.d.ts.map +1 -0
  184. package/dist/core/portable.js +24 -0
  185. package/dist/core/portable.js.map +1 -0
  186. package/dist/features/auth/authJsAdapter.d.ts +110 -0
  187. package/dist/features/auth/authJsAdapter.d.ts.map +1 -0
  188. package/dist/features/auth/authJsAdapter.js +248 -0
  189. package/dist/features/auth/authJsAdapter.js.map +1 -0
  190. package/dist/index.d.ts +1 -0
  191. package/dist/index.d.ts.map +1 -1
  192. package/dist/index.js +1 -0
  193. package/dist/index.js.map +1 -1
  194. package/package.json +149 -24
@@ -0,0 +1,392 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var electronMainAdapter_exports = {};
29
+ __export(electronMainAdapter_exports, {
30
+ ElectronMainAdapter: () => ElectronMainAdapter,
31
+ createElectronMainAdapter: () => createElectronMainAdapter
32
+ });
33
+ module.exports = __toCommonJS(electronMainAdapter_exports);
34
+ var import_path = __toESM(require("path"));
35
+ var import_electron = require("electron");
36
+ var import_betterSqliteAdapter = require("../betterSqliteAdapter.js");
37
+ var import_protocol = require("./ipc/protocol.js");
38
+ var import_channels = require("./ipc/channels.js");
39
+ var import_segment = require("../../shared/segment.js");
40
+ const DEFAULT_WAL_CONFIG = {
41
+ enabled: true,
42
+ checkpointInterval: 3e5,
43
+ // 5 minutes
44
+ autoCheckpointPages: 1e3,
45
+ synchronous: "NORMAL"
46
+ };
47
+ const DEFAULT_RECOVERY_CONFIG = {
48
+ enabled: true,
49
+ checkOnOpen: true,
50
+ autoRepair: true,
51
+ integrityCheckTimeout: 3e4
52
+ };
53
+ const DEFAULT_MULTI_WINDOW_CONFIG = {
54
+ enabled: true,
55
+ broadcastChanges: true
56
+ };
57
+ class ElectronMainAdapter {
58
+ constructor(options) {
59
+ this.kind = "electron-main";
60
+ this.isInitialized = false;
61
+ this.walCheckpointTimer = null;
62
+ this.backupTimer = null;
63
+ this.options = options;
64
+ this.walConfig = { ...DEFAULT_WAL_CONFIG, ...options.wal };
65
+ this.recoveryConfig = { ...DEFAULT_RECOVERY_CONFIG, ...options.recovery };
66
+ this.multiWindowConfig = { ...DEFAULT_MULTI_WINDOW_CONFIG, ...options.multiWindow };
67
+ this.filePath = (0, import_segment.segmentFilePath)(options.filePath, options.segment);
68
+ this.innerAdapter = (0, import_betterSqliteAdapter.createBetterSqliteAdapter)(options.filePath, { segment: options.segment });
69
+ const baseCapabilities = new Set(this.innerAdapter.capabilities);
70
+ baseCapabilities.add("batch");
71
+ this.capabilities = baseCapabilities;
72
+ }
73
+ // ============================================================================
74
+ // Lifecycle Methods
75
+ // ============================================================================
76
+ /**
77
+ * Open the database and initialize all subsystems.
78
+ */
79
+ async open(openOptions) {
80
+ if (this.isInitialized) {
81
+ this.log("Already initialized, skipping open()");
82
+ return;
83
+ }
84
+ try {
85
+ await this.innerAdapter.open(openOptions);
86
+ if (this.recoveryConfig.enabled && this.recoveryConfig.checkOnOpen) {
87
+ await this.runIntegrityCheck();
88
+ }
89
+ if (this.walConfig.enabled) {
90
+ await this.configureWalMode();
91
+ this.startWalCheckpointTimer();
92
+ }
93
+ if (this.options.segment === void 0) {
94
+ (0, import_protocol.initializeIpcProtocol)(this);
95
+ }
96
+ if (this.options.backup?.enabled && this.options.backup.provider) {
97
+ this.startBackupScheduler();
98
+ }
99
+ this.isInitialized = true;
100
+ this.log("Electron Main Adapter initialized successfully");
101
+ } catch (error) {
102
+ this.log(`Failed to initialize: ${error}`);
103
+ throw error;
104
+ }
105
+ }
106
+ /**
107
+ * Close the database and cleanup all subsystems.
108
+ */
109
+ async close() {
110
+ if (!this.isInitialized) {
111
+ return;
112
+ }
113
+ try {
114
+ if (this.walCheckpointTimer) {
115
+ clearInterval(this.walCheckpointTimer);
116
+ this.walCheckpointTimer = null;
117
+ }
118
+ if (this.backupTimer) {
119
+ clearInterval(this.backupTimer);
120
+ this.backupTimer = null;
121
+ }
122
+ if (this.walConfig.enabled) {
123
+ await this.runWalCheckpoint();
124
+ }
125
+ if (this.options.segment === void 0) {
126
+ (0, import_protocol.disposeIpcProtocol)();
127
+ }
128
+ await this.innerAdapter.close();
129
+ this.isInitialized = false;
130
+ this.log("Electron Main Adapter closed");
131
+ } catch (error) {
132
+ this.log(`Error during close: ${error}`);
133
+ throw error;
134
+ }
135
+ }
136
+ // ============================================================================
137
+ // Storage Adapter Interface
138
+ // ============================================================================
139
+ async run(statement, parameters) {
140
+ const result = await this.innerAdapter.run(statement, parameters);
141
+ if (this.multiWindowConfig.enabled && this.multiWindowConfig.broadcastChanges) {
142
+ this.broadcastChange({
143
+ type: this.detectMutationType(statement),
144
+ tables: this.extractTables(statement),
145
+ changes: result.changes,
146
+ timestamp: Date.now()
147
+ });
148
+ }
149
+ return result;
150
+ }
151
+ async get(statement, parameters) {
152
+ return this.innerAdapter.get(statement, parameters);
153
+ }
154
+ async all(statement, parameters) {
155
+ return this.innerAdapter.all(statement, parameters);
156
+ }
157
+ async exec(script) {
158
+ await this.innerAdapter.exec(script);
159
+ if (this.multiWindowConfig.enabled && this.multiWindowConfig.broadcastChanges) {
160
+ this.broadcastChange({
161
+ type: "transaction",
162
+ tables: [],
163
+ changes: 0,
164
+ timestamp: Date.now()
165
+ });
166
+ }
167
+ }
168
+ async transaction(fn) {
169
+ const result = await this.innerAdapter.transaction(fn);
170
+ if (this.multiWindowConfig.enabled && this.multiWindowConfig.broadcastChanges) {
171
+ this.broadcastChange({
172
+ type: "transaction",
173
+ tables: [],
174
+ changes: 0,
175
+ timestamp: Date.now()
176
+ });
177
+ }
178
+ return result;
179
+ }
180
+ async batch(operations) {
181
+ if (!this.innerAdapter.batch) {
182
+ throw new Error("Batch operations not supported");
183
+ }
184
+ const result = await this.innerAdapter.batch(operations);
185
+ if (this.multiWindowConfig.enabled && this.multiWindowConfig.broadcastChanges) {
186
+ this.broadcastChange({
187
+ type: "transaction",
188
+ tables: operations.flatMap((op) => this.extractTables(op.statement)),
189
+ changes: result.successful,
190
+ timestamp: Date.now()
191
+ });
192
+ }
193
+ return result;
194
+ }
195
+ prepare(statement) {
196
+ if (!this.innerAdapter.prepare) {
197
+ throw new Error("Prepared statements not supported");
198
+ }
199
+ return this.innerAdapter.prepare(statement);
200
+ }
201
+ // ============================================================================
202
+ // WAL Management
203
+ // ============================================================================
204
+ /**
205
+ * Configure WAL mode on the database.
206
+ */
207
+ async configureWalMode() {
208
+ await this.innerAdapter.exec(`
209
+ PRAGMA journal_mode = WAL;
210
+ PRAGMA synchronous = ${this.walConfig.synchronous};
211
+ PRAGMA wal_autocheckpoint = ${this.walConfig.autoCheckpointPages};
212
+ `);
213
+ this.log("WAL mode configured");
214
+ }
215
+ /**
216
+ * Start the WAL checkpoint timer.
217
+ */
218
+ startWalCheckpointTimer() {
219
+ if (this.walCheckpointTimer) {
220
+ clearInterval(this.walCheckpointTimer);
221
+ }
222
+ this.walCheckpointTimer = setInterval(() => this.runWalCheckpoint().catch((err) => this.log(`WAL checkpoint error: ${err}`)), this.walConfig.checkpointInterval);
223
+ }
224
+ /**
225
+ * Run a WAL checkpoint.
226
+ */
227
+ async runWalCheckpoint() {
228
+ const result = await this.innerAdapter.get("PRAGMA wal_checkpoint(PASSIVE)");
229
+ const checkpointResult = {
230
+ framesCheckpointed: result?.checkpointed ?? 0,
231
+ totalFrames: result?.log ?? 0
232
+ };
233
+ this.log(`WAL checkpoint: ${checkpointResult.framesCheckpointed}/${checkpointResult.totalFrames} frames`);
234
+ return checkpointResult;
235
+ }
236
+ // ============================================================================
237
+ // Integrity Check & Recovery
238
+ // ============================================================================
239
+ /**
240
+ * Run an integrity check on the database.
241
+ */
242
+ async runIntegrityCheck() {
243
+ const results = await this.innerAdapter.all("PRAGMA integrity_check");
244
+ const issues = results.map((r) => r.integrity_check).filter((msg) => msg !== "ok");
245
+ const ok = issues.length === 0;
246
+ if (!ok) {
247
+ this.log(`Integrity check found ${issues.length} issues`);
248
+ if (this.recoveryConfig.autoRepair) {
249
+ await this.attemptRepair();
250
+ }
251
+ } else {
252
+ this.log("Integrity check passed");
253
+ }
254
+ return { ok, issues };
255
+ }
256
+ /**
257
+ * Attempt to repair the database.
258
+ */
259
+ async attemptRepair() {
260
+ this.log("Attempting database repair...");
261
+ try {
262
+ await this.innerAdapter.exec("VACUUM");
263
+ this.log("VACUUM completed successfully");
264
+ } catch (error) {
265
+ this.log(`Repair failed: ${error}`);
266
+ throw new Error(`Database repair failed: ${error}`);
267
+ }
268
+ }
269
+ // ============================================================================
270
+ // Backup Management
271
+ // ============================================================================
272
+ /**
273
+ * Start the backup scheduler.
274
+ */
275
+ startBackupScheduler() {
276
+ const interval = this.options.backup?.interval ?? 36e5;
277
+ this.backupTimer = setInterval(() => this.runBackup().catch((err) => this.log(`Backup error: ${err}`)), interval);
278
+ }
279
+ /**
280
+ * Run a backup.
281
+ */
282
+ async runBackup() {
283
+ if (!this.options.backup?.provider) {
284
+ throw new Error("No backup provider configured");
285
+ }
286
+ const backupPath = `${this.filePath}.backup`;
287
+ const remotePath = `backups/${import_path.default.basename(this.filePath)}_${Date.now()}.db`;
288
+ await this.innerAdapter.exec(`VACUUM INTO '${backupPath}'`);
289
+ await this.options.backup.provider.upload(backupPath, remotePath);
290
+ await this.cleanupOldBackups();
291
+ this.log(`Backup completed: ${remotePath}`);
292
+ }
293
+ /**
294
+ * Cleanup old backups beyond the retention limit.
295
+ */
296
+ async cleanupOldBackups() {
297
+ if (!this.options.backup?.provider)
298
+ return;
299
+ const maxBackups = this.options.backup.maxBackups ?? 7;
300
+ const backups = await this.options.backup.provider.list();
301
+ if (backups.length > maxBackups) {
302
+ backups.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
303
+ const toDelete = backups.slice(0, backups.length - maxBackups);
304
+ for (const backup of toDelete) {
305
+ await this.options.backup.provider.delete(backup.path);
306
+ this.log(`Deleted old backup: ${backup.path}`);
307
+ }
308
+ }
309
+ }
310
+ // ============================================================================
311
+ // Multi-Window Broadcasting
312
+ // ============================================================================
313
+ /**
314
+ * Broadcast a database change to all windows.
315
+ */
316
+ broadcastChange(change) {
317
+ const allWindows = import_electron.BrowserWindow.getAllWindows();
318
+ for (const win of allWindows) {
319
+ if (!win.isDestroyed()) {
320
+ win.webContents.send(import_channels.BROADCAST_CHANNELS.DB_CHANGE, change);
321
+ }
322
+ }
323
+ }
324
+ // ============================================================================
325
+ // Helper Methods
326
+ // ============================================================================
327
+ /**
328
+ * Detect mutation type from SQL statement.
329
+ */
330
+ detectMutationType(statement) {
331
+ const upper = statement.trim().toUpperCase();
332
+ if (upper.startsWith("INSERT"))
333
+ return "insert";
334
+ if (upper.startsWith("UPDATE"))
335
+ return "update";
336
+ if (upper.startsWith("DELETE"))
337
+ return "delete";
338
+ return "transaction";
339
+ }
340
+ /**
341
+ * Extract table names from SQL statement.
342
+ */
343
+ extractTables(statement) {
344
+ const tables = [];
345
+ const patterns = [
346
+ /FROM\s+([^\s,;(]+)/gi,
347
+ /INSERT\s+INTO\s+([^\s(]+)/gi,
348
+ /UPDATE\s+([^\s]+)/gi,
349
+ /DELETE\s+FROM\s+([^\s]+)/gi
350
+ ];
351
+ for (const pattern of patterns) {
352
+ const matches = statement.matchAll(pattern);
353
+ for (const match of matches) {
354
+ if (match[1]) {
355
+ tables.push(match[1].toLowerCase().replace(/["`[\]]/g, ""));
356
+ }
357
+ }
358
+ }
359
+ return [...new Set(tables)];
360
+ }
361
+ /**
362
+ * Log a message if verbose mode is enabled.
363
+ */
364
+ log(message) {
365
+ if (this.options.verbose) {
366
+ console.log(`[ElectronMainAdapter] ${message}`);
367
+ }
368
+ }
369
+ // ============================================================================
370
+ // Public Utilities
371
+ // ============================================================================
372
+ /**
373
+ * Check if the adapter is initialized.
374
+ */
375
+ isOpen() {
376
+ return this.isInitialized;
377
+ }
378
+ /**
379
+ * Get the database file path.
380
+ */
381
+ getFilePath() {
382
+ return this.filePath;
383
+ }
384
+ }
385
+ function createElectronMainAdapter(options) {
386
+ return new ElectronMainAdapter(options);
387
+ }
388
+ // Annotate the CommonJS export names for ESM import in node:
389
+ 0 && (module.exports = {
390
+ ElectronMainAdapter,
391
+ createElectronMainAdapter
392
+ });
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Electron Renderer Process Storage Adapter.
3
+ *
4
+ * Provides the same StorageAdapter interface to renderer processes
5
+ * by proxying all operations to the main process via IPC.
6
+ *
7
+ * ## Architecture
8
+ * This adapter runs in renderer processes and communicates with
9
+ * ElectronMainAdapter in the main process via the preload script API.
10
+ *
11
+ * ## Requirements
12
+ * - Preload script must be loaded and expose `window.sqlStorage`
13
+ * - Main process must have ElectronMainAdapter initialized
14
+ *
15
+ * ## Usage
16
+ * ```typescript
17
+ * import { createElectronRendererAdapter } from '@framers/sql-storage-adapter/electron';
18
+ *
19
+ * const db = createElectronRendererAdapter({
20
+ * onDatabaseChange: (change) => {
21
+ * console.log('Database changed:', change);
22
+ * // React to changes from other windows
23
+ * },
24
+ * });
25
+ *
26
+ * await db.open();
27
+ * const users = await db.all('SELECT * FROM users');
28
+ * ```
29
+ */
30
+ import type { StorageAdapter, StorageCapability, StorageOpenOptions, StorageParameters, StorageRunResult, BatchOperation, BatchResult, PreparedStatement } from '../../core/contracts/index.js';
31
+ import type { DbChangeEvent, SyncStatus } from './ipc/types.js';
32
+ /**
33
+ * Options for ElectronRendererAdapter.
34
+ */
35
+ export interface ElectronRendererAdapterOptions {
36
+ /**
37
+ * Callback when database changes from another window.
38
+ * Use this to invalidate caches or refresh UI.
39
+ */
40
+ onDatabaseChange?: (event: DbChangeEvent) => void;
41
+ /**
42
+ * Callback when sync progress updates.
43
+ */
44
+ onSyncProgress?: (progress: number) => void;
45
+ /**
46
+ * Callback when sync completes.
47
+ */
48
+ onSyncComplete?: () => void;
49
+ /**
50
+ * Callback when sync encounters an error.
51
+ */
52
+ onSyncError?: (error: Error) => void;
53
+ /**
54
+ * Enable verbose logging (default: false).
55
+ */
56
+ verbose?: boolean;
57
+ }
58
+ /**
59
+ * Storage adapter for Electron renderer processes.
60
+ *
61
+ * Proxies all database operations to the main process via IPC.
62
+ * Implements the same StorageAdapter interface as other adapters.
63
+ */
64
+ export declare class ElectronRendererAdapter implements StorageAdapter {
65
+ readonly kind = "electron-renderer";
66
+ capabilities: ReadonlySet<StorageCapability>;
67
+ private readonly options;
68
+ private eventUnsubscribers;
69
+ private isInitialized;
70
+ private cachedCapabilities;
71
+ constructor(options?: ElectronRendererAdapterOptions);
72
+ /**
73
+ * Get the preload API, throwing if not available.
74
+ */
75
+ private getApi;
76
+ /**
77
+ * Log a message if verbose mode is enabled.
78
+ */
79
+ private log;
80
+ /**
81
+ * Open connection to the database via main process.
82
+ */
83
+ open(options?: StorageOpenOptions): Promise<void>;
84
+ /**
85
+ * Close connection.
86
+ */
87
+ close(): Promise<void>;
88
+ /**
89
+ * Subscribe to database events from main process.
90
+ */
91
+ private subscribeToEvents;
92
+ /**
93
+ * Execute a mutation statement (INSERT, UPDATE, DELETE).
94
+ */
95
+ run(statement: string, parameters?: StorageParameters): Promise<StorageRunResult>;
96
+ /**
97
+ * Get a single row.
98
+ */
99
+ get<T = unknown>(statement: string, parameters?: StorageParameters): Promise<T | null>;
100
+ /**
101
+ * Get all matching rows.
102
+ */
103
+ all<T = unknown>(statement: string, parameters?: StorageParameters): Promise<T[]>;
104
+ /**
105
+ * Execute a SQL script.
106
+ */
107
+ exec(script: string): Promise<void>;
108
+ /**
109
+ * Execute operations within a transaction.
110
+ */
111
+ transaction<T>(fn: (trx: StorageAdapter) => Promise<T>): Promise<T>;
112
+ /**
113
+ * Execute batch operations.
114
+ */
115
+ batch(operations: BatchOperation[]): Promise<BatchResult>;
116
+ /**
117
+ * Prepared statements are not directly supported in renderer.
118
+ * Use the main process adapter for prepared statements.
119
+ */
120
+ prepare?<T = unknown>(_statement: string): PreparedStatement<T>;
121
+ /**
122
+ * Get current sync status.
123
+ */
124
+ getSyncStatus(): Promise<SyncStatus>;
125
+ /**
126
+ * Trigger a manual sync.
127
+ */
128
+ triggerSync(): Promise<void>;
129
+ /**
130
+ * Assert that the adapter is open.
131
+ */
132
+ private assertOpen;
133
+ /**
134
+ * Check if the adapter is open.
135
+ */
136
+ isOpen(): boolean;
137
+ /**
138
+ * Check if the main process database is open.
139
+ */
140
+ isMainProcessOpen(): Promise<boolean>;
141
+ /**
142
+ * Add an event listener for database changes.
143
+ */
144
+ onDatabaseChange(callback: (event: DbChangeEvent) => void): () => void;
145
+ }
146
+ /**
147
+ * Create an Electron Renderer Process Storage Adapter.
148
+ *
149
+ * This adapter proxies all database operations to the main process
150
+ * via IPC. Use it in renderer processes to access the shared database.
151
+ *
152
+ * @param options - Adapter configuration
153
+ * @returns ElectronRendererAdapter instance
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const db = createElectronRendererAdapter({
158
+ * onDatabaseChange: (change) => {
159
+ * console.log('Database changed:', change);
160
+ * // Refresh data or invalidate caches
161
+ * },
162
+ * });
163
+ *
164
+ * await db.open();
165
+ * const users = await db.all('SELECT * FROM users');
166
+ * ```
167
+ */
168
+ export declare function createElectronRendererAdapter(options?: ElectronRendererAdapterOptions): ElectronRendererAdapter;
169
+ /**
170
+ * Helper to detect if running in Electron renderer.
171
+ */
172
+ export declare function isElectronRenderer(): boolean;
173
+ /**
174
+ * Helper to check if preload API is available.
175
+ */
176
+ export declare function isPreloadApiAvailable(): boolean;
177
+ //# sourceMappingURL=electronRendererAdapter.d.ts.map