@mauryasumit/driftdb 2.0.0

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 (82) hide show
  1. package/README.md +810 -0
  2. package/dist/db.d.ts +30 -0
  3. package/dist/db.d.ts.map +1 -0
  4. package/dist/db.js +115 -0
  5. package/dist/db.js.map +1 -0
  6. package/dist/index.d.ts +8 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +12 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/orm/model.d.ts +35 -0
  11. package/dist/orm/model.d.ts.map +1 -0
  12. package/dist/orm/model.js +34 -0
  13. package/dist/orm/model.js.map +1 -0
  14. package/dist/orm/query-builder.d.ts +8 -0
  15. package/dist/orm/query-builder.d.ts.map +1 -0
  16. package/dist/orm/query-builder.js +90 -0
  17. package/dist/orm/query-builder.js.map +1 -0
  18. package/dist/orm/repository.d.ts +38 -0
  19. package/dist/orm/repository.d.ts.map +1 -0
  20. package/dist/orm/repository.js +107 -0
  21. package/dist/orm/repository.js.map +1 -0
  22. package/dist/orm/schema.d.ts +20 -0
  23. package/dist/orm/schema.d.ts.map +1 -0
  24. package/dist/orm/schema.js +81 -0
  25. package/dist/orm/schema.js.map +1 -0
  26. package/dist/queue/queue.d.ts +17 -0
  27. package/dist/queue/queue.d.ts.map +1 -0
  28. package/dist/queue/queue.js +109 -0
  29. package/dist/queue/queue.js.map +1 -0
  30. package/dist/storage/s3-adapter.d.ts +21 -0
  31. package/dist/storage/s3-adapter.d.ts.map +1 -0
  32. package/dist/storage/s3-adapter.js +133 -0
  33. package/dist/storage/s3-adapter.js.map +1 -0
  34. package/dist/sync/change-log.d.ts +15 -0
  35. package/dist/sync/change-log.d.ts.map +1 -0
  36. package/dist/sync/change-log.js +78 -0
  37. package/dist/sync/change-log.js.map +1 -0
  38. package/dist/sync/engine.d.ts +31 -0
  39. package/dist/sync/engine.d.ts.map +1 -0
  40. package/dist/sync/engine.js +210 -0
  41. package/dist/sync/engine.js.map +1 -0
  42. package/dist/sync/snapshot-manager.d.ts +17 -0
  43. package/dist/sync/snapshot-manager.d.ts.map +1 -0
  44. package/dist/sync/snapshot-manager.js +91 -0
  45. package/dist/sync/snapshot-manager.js.map +1 -0
  46. package/dist/types.d.ts +120 -0
  47. package/dist/types.d.ts.map +1 -0
  48. package/dist/types.js +3 -0
  49. package/dist/types.js.map +1 -0
  50. package/dist/utils/compress.d.ts +3 -0
  51. package/dist/utils/compress.d.ts.map +1 -0
  52. package/dist/utils/compress.js +16 -0
  53. package/dist/utils/compress.js.map +1 -0
  54. package/dist/utils/crypto.d.ts +4 -0
  55. package/dist/utils/crypto.d.ts.map +1 -0
  56. package/dist/utils/crypto.js +35 -0
  57. package/dist/utils/crypto.js.map +1 -0
  58. package/dist/utils/id.d.ts +3 -0
  59. package/dist/utils/id.d.ts.map +1 -0
  60. package/dist/utils/id.js +13 -0
  61. package/dist/utils/id.js.map +1 -0
  62. package/dist/utils/retry.d.ts +5 -0
  63. package/dist/utils/retry.d.ts.map +1 -0
  64. package/dist/utils/retry.js +36 -0
  65. package/dist/utils/retry.js.map +1 -0
  66. package/package.json +55 -0
  67. package/src/db.ts +154 -0
  68. package/src/index.ts +24 -0
  69. package/src/orm/model.ts +95 -0
  70. package/src/orm/query-builder.ts +100 -0
  71. package/src/orm/repository.ts +156 -0
  72. package/src/orm/schema.ts +92 -0
  73. package/src/queue/queue.ts +138 -0
  74. package/src/storage/s3-adapter.ts +181 -0
  75. package/src/sync/change-log.ts +101 -0
  76. package/src/sync/engine.ts +249 -0
  77. package/src/sync/snapshot-manager.ts +80 -0
  78. package/src/types.ts +130 -0
  79. package/src/utils/compress.ts +14 -0
  80. package/src/utils/crypto.ts +33 -0
  81. package/src/utils/id.ts +10 -0
  82. package/src/utils/retry.ts +38 -0
