@mauryasumit/driftdb 2.0.0 → 3.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.
@@ -8,21 +8,24 @@ import type { S3UploadOptions } from '../storage/s3-adapter.js';
8
8
 
9
9
  export class SnapshotManager {
10
10
  private readonly db: Database.Database;
11
- private readonly s3: S3Adapter;
12
- private readonly nodeId: string;
11
+ private readonly s3: S3Adapter;
12
+ private readonly dbName: string;
13
+ private readonly nodeId: string;
13
14
  private readonly sqlitePath: string;
14
15
  private readonly uploadOptions: S3UploadOptions;
15
16
 
16
17
  constructor(
17
- db: Database.Database,
18
- s3: S3Adapter,
19
- nodeId: string,
20
- sqlitePath: string,
21
- uploadOptions: S3UploadOptions
22
- ) {
23
- this.db = db;
24
- this.s3 = s3;
25
- this.nodeId = nodeId;
18
+ db: Database.Database,
19
+ s3: S3Adapter,
20
+ dbName: string,
21
+ nodeId: string,
22
+ sqlitePath: string,
23
+ uploadOptions: S3UploadOptions
24
+ ) {
25
+ this.db = db;
26
+ this.s3 = s3;
27
+ this.dbName = dbName;
28
+ this.nodeId = nodeId;
26
29
  this.sqlitePath = sqlitePath;
27
30
  this.uploadOptions = uploadOptions;
28
31
  }
@@ -35,24 +38,24 @@ export class SnapshotManager {
35
38
  this.db.exec('PRAGMA wal_checkpoint(FULL)');
36
39
 
37
40
  if (this.sqlitePath === ':memory:') {
38
- const backup = this.db.serialize();
39
- await this.s3.upload(
40
- this.s3.snapshotKey(this.nodeId, timestamp),
41
- Buffer.from(backup),
42
- this.uploadOptions
43
- );
44
- } else {
45
- copyFileSync(this.sqlitePath, tempPath);
46
- const data = readFileSync(tempPath);
47
- await this.s3.upload(
48
- this.s3.snapshotKey(this.nodeId, timestamp),
49
- data,
50
- this.uploadOptions
51
- );
52
- }
53
-
54
- const key = this.s3.snapshotKey(this.nodeId, timestamp);
55
- return { key, timestamp };
41
+ const backup = this.db.serialize();
42
+ await this.s3.upload(
43
+ this.s3.snapshotKey(this.dbName, this.nodeId, timestamp),
44
+ Buffer.from(backup),
45
+ this.uploadOptions
46
+ );
47
+ } else {
48
+ copyFileSync(this.sqlitePath, tempPath);
49
+ const data = readFileSync(tempPath);
50
+ await this.s3.upload(
51
+ this.s3.snapshotKey(this.dbName, this.nodeId, timestamp),
52
+ data,
53
+ this.uploadOptions
54
+ );
55
+ }
56
+
57
+ const key = this.s3.snapshotKey(this.dbName, this.nodeId, timestamp);
58
+ return { key, timestamp };
56
59
  } finally {
57
60
  if (existsSync(tempPath)) {
58
61
  try { unlinkSync(tempPath); } catch { /* ignore */ }
@@ -60,8 +63,8 @@ export class SnapshotManager {
60
63
  }
61
64
  }
62
65
 
63
- async restoreLatest(): Promise<boolean> {
64
- const manifest = await this.s3.getManifest(this.nodeId);
66
+ async restoreLatest(): Promise<boolean> {
67
+ const manifest = await this.s3.getManifest(this.dbName);
65
68
  if (!manifest?.latestSnapshotKey) return false;
66
69
 
67
70
  const data = await this.s3.download(manifest.latestSnapshotKey, this.uploadOptions);
package/src/types.ts CHANGED
@@ -1,130 +1,133 @@
1
- export type ColumnType = 'TEXT' | 'INTEGER' | 'REAL' | 'BLOB' | 'BOOLEAN';
2
-
3
- export interface ColumnDef {
4
- type: ColumnType;
5
- notNull?: boolean;
6
- unique?: boolean;
7
- default?: string | number | boolean | null;
8
- index?: boolean;
9
- }
10
-
11
- export type ModelSchema = Record<string, ColumnDef>;
12
-
13
- export interface BaseRecord {
14
- id: string;
15
- createdAt: number;
16
- updatedAt: number;
17
- }
18
-
19
- export type WhereValue<V> =
20
- | V
21
- | { $gt?: V; $gte?: V; $lt?: V; $lte?: V; $in?: V[]; $like?: string; $ne?: V };
22
-
23
- export type WhereClause<T> = {
24
- [K in keyof T]?: WhereValue<T[K]>;
25
- };
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
-
34
- export interface S3Config {
35
- bucket: string;
36
- region: string;
37
- prefix?: string;
38
- accessKeyId?: string;
39
- secretAccessKey?: string;
40
- endpoint?: string;
41
- forcePathStyle?: boolean;
42
- }
43
-
44
- export interface RetryConfig {
45
- maxRetries: number;
46
- baseDelayMs: number;
47
- maxDelayMs: number;
48
- }
49
-
50
- export interface EncryptionConfig {
51
- key: string;
52
- }
53
-
54
- export interface DBConfig {
55
- sqlitePath: string;
56
- s3Config?: S3Config;
57
- nodeId?: string;
58
- syncIntervalMs?: number;
59
- snapshotEveryNLogs?: number;
60
- maxBatchSize?: number;
61
- compression?: boolean;
62
- encryption?: EncryptionConfig;
63
- retryConfig?: RetryConfig;
64
- autoSync?: boolean;
65
- }
66
-
67
- export interface ChangeLogEntry {
68
- sequence: number;
69
- timestamp: number;
70
- nodeId: string;
71
- table: string;
72
- operation: 'insert' | 'update' | 'delete';
73
- data: string | null;
74
- synced: 0 | 1;
75
- }
76
-
77
- export interface LogBatch {
78
- version: 1;
79
- nodeId: string;
80
- fromSequence: number;
81
- toSequence: number;
82
- entries: Array<{
83
- sequence: number;
84
- timestamp: number;
85
- table: string;
86
- operation: 'insert' | 'update' | 'delete';
87
- data: Record<string, unknown> | null;
88
- }>;
89
- }
90
-
91
- export interface SyncJob {
92
- id: string;
93
- type: 'upload_log' | 'upload_snapshot';
94
- payload: string;
95
- status: 'pending' | 'processing' | 'done' | 'failed';
96
- attempts: number;
97
- nextRetryAt: number;
98
- createdAt: number;
99
- error: string | null;
100
- }
101
-
102
- export interface SyncManifest {
103
- nodeId: string;
104
- latestSnapshotKey: string | null;
105
- latestSnapshotTimestamp: number | null;
106
- latestLogSequence: number;
107
- updatedAt: number;
108
- }
109
-
110
- export interface SyncMetrics {
111
- lastSyncAt: number | null;
112
- lastSnapshotAt: number | null;
113
- pendingChanges: number;
114
- dbSizeBytes: number;
115
- totalSynced: number;
116
- syncErrors: number;
117
- isRunning: boolean;
118
- }
119
-
120
- export interface UploadLogPayload {
121
- fromSequence: number;
122
- toSequence: number;
123
- s3Key: string;
124
- }
125
-
126
- export interface UploadSnapshotPayload {
127
- timestamp: number;
128
- s3Key: string;
129
- dbPath: string;
130
- }
1
+ export type ColumnType = 'TEXT' | 'INTEGER' | 'REAL' | 'BLOB' | 'BOOLEAN';
2
+
3
+ export interface ColumnDef {
4
+ type: ColumnType;
5
+ notNull?: boolean;
6
+ unique?: boolean;
7
+ default?: string | number | boolean | null;
8
+ index?: boolean;
9
+ }
10
+
11
+ export type ModelSchema = Record<string, ColumnDef>;
12
+
13
+ export interface BaseRecord {
14
+ id: string;
15
+ createdAt: number;
16
+ updatedAt: number;
17
+ }
18
+
19
+ export type WhereValue<V> =
20
+ | V
21
+ | { $gt?: V; $gte?: V; $lt?: V; $lte?: V; $in?: V[]; $like?: string; $ne?: V };
22
+
23
+ export type WhereClause<T> = {
24
+ [K in keyof T]?: WhereValue<T[K]>;
25
+ };
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
+
34
+ export interface S3Config {
35
+ bucket: string;
36
+ region: string;
37
+ prefix?: string;
38
+ accessKeyId?: string;
39
+ secretAccessKey?: string;
40
+ endpoint?: string;
41
+ forcePathStyle?: boolean;
42
+ }
43
+
44
+ export interface RetryConfig {
45
+ maxRetries: number;
46
+ baseDelayMs: number;
47
+ maxDelayMs: number;
48
+ }
49
+
50
+ export interface EncryptionConfig {
51
+ key: string;
52
+ }
53
+
54
+ export interface DBConfig {
55
+ dbName: string;
56
+ sqlitePath: string;
57
+ s3Config?: S3Config;
58
+ nodeId?: string;
59
+ syncIntervalMs?: number;
60
+ snapshotEveryNLogs?: number;
61
+ maxBatchSize?: number;
62
+ compression?: boolean;
63
+ encryption?: EncryptionConfig;
64
+ retryConfig?: RetryConfig;
65
+ autoSync?: boolean;
66
+ restoreFromS3?: boolean;
67
+ }
68
+
69
+ export interface ChangeLogEntry {
70
+ sequence: number;
71
+ timestamp: number;
72
+ nodeId: string;
73
+ table: string;
74
+ operation: 'insert' | 'update' | 'delete';
75
+ data: string | null;
76
+ synced: 0 | 1;
77
+ }
78
+
79
+ export interface LogBatch {
80
+ version: 1;
81
+ nodeId: string;
82
+ fromSequence: number;
83
+ toSequence: number;
84
+ entries: Array<{
85
+ sequence: number;
86
+ timestamp: number;
87
+ table: string;
88
+ operation: 'insert' | 'update' | 'delete';
89
+ data: Record<string, unknown> | null;
90
+ }>;
91
+ }
92
+
93
+ export interface SyncJob {
94
+ id: string;
95
+ type: 'upload_log' | 'upload_snapshot';
96
+ payload: string;
97
+ status: 'pending' | 'processing' | 'done' | 'failed';
98
+ attempts: number;
99
+ nextRetryAt: number;
100
+ createdAt: number;
101
+ error: string | null;
102
+ }
103
+
104
+ export interface SyncManifest {
105
+ dbName: string;
106
+ nodeId: string;
107
+ latestSnapshotKey: string | null;
108
+ latestSnapshotTimestamp: number | null;
109
+ latestLogSequence: number;
110
+ updatedAt: number;
111
+ }
112
+
113
+ export interface SyncMetrics {
114
+ lastSyncAt: number | null;
115
+ lastSnapshotAt: number | null;
116
+ pendingChanges: number;
117
+ dbSizeBytes: number;
118
+ totalSynced: number;
119
+ syncErrors: number;
120
+ isRunning: boolean;
121
+ }
122
+
123
+ export interface UploadLogPayload {
124
+ fromSequence: number;
125
+ toSequence: number;
126
+ s3Key: string;
127
+ }
128
+
129
+ export interface UploadSnapshotPayload {
130
+ timestamp: number;
131
+ s3Key: string;
132
+ dbPath: string;
133
+ }