@@ -0,0 +1,210 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SyncEngine = void 0;
4
+ const queue_js_1 = require("../queue/queue.js");
5
+ const change_log_js_1 = require("./change-log.js");
6
+ const snapshot_manager_js_1 = require("./snapshot-manager.js");
7
+ const s3_adapter_js_1 = require("../storage/s3-adapter.js");
8
+ const retry_js_1 = require("../utils/retry.js");
9
+ const fs_1 = require("fs");
10
+ const DEFAULT_SYNC_INTERVAL_MS = 5000;
11
+ const DEFAULT_SNAPSHOT_EVERY_N_LOGS = 1000;
12
+ const DEFAULT_MAX_BATCH_SIZE = 100;
13
+ const DEFAULT_RETRY_CONFIG = { maxRetries: 5, baseDelayMs: 500, maxDelayMs: 30000 };
14
+ class SyncEngine {
15
+ constructor(db, nodeId, config) {
16
+ this.timer = null;
17
+ this.isProcessing = false;
18
+ this.metrics = {
19
+ lastSyncAt: null,
20
+ lastSnapshotAt: null,
21
+ pendingChanges: 0,
22
+ dbSizeBytes: 0,
23
+ totalSynced: 0,
24
+ syncErrors: 0,
25
+ isRunning: false,
26
+ };
27
+ this.db = db;
28
+ this.config = config;
29
+ this.nodeId = nodeId;
30
+ const retryConfig = { ...DEFAULT_RETRY_CONFIG, ...config.retryConfig };
31
+ this.queue = new queue_js_1.SyncQueue(db, retryConfig);
32
+ this.changeLog = new change_log_js_1.ChangeLog(db, nodeId);
33
+ if (config.s3Config) {
34
+ this.s3 = new s3_adapter_js_1.S3Adapter(config.s3Config);
35
+ const uploadOptions = {
36
+ compress: config.compression !== false,
37
+ encryptionKey: config.encryption?.key,
38
+ };
39
+ this.snapshotManager = new snapshot_manager_js_1.SnapshotManager(db, this.s3, nodeId, config.sqlitePath, uploadOptions);
40
+ }
41
+ else {
42
+ this.s3 = null;
43
+ this.snapshotManager = null;
44
+ }
45
+ }
46
+ getChangeLog() {
47
+ return this.changeLog;
48
+ }
49
+ getQueue() {
50
+ return this.queue;
51
+ }
52
+ start() {
53
+ if (this.timer)
54
+ return;
55
+ this.metrics.isRunning = true;
56
+ this.queue.resetStuck();
57
+ const intervalMs = this.config.syncIntervalMs ?? DEFAULT_SYNC_INTERVAL_MS;
58
+ this.timer = setInterval(() => {
59
+ void this.tick();
60
+ }, intervalMs);
61
+ if (this.timer.unref) {
62
+ this.timer.unref();
63
+ }
64
+ }
65
+ stop() {
66
+ if (this.timer) {
67
+ clearInterval(this.timer);
68
+ this.timer = null;
69
+ }
70
+ this.metrics.isRunning = false;
71
+ }
72
+ async flush() {
73
+ await this.tick();
74
+ }
75
+ getMetrics() {
76
+ return {
77
+ ...this.metrics,
78
+ pendingChanges: this.changeLog.pendingCount(),
79
+ dbSizeBytes: this.getDbSizeBytes(),
80
+ };
81
+ }
82
+ getDbSizeBytes() {
83
+ const path = this.config.sqlitePath;
84
+ if (path === ':memory:' || !(0, fs_1.existsSync)(path))
85
+ return 0;
86
+ try {
87
+ return (0, fs_1.statSync)(path).size;
88
+ }
89
+ catch {
90
+ return 0;
91
+ }
92
+ }
93
+ async tick() {
94
+ if (this.isProcessing || !this.s3)
95
+ return;
96
+ this.isProcessing = true;
97
+ try {
98
+ await this.enqueuePendingLogs();
99
+ await this.processQueue();
100
+ }
101
+ catch (err) {
102
+ this.metrics.syncErrors++;
103
+ }
104
+ finally {
105
+ this.isProcessing = false;
106
+ }
107
+ }
108
+ async enqueuePendingLogs() {
109
+ const maxBatch = this.config.maxBatchSize ?? DEFAULT_MAX_BATCH_SIZE;
110
+ const pending = this.changeLog.pendingEntries(maxBatch);
111
+ if (pending.length === 0)
112
+ return;
113
+ const batch = this.changeLog.buildBatch(pending);
114
+ const s3Key = this.s3.logKey(this.nodeId, batch.fromSequence, batch.toSequence);
115
+ const alreadyQueued = this.queue.hasPendingOfType('upload_log');
116
+ if (!alreadyQueued) {
117
+ const payload = {
118
+ fromSequence: batch.fromSequence,
119
+ toSequence: batch.toSequence,
120
+ s3Key,
121
+ };
122
+ this.queue.enqueue('upload_log', { ...payload, batch });
123
+ }
124
+ }
125
+ async processQueue() {
126
+ const jobs = this.queue.dequeue(3);
127
+ await Promise.allSettled(jobs.map((job) => this.processJob(job)));
128
+ this.queue.purgeCompleted();
129
+ }
130
+ async processJob(job) {
131
+ const retryConfig = { ...DEFAULT_RETRY_CONFIG, ...this.config.retryConfig };
132
+ const uploadOptions = {
133
+ compress: this.config.compression !== false,
134
+ encryptionKey: this.config.encryption?.key,
135
+ };
136
+ try {
137
+ await (0, retry_js_1.withRetry)(async () => {
138
+ if (job.type === 'upload_log') {
139
+ const p = JSON.parse(job.payload);
140
+ const batchBuffer = Buffer.from(JSON.stringify(p.batch), 'utf8');
141
+ await this.s3.upload(p.s3Key, batchBuffer, uploadOptions);
142
+ this.changeLog.markSynced(p.fromSequence, p.toSequence);
143
+ const manifest = await this.s3.getManifest(this.nodeId);
144
+ const latestSeq = Math.max(manifest?.latestLogSequence ?? 0, p.toSequence);
145
+ await this.s3.putManifest(this.nodeId, {
146
+ nodeId: this.nodeId,
147
+ latestSnapshotKey: manifest?.latestSnapshotKey ?? null,
148
+ latestSnapshotTimestamp: manifest?.latestSnapshotTimestamp ?? null,
149
+ latestLogSequence: latestSeq,
150
+ updatedAt: Date.now(),
151
+ });
152
+ this.metrics.totalSynced += (p.toSequence - p.fromSequence + 1);
153
+ this.metrics.lastSyncAt = Date.now();
154
+ await this.maybeSnapshot(latestSeq);
155
+ }
156
+ else if (job.type === 'upload_snapshot') {
157
+ const p = JSON.parse(job.payload);
158
+ if (this.snapshotManager) {
159
+ const { key, timestamp } = await this.snapshotManager.takeAndUpload();
160
+ const manifest = await this.s3.getManifest(this.nodeId);
161
+ await this.s3.putManifest(this.nodeId, {
162
+ nodeId: this.nodeId,
163
+ latestSnapshotKey: key,
164
+ latestSnapshotTimestamp: timestamp,
165
+ latestLogSequence: manifest?.latestLogSequence ?? 0,
166
+ updatedAt: Date.now(),
167
+ });
168
+ this.metrics.lastSnapshotAt = Date.now();
169
+ }
170
+ void p;
171
+ }
172
+ }, retryConfig);
173
+ this.queue.markDone(job.id);
174
+ }
175
+ catch (err) {
176
+ const msg = err instanceof Error ? err.message : String(err);
177
+ this.queue.markFailed(job.id, msg);
178
+ this.metrics.syncErrors++;
179
+ }
180
+ }
181
+ async maybeSnapshot(latestSequence) {
182
+ const threshold = this.config.snapshotEveryNLogs ?? DEFAULT_SNAPSHOT_EVERY_N_LOGS;
183
+ if (latestSequence > 0 && latestSequence % threshold === 0) {
184
+ if (!this.queue.hasPendingOfType('upload_snapshot')) {
185
+ const payload = {
186
+ timestamp: Date.now(),
187
+ s3Key: this.s3.snapshotKey(this.nodeId, Date.now()),
188
+ dbPath: this.config.sqlitePath,
189
+ };
190
+ this.queue.enqueue('upload_snapshot', payload);
191
+ }
192
+ }
193
+ }
194
+ async triggerSnapshot() {
195
+ if (!this.snapshotManager || !this.s3)
196
+ return;
197
+ const { key, timestamp } = await this.snapshotManager.takeAndUpload();
198
+ const manifest = await this.s3.getManifest(this.nodeId);
199
+ await this.s3.putManifest(this.nodeId, {
200
+ nodeId: this.nodeId,
201
+ latestSnapshotKey: key,
202
+ latestSnapshotTimestamp: timestamp,
203
+ latestLogSequence: manifest?.latestLogSequence ?? 0,
204
+ updatedAt: Date.now(),
205
+ });
206
+ this.metrics.lastSnapshotAt = Date.now();
207
+ }
208
+ }
209
+ exports.SyncEngine = SyncEngine;
210
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/sync/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type Database from 'better-sqlite3';
2
+ import type { S3Adapter } from '../storage/s3-adapter.js';
3
+ import type { S3UploadOptions } from '../storage/s3-adapter.js';
4
+ export declare class SnapshotManager {
5
+ private readonly db;
6
+ private readonly s3;
7
+ private readonly nodeId;
8
+ private readonly sqlitePath;
9
+ private readonly uploadOptions;
10
+ constructor(db: Database.Database, s3: S3Adapter, nodeId: string, sqlitePath: string, uploadOptions: S3UploadOptions);
11
+ takeAndUpload(): Promise<{
12
+ key: string;
13
+ timestamp: number;
14
+ }>;
15
+ restoreLatest(): Promise<boolean>;
16
+ }
17
+ //# sourceMappingURL=snapshot-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-manager.d.ts","sourceRoot":"","sources":["../../src/sync/snapshot-manager.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAEhE,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAoB;IACvC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAY;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkB;gBAG9C,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,EAAE,EAAE,SAAS,EACb,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,eAAe;IAS1B,aAAa,IAAI,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAiC5D,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC;CAiBxC"}
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SnapshotManager = void 0;
37
+ const fs_1 = require("fs");
38
+ const path_1 = require("path");
39
+ const os_1 = require("os");
40
+ const fs_2 = require("fs");
41
+ class SnapshotManager {
42
+ constructor(db, s3, nodeId, sqlitePath, uploadOptions) {
43
+ this.db = db;
44
+ this.s3 = s3;
45
+ this.nodeId = nodeId;
46
+ this.sqlitePath = sqlitePath;
47
+ this.uploadOptions = uploadOptions;
48
+ }
49
+ async takeAndUpload() {
50
+ const timestamp = Date.now();
51
+ const tempPath = (0, path_1.join)((0, os_1.tmpdir)(), `driftdb-snap-${this.nodeId}-${timestamp}.sqlite`);
52
+ try {
53
+ this.db.exec('PRAGMA wal_checkpoint(FULL)');
54
+ if (this.sqlitePath === ':memory:') {
55
+ const backup = this.db.serialize();
56
+ await this.s3.upload(this.s3.snapshotKey(this.nodeId, timestamp), Buffer.from(backup), this.uploadOptions);
57
+ }
58
+ else {
59
+ (0, fs_2.copyFileSync)(this.sqlitePath, tempPath);
60
+ const data = (0, fs_1.readFileSync)(tempPath);
61
+ await this.s3.upload(this.s3.snapshotKey(this.nodeId, timestamp), data, this.uploadOptions);
62
+ }
63
+ const key = this.s3.snapshotKey(this.nodeId, timestamp);
64
+ return { key, timestamp };
65
+ }
66
+ finally {
67
+ if ((0, fs_1.existsSync)(tempPath)) {
68
+ try {
69
+ (0, fs_2.unlinkSync)(tempPath);
70
+ }
71
+ catch { /* ignore */ }
72
+ }
73
+ }
74
+ }
75
+ async restoreLatest() {
76
+ const manifest = await this.s3.getManifest(this.nodeId);
77
+ if (!manifest?.latestSnapshotKey)
78
+ return false;
79
+ const data = await this.s3.download(manifest.latestSnapshotKey, this.uploadOptions);
80
+ const restorePath = this.sqlitePath !== ':memory:' ? this.sqlitePath : null;
81
+ if (!restorePath)
82
+ return false;
83
+ const dir = (0, path_1.dirname)(restorePath);
84
+ (0, fs_2.mkdirSync)(dir, { recursive: true });
85
+ const { writeFileSync } = await Promise.resolve().then(() => __importStar(require('fs')));
86
+ writeFileSync(restorePath, data);
87
+ return true;
88
+ }
89
+ }
90
+ exports.SnapshotManager = SnapshotManager;
91
+ //# sourceMappingURL=snapshot-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-manager.js","sourceRoot":"","sources":["../../src/sync/snapshot-manager.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2BAA8C;AAC9C,+BAAqC;AACrC,2BAA4B;AAC5B,2BAAyD;AAKzD,MAAa,eAAe;IAO1B,YACE,EAAqB,EACrB,EAAa,EACb,MAAc,EACd,UAAkB,EAClB,aAA8B;QAE9B,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,IAAA,WAAI,EAAC,IAAA,WAAM,GAAE,EAAE,gBAAgB,IAAI,CAAC,MAAM,IAAI,SAAS,SAAS,CAAC,CAAC;QAEnF,IAAI,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;YAE5C,IAAI,IAAI,CAAC,UAAU,KAAK,UAAU,EAAE,CAAC;gBACnC,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC;gBACnC,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAClB,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,EAC3C,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EACnB,IAAI,CAAC,aAAa,CACnB,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,IAAA,iBAAY,EAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;gBACxC,MAAM,IAAI,GAAG,IAAA,iBAAY,EAAC,QAAQ,CAAC,CAAC;gBACpC,MAAM,IAAI,CAAC,EAAE,CAAC,MAAM,CAClB,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,EAC3C,IAAI,EACJ,IAAI,CAAC,aAAa,CACnB,CAAC;YACJ,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;YACxD,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;QAC5B,CAAC;gBAAS,CAAC;YACT,IAAI,IAAA,eAAU,EAAC,QAAQ,CAAC,EAAE,CAAC;gBACzB,IAAI,CAAC;oBAAC,IAAA,eAAU,EAAC,QAAQ,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,YAAY,CAAC,CAAC;YACtD,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ,EAAE,iBAAiB;YAAE,OAAO,KAAK,CAAC;QAE/C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,iBAAiB,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAEpF,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5E,IAAI,CAAC,WAAW;YAAE,OAAO,KAAK,CAAC;QAE/B,MAAM,GAAG,GAAG,IAAA,cAAO,EAAC,WAAW,CAAC,CAAC;QACjC,IAAA,cAAS,EAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEpC,MAAM,EAAE,aAAa,EAAE,GAAG,wDAAa,IAAI,GAAC,CAAC;QAC7C,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAEjC,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAvED,0CAuEC"}
@@ -0,0 +1,120 @@
1
+ export type ColumnType = 'TEXT' | 'INTEGER' | 'REAL' | 'BLOB' | 'BOOLEAN';
2
+ export interface ColumnDef {
3
+ type: ColumnType;
4
+ notNull?: boolean;
5
+ unique?: boolean;
6
+ default?: string | number | boolean | null;
7
+ index?: boolean;
8
+ }
9
+ export type ModelSchema = Record<string, ColumnDef>;
10
+ export interface BaseRecord {
11
+ id: string;
12
+ createdAt: number;
13
+ updatedAt: number;
14
+ }
15
+ export type WhereValue<V> = V | {
16
+ $gt?: V;
17
+ $gte?: V;
18
+ $lt?: V;
19
+ $lte?: V;
20
+ $in?: V[];
21
+ $like?: string;
22
+ $ne?: V;
23
+ };
24
+ export type WhereClause<T> = {
25
+ [K in keyof T]?: WhereValue<T[K]>;
26
+ };
27
+ export interface FindOptions<T> {
28
+ where?: WhereClause<T>;
29
+ orderBy?: Partial<Record<keyof T, 'ASC' | 'DESC'>>;
30
+ limit?: number;
31
+ offset?: number;
32
+ }
33
+ export interface S3Config {
34
+ bucket: string;
35
+ region: string;
36
+ prefix?: string;
37
+ accessKeyId?: string;
38
+ secretAccessKey?: string;
39
+ endpoint?: string;
40
+ forcePathStyle?: boolean;
41
+ }
42
+ export interface RetryConfig {
43
+ maxRetries: number;
44
+ baseDelayMs: number;
45
+ maxDelayMs: number;
46
+ }
47
+ export interface EncryptionConfig {
48
+ key: string;
49
+ }
50
+ export interface DBConfig {
51
+ sqlitePath: string;
52
+ s3Config?: S3Config;
53
+ nodeId?: string;
54
+ syncIntervalMs?: number;
55
+ snapshotEveryNLogs?: number;
56
+ maxBatchSize?: number;
57
+ compression?: boolean;
58
+ encryption?: EncryptionConfig;
59
+ retryConfig?: RetryConfig;
60
+ autoSync?: boolean;
61
+ }
62
+ export interface ChangeLogEntry {
63
+ sequence: number;
64
+ timestamp: number;
65
+ nodeId: string;
66
+ table: string;
67
+ operation: 'insert' | 'update' | 'delete';
68
+ data: string | null;
69
+ synced: 0 | 1;
70
+ }
71
+ export interface LogBatch {
72
+ version: 1;
73
+ nodeId: string;
74
+ fromSequence: number;
75
+ toSequence: number;
76
+ entries: Array<{
77
+ sequence: number;
78
+ timestamp: number;
79
+ table: string;
80
+ operation: 'insert' | 'update' | 'delete';
81
+ data: Record<string, unknown> | null;
82
+ }>;
83
+ }
84
+ export interface SyncJob {
85
+ id: string;
86
+ type: 'upload_log' | 'upload_snapshot';
87
+ payload: string;
88
+ status: 'pending' | 'processing' | 'done' | 'failed';
89
+ attempts: number;
90
+ nextRetryAt: number;
91
+ createdAt: number;
92
+ error: string | null;
93
+ }
94
+ export interface SyncManifest {
95
+ nodeId: string;
96
+ latestSnapshotKey: string | null;
97
+ latestSnapshotTimestamp: number | null;
98
+ latestLogSequence: number;
99
+ updatedAt: number;
100
+ }
101
+ export interface SyncMetrics {
102
+ lastSyncAt: number | null;
103
+ lastSnapshotAt: number | null;
104
+ pendingChanges: number;
105
+ dbSizeBytes: number;
106
+ totalSynced: number;
107
+ syncErrors: number;
108
+ isRunning: boolean;
109
+ }
110
+ export interface UploadLogPayload {
111
+ fromSequence: number;
112
+ toSequence: number;
113
+ s3Key: string;
114
+ }
115
+ export interface UploadSnapshotPayload {
116
+ timestamp: number;
117
+ s3Key: string;
118
+ dbPath: string;
119
+ }
120
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ export declare function compress(data: Buffer | string): Promise<Buffer>;
2
+ export declare function decompress(data: Buffer): Promise<Buffer>;
3
+ //# sourceMappingURL=compress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compress.d.ts","sourceRoot":"","sources":["../../src/utils/compress.ts"],"names":[],"mappings":"AAMA,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGrE;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE9D"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.compress = compress;
4
+ exports.decompress = decompress;
5
+ const zlib_1 = require("zlib");
6
+ const util_1 = require("util");
7
+ const gzipAsync = (0, util_1.promisify)(zlib_1.gzip);
8
+ const gunzipAsync = (0, util_1.promisify)(zlib_1.gunzip);
9
+ async function compress(data) {
10
+ const buf = typeof data === 'string' ? Buffer.from(data, 'utf8') : data;
11
+ return gzipAsync(buf, { level: zlib_1.constants.Z_BEST_SPEED });
12
+ }
13
+ async function decompress(data) {
14
+ return gunzipAsync(data);
15
+ }
16
+ //# sourceMappingURL=compress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compress.js","sourceRoot":"","sources":["../../src/utils/compress.ts"],"names":[],"mappings":";;AAMA,4BAGC;AAED,gCAEC;AAbD,+BAA+C;AAC/C,+BAAiC;AAEjC,MAAM,SAAS,GAAG,IAAA,gBAAS,EAAC,WAAI,CAAC,CAAC;AAClC,MAAM,WAAW,GAAG,IAAA,gBAAS,EAAC,aAAM,CAAC,CAAC;AAE/B,KAAK,UAAU,QAAQ,CAAC,IAAqB;IAClD,MAAM,GAAG,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxE,OAAO,SAAS,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,gBAAS,CAAC,YAAY,EAAE,CAAC,CAAC;AAC3D,CAAC;AAEM,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function normalizeKey(hexKey: string): Buffer;
2
+ export declare function encrypt(data: Buffer, hexKey: string): Buffer;
3
+ export declare function decrypt(data: Buffer, hexKey: string): Buffer;
4
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/utils/crypto.ts"],"names":[],"mappings":"AAOA,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMnD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAO5D;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAQ5D"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeKey = normalizeKey;
4
+ exports.encrypt = encrypt;
5
+ exports.decrypt = decrypt;
6
+ const crypto_1 = require("crypto");
7
+ const ALGORITHM = 'aes-256-gcm';
8
+ const IV_LENGTH = 12;
9
+ const TAG_LENGTH = 16;
10
+ const KEY_LENGTH = 32;
11
+ function normalizeKey(hexKey) {
12
+ const buf = Buffer.from(hexKey, 'hex');
13
+ if (buf.length !== KEY_LENGTH) {
14
+ throw new Error(`Encryption key must be ${KEY_LENGTH * 2} hex characters (${KEY_LENGTH} bytes)`);
15
+ }
16
+ return buf;
17
+ }
18
+ function encrypt(data, hexKey) {
19
+ const key = normalizeKey(hexKey);
20
+ const iv = (0, crypto_1.randomBytes)(IV_LENGTH);
21
+ const cipher = (0, crypto_1.createCipheriv)(ALGORITHM, key, iv);
22
+ const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
23
+ const tag = cipher.getAuthTag();
24
+ return Buffer.concat([iv, tag, encrypted]);
25
+ }
26
+ function decrypt(data, hexKey) {
27
+ const key = normalizeKey(hexKey);
28
+ const iv = data.subarray(0, IV_LENGTH);
29
+ const tag = data.subarray(IV_LENGTH, IV_LENGTH + TAG_LENGTH);
30
+ const encrypted = data.subarray(IV_LENGTH + TAG_LENGTH);
31
+ const decipher = (0, crypto_1.createDecipheriv)(ALGORITHM, key, iv);
32
+ decipher.setAuthTag(tag);
33
+ return Buffer.concat([decipher.update(encrypted), decipher.final()]);
34
+ }
35
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/utils/crypto.ts"],"names":[],"mappings":";;AAOA,oCAMC;AAED,0BAOC;AAED,0BAQC;AAhCD,mCAAuE;AAEvE,MAAM,SAAS,GAAG,aAAa,CAAC;AAChC,MAAM,SAAS,GAAG,EAAE,CAAC;AACrB,MAAM,UAAU,GAAG,EAAE,CAAC;AACtB,MAAM,UAAU,GAAG,EAAE,CAAC;AAEtB,SAAgB,YAAY,CAAC,MAAc;IACzC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACvC,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,0BAA0B,UAAU,GAAG,CAAC,oBAAoB,UAAU,SAAS,CAAC,CAAC;IACnG,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAgB,OAAO,CAAC,IAAY,EAAE,MAAc;IAClD,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,EAAE,GAAG,IAAA,oBAAW,EAAC,SAAS,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,IAAA,uBAAc,EAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IAClD,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACvE,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAChC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,SAAgB,OAAO,CAAC,IAAY,EAAE,MAAc;IAClD,MAAM,GAAG,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,UAAU,CAAC,CAAC;IAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,GAAG,UAAU,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,IAAA,yBAAgB,EAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACzB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACvE,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function generateId(): string;
2
+ export declare function generateNodeId(): string;
3
+ //# sourceMappingURL=id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.d.ts","sourceRoot":"","sources":["../../src/utils/id.ts"],"names":[],"mappings":"AAGA,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC"}
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateId = generateId;
4
+ exports.generateNodeId = generateNodeId;
5
+ const uuid_1 = require("uuid");
6
+ const crypto_1 = require("crypto");
7
+ function generateId() {
8
+ return (0, uuid_1.v4)();
9
+ }
10
+ function generateNodeId() {
11
+ return (0, crypto_1.randomBytes)(6).toString('hex');
12
+ }
13
+ //# sourceMappingURL=id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/utils/id.ts"],"names":[],"mappings":";;AAGA,gCAEC;AAED,wCAEC;AATD,+BAAoC;AACpC,mCAAqC;AAErC,SAAgB,UAAU;IACxB,OAAO,IAAA,SAAM,GAAE,CAAC;AAClB,CAAC;AAED,SAAgB,cAAc;IAC5B,OAAO,IAAA,oBAAW,EAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { RetryConfig } from '../types.js';
2
+ export declare function withRetry<T>(fn: () => Promise<T>, config?: Partial<RetryConfig>): Promise<T>;
3
+ export declare function sleep(ms: number): Promise<void>;
4
+ export declare function nextRetryAt(attempt: number, config?: RetryConfig): number;
5
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAQ/C,wBAAsB,SAAS,CAAC,CAAC,EAC/B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAChC,OAAO,CAAC,CAAC,CAAC,CAiBZ;AAED,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,WAAkC,GAAG,MAAM,CAG/F"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withRetry = withRetry;
4
+ exports.sleep = sleep;
5
+ exports.nextRetryAt = nextRetryAt;
6
+ const DEFAULT_RETRY_CONFIG = {
7
+ maxRetries: 5,
8
+ baseDelayMs: 500,
9
+ maxDelayMs: 30000,
10
+ };
11
+ async function withRetry(fn, config = {}) {
12
+ const cfg = { ...DEFAULT_RETRY_CONFIG, ...config };
13
+ let lastError;
14
+ for (let attempt = 0; attempt <= cfg.maxRetries; attempt++) {
15
+ try {
16
+ return await fn();
17
+ }
18
+ catch (err) {
19
+ lastError = err instanceof Error ? err : new Error(String(err));
20
+ if (attempt === cfg.maxRetries)
21
+ break;
22
+ const delay = Math.min(cfg.baseDelayMs * Math.pow(2, attempt), cfg.maxDelayMs);
23
+ const jitter = Math.random() * delay * 0.2;
24
+ await sleep(delay + jitter);
25
+ }
26
+ }
27
+ throw lastError ?? new Error('Retry failed');
28
+ }
29
+ function sleep(ms) {
30
+ return new Promise((resolve) => setTimeout(resolve, ms));
31
+ }
32
+ function nextRetryAt(attempt, config = DEFAULT_RETRY_CONFIG) {
33
+ const delay = Math.min(config.baseDelayMs * Math.pow(2, attempt), config.maxDelayMs);
34
+ return Date.now() + delay;
35
+ }
36
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/utils/retry.ts"],"names":[],"mappings":";;AAQA,8BAoBC;AAED,sBAEC;AAED,kCAGC;AAnCD,MAAM,oBAAoB,GAAgB;IACxC,UAAU,EAAE,CAAC;IACb,WAAW,EAAE,GAAG;IAChB,UAAU,EAAE,KAAM;CACnB,CAAC;AAEK,KAAK,UAAU,SAAS,CAC7B,EAAoB,EACpB,SAA+B,EAAE;IAEjC,MAAM,GAAG,GAAG,EAAE,GAAG,oBAAoB,EAAE,GAAG,MAAM,EAAE,CAAC;IACnD,IAAI,SAA4B,CAAC;IAEjC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,GAAG,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;QAC3D,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,SAAS,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAChE,IAAI,OAAO,KAAK,GAAG,CAAC,UAAU;gBAAE,MAAM;YACtC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;YAC/E,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,KAAK,GAAG,GAAG,CAAC;YAC3C,MAAM,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,MAAM,SAAS,IAAI,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;AAC/C,CAAC;AAED,SAAgB,KAAK,CAAC,EAAU;IAC9B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAgB,WAAW,CAAC,OAAe,EAAE,SAAsB,oBAAoB;IACrF,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC;IACrF,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;AAC5B,CAAC"}