@framers/sql-storage-adapter 0.1.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.
- package/LICENSE +21 -0
- package/README.md +363 -0
- package/dist/adapters/baseStorageAdapter.d.ts +204 -0
- package/dist/adapters/baseStorageAdapter.d.ts.map +1 -0
- package/dist/adapters/baseStorageAdapter.js +364 -0
- package/dist/adapters/baseStorageAdapter.js.map +1 -0
- package/dist/adapters/betterSqliteAdapter.d.ts +64 -0
- package/dist/adapters/betterSqliteAdapter.d.ts.map +1 -0
- package/dist/adapters/betterSqliteAdapter.js +206 -0
- package/dist/adapters/betterSqliteAdapter.js.map +1 -0
- package/dist/adapters/capacitorSqliteAdapter.d.ts +33 -0
- package/dist/adapters/capacitorSqliteAdapter.d.ts.map +1 -0
- package/dist/adapters/capacitorSqliteAdapter.js +95 -0
- package/dist/adapters/capacitorSqliteAdapter.js.map +1 -0
- package/dist/adapters/postgresAdapter.d.ts +180 -0
- package/dist/adapters/postgresAdapter.d.ts.map +1 -0
- package/dist/adapters/postgresAdapter.js +271 -0
- package/dist/adapters/postgresAdapter.js.map +1 -0
- package/dist/adapters/sqlJsAdapter.d.ts +28 -0
- package/dist/adapters/sqlJsAdapter.d.ts.map +1 -0
- package/dist/adapters/sqlJsAdapter.js +136 -0
- package/dist/adapters/sqlJsAdapter.js.map +1 -0
- package/dist/adapters/supabase.d.ts +58 -0
- package/dist/adapters/supabase.d.ts.map +1 -0
- package/dist/adapters/supabase.js +385 -0
- package/dist/adapters/supabase.js.map +1 -0
- package/dist/database.d.ts +124 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +136 -0
- package/dist/database.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/resolver.d.ts +24 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +91 -0
- package/dist/resolver.js.map +1 -0
- package/dist/types/context.d.ts +221 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/context.js +9 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/events.d.ts +225 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +8 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/extensions.d.ts +73 -0
- package/dist/types/extensions.d.ts.map +1 -0
- package/dist/types/extensions.js +7 -0
- package/dist/types/extensions.js.map +1 -0
- package/dist/types/limitations.d.ts +46 -0
- package/dist/types/limitations.d.ts.map +1 -0
- package/dist/types/limitations.js +154 -0
- package/dist/types/limitations.js.map +1 -0
- package/dist/types.d.ts +235 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cloudBackup.d.ts +219 -0
- package/dist/utils/cloudBackup.d.ts.map +1 -0
- package/dist/utils/cloudBackup.js +289 -0
- package/dist/utils/cloudBackup.js.map +1 -0
- package/dist/utils/dataExport.d.ts +77 -0
- package/dist/utils/dataExport.d.ts.map +1 -0
- package/dist/utils/dataExport.js +212 -0
- package/dist/utils/dataExport.js.map +1 -0
- package/dist/utils/dataImport.d.ts +54 -0
- package/dist/utils/dataImport.d.ts.map +1 -0
- package/dist/utils/dataImport.js +324 -0
- package/dist/utils/dataImport.js.map +1 -0
- package/dist/utils/migration.d.ts +89 -0
- package/dist/utils/migration.d.ts.map +1 -0
- package/dist/utils/migration.js +184 -0
- package/dist/utils/migration.js.map +1 -0
- package/dist/utils/parameterUtils.d.ts +9 -0
- package/dist/utils/parameterUtils.d.ts.map +1 -0
- package/dist/utils/parameterUtils.js +17 -0
- package/dist/utils/parameterUtils.js.map +1 -0
- package/dist/utils/syncManager.d.ts +342 -0
- package/dist/utils/syncManager.d.ts.map +1 -0
- package/dist/utils/syncManager.js +533 -0
- package/dist/utils/syncManager.js.map +1 -0
- package/package.json +108 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud backup utilities for S3, R2, and other object storage providers.
|
|
3
|
+
*
|
|
4
|
+
* This module provides automatic scheduled backups and restore functionality
|
|
5
|
+
* for SQL databases using S3-compatible storage (AWS S3, Cloudflare R2, MinIO, etc.).
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Automatic scheduled backups with configurable intervals
|
|
9
|
+
* - Gzip compression to reduce storage costs
|
|
10
|
+
* - Retention policies (automatic cleanup of old backups)
|
|
11
|
+
* - JSON and SQL export formats
|
|
12
|
+
* - Manual backup/restore on demand
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { S3Client } from '@aws-sdk/client-s3';
|
|
17
|
+
* import { createCloudBackupManager } from '@framers/sql-storage-adapter';
|
|
18
|
+
*
|
|
19
|
+
* const s3Client = new S3Client({ region: 'us-east-1' });
|
|
20
|
+
* const manager = createCloudBackupManager(db, s3Client, 'my-backups', {
|
|
21
|
+
* interval: 3600000, // 1 hour
|
|
22
|
+
* maxBackups: 24,
|
|
23
|
+
* options: { compression: 'gzip', format: 'json' }
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* manager.start(); // Auto-schedule backups
|
|
27
|
+
* await manager.backupNow(); // Manual backup
|
|
28
|
+
* await manager.restore('backups/db-2024-01-15.json.gz');
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @module cloudBackup
|
|
32
|
+
*/
|
|
33
|
+
import { exportAsJSON, exportAsSQL } from './dataExport';
|
|
34
|
+
import { importFromJSON, importFromSQL } from './dataImport';
|
|
35
|
+
/**
|
|
36
|
+
* S3-compatible cloud storage provider.
|
|
37
|
+
*
|
|
38
|
+
* Works with AWS S3, Cloudflare R2, MinIO, and other S3-compatible services.
|
|
39
|
+
* Uses the AWS SDK v3 for S3 operations.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* import { S3Client } from '@aws-sdk/client-s3';
|
|
44
|
+
*
|
|
45
|
+
* const s3Client = new S3Client({ region: 'us-east-1' });
|
|
46
|
+
* const provider = new S3StorageProvider(s3Client, 'my-bucket');
|
|
47
|
+
*
|
|
48
|
+
* await provider.upload('backups/test.json', JSON.stringify(data));
|
|
49
|
+
* const backups = await provider.list('backups/');
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export class S3StorageProvider {
|
|
53
|
+
/**
|
|
54
|
+
* @param client - AWS SDK S3Client instance
|
|
55
|
+
* @param bucket - S3 bucket name
|
|
56
|
+
*/
|
|
57
|
+
constructor(client, bucket) {
|
|
58
|
+
this.client = client;
|
|
59
|
+
this.bucket = bucket;
|
|
60
|
+
}
|
|
61
|
+
async upload(key, data) {
|
|
62
|
+
const { PutObjectCommand } = await import('@aws-sdk/client-s3');
|
|
63
|
+
await this.client.send(new PutObjectCommand({
|
|
64
|
+
Bucket: this.bucket,
|
|
65
|
+
Key: key,
|
|
66
|
+
Body: data,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
async download(key) {
|
|
70
|
+
const { GetObjectCommand } = await import('@aws-sdk/client-s3');
|
|
71
|
+
const response = await this.client.send(new GetObjectCommand({
|
|
72
|
+
Bucket: this.bucket,
|
|
73
|
+
Key: key,
|
|
74
|
+
}));
|
|
75
|
+
// Handle different SDK versions
|
|
76
|
+
if (response.Body.transformToString) {
|
|
77
|
+
return await response.Body.transformToString();
|
|
78
|
+
}
|
|
79
|
+
return response.Body.toString('utf-8');
|
|
80
|
+
}
|
|
81
|
+
async list(prefix) {
|
|
82
|
+
const { ListObjectsV2Command } = await import('@aws-sdk/client-s3');
|
|
83
|
+
const response = await this.client.send(new ListObjectsV2Command({
|
|
84
|
+
Bucket: this.bucket,
|
|
85
|
+
Prefix: prefix,
|
|
86
|
+
}));
|
|
87
|
+
return response.Contents?.map((obj) => obj.Key).filter((key) => !!key) ?? [];
|
|
88
|
+
}
|
|
89
|
+
async delete(key) {
|
|
90
|
+
const { DeleteObjectCommand } = await import('@aws-sdk/client-s3');
|
|
91
|
+
await this.client.send(new DeleteObjectCommand({
|
|
92
|
+
Bucket: this.bucket,
|
|
93
|
+
Key: key,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Compress data using gzip.
|
|
99
|
+
*/
|
|
100
|
+
async function compress(data) {
|
|
101
|
+
const { gzip } = await import('zlib');
|
|
102
|
+
const { promisify } = await import('util');
|
|
103
|
+
const gzipAsync = promisify(gzip);
|
|
104
|
+
return await gzipAsync(Buffer.from(data));
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Decompress gzipped data.
|
|
108
|
+
*/
|
|
109
|
+
async function decompress(data) {
|
|
110
|
+
const { gunzip } = await import('zlib');
|
|
111
|
+
const { promisify } = await import('util');
|
|
112
|
+
const gunzipAsync = promisify(gunzip);
|
|
113
|
+
const decompressed = await gunzipAsync(data);
|
|
114
|
+
return decompressed.toString('utf-8');
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Cloud backup manager for automatic scheduled backups.
|
|
118
|
+
*/
|
|
119
|
+
export class CloudBackupManager {
|
|
120
|
+
constructor(adapter, storage, config) {
|
|
121
|
+
this.adapter = adapter;
|
|
122
|
+
this.storage = storage;
|
|
123
|
+
this.config = config;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Create a backup and upload to cloud storage.
|
|
127
|
+
*/
|
|
128
|
+
async backup(options = {}) {
|
|
129
|
+
const format = options.format ?? this.config.options?.format ?? 'json';
|
|
130
|
+
const compression = options.compression ?? this.config.options?.compression ?? 'none';
|
|
131
|
+
const tables = options.tables ?? this.config.options?.tables;
|
|
132
|
+
const prefix = options.prefix ?? this.config.options?.prefix ?? 'backups/';
|
|
133
|
+
const includeTimestamp = options.includeTimestamp ?? this.config.options?.includeTimestamp ?? true;
|
|
134
|
+
// Export data
|
|
135
|
+
let data;
|
|
136
|
+
if (format === 'json') {
|
|
137
|
+
data = await exportAsJSON(this.adapter, { tables });
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
data = await exportAsSQL(this.adapter, { tables });
|
|
141
|
+
}
|
|
142
|
+
// Compress if needed
|
|
143
|
+
let uploadData = data;
|
|
144
|
+
if (compression === 'gzip') {
|
|
145
|
+
uploadData = await compress(data);
|
|
146
|
+
}
|
|
147
|
+
// Generate key
|
|
148
|
+
const timestamp = includeTimestamp ? `-${new Date().toISOString().replace(/[:.]/g, '-')}` : '';
|
|
149
|
+
const ext = format === 'json' ? 'json' : 'sql';
|
|
150
|
+
const compExt = compression === 'gzip' ? '.gz' : '';
|
|
151
|
+
const key = `${prefix}backup${timestamp}.${ext}${compExt}`;
|
|
152
|
+
// Upload
|
|
153
|
+
await this.storage.upload(key, uploadData);
|
|
154
|
+
// Cleanup old backups if needed
|
|
155
|
+
if (this.config.maxBackups) {
|
|
156
|
+
await this.cleanupOldBackups(prefix);
|
|
157
|
+
}
|
|
158
|
+
return key;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Restore from a cloud backup.
|
|
162
|
+
*/
|
|
163
|
+
async restore(key) {
|
|
164
|
+
// Download
|
|
165
|
+
const data = await this.storage.download(key);
|
|
166
|
+
// Decompress if needed
|
|
167
|
+
let restored;
|
|
168
|
+
if (key.endsWith('.gz')) {
|
|
169
|
+
restored = await decompress(Buffer.from(data));
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
restored = typeof data === 'string' ? data : data.toString('utf-8');
|
|
173
|
+
}
|
|
174
|
+
// Import
|
|
175
|
+
if (key.includes('.json')) {
|
|
176
|
+
await importFromJSON(this.adapter, restored);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
await importFromSQL(this.adapter, restored);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* List all backups in cloud storage.
|
|
184
|
+
*/
|
|
185
|
+
async listBackups(prefix) {
|
|
186
|
+
const searchPrefix = prefix ?? this.config.options?.prefix ?? 'backups/';
|
|
187
|
+
return await this.storage.list(searchPrefix);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Delete old backups exceeding maxBackups limit.
|
|
191
|
+
*/
|
|
192
|
+
async cleanupOldBackups(prefix) {
|
|
193
|
+
if (!this.config.maxBackups)
|
|
194
|
+
return;
|
|
195
|
+
const backups = await this.storage.list(prefix);
|
|
196
|
+
if (backups.length <= this.config.maxBackups)
|
|
197
|
+
return;
|
|
198
|
+
// Sort by name (timestamp) and delete oldest
|
|
199
|
+
const sorted = backups.sort();
|
|
200
|
+
const toDelete = sorted.slice(0, backups.length - this.config.maxBackups);
|
|
201
|
+
for (const key of toDelete) {
|
|
202
|
+
await this.storage.delete(key);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Start automatic scheduled backups.
|
|
207
|
+
*/
|
|
208
|
+
start() {
|
|
209
|
+
if (this.intervalId) {
|
|
210
|
+
throw new Error('Scheduled backups already started');
|
|
211
|
+
}
|
|
212
|
+
this.intervalId = setInterval(async () => {
|
|
213
|
+
try {
|
|
214
|
+
const key = await this.backup();
|
|
215
|
+
this.config.onSuccess?.(key);
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
this.config.onError?.(error);
|
|
219
|
+
}
|
|
220
|
+
}, this.config.interval);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Stop automatic scheduled backups.
|
|
224
|
+
*/
|
|
225
|
+
stop() {
|
|
226
|
+
if (this.intervalId) {
|
|
227
|
+
clearInterval(this.intervalId);
|
|
228
|
+
this.intervalId = undefined;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Perform a backup immediately (manual trigger).
|
|
233
|
+
*/
|
|
234
|
+
async backupNow(options) {
|
|
235
|
+
return await this.backup(options);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Create a cloud backup manager with S3-compatible storage.
|
|
240
|
+
*
|
|
241
|
+
* This is the main factory function for setting up cloud backups.
|
|
242
|
+
* It creates an S3StorageProvider and CloudBackupManager configured
|
|
243
|
+
* with your database and S3-compatible storage.
|
|
244
|
+
*
|
|
245
|
+
* @param adapter - The StorageAdapter instance to backup
|
|
246
|
+
* @param s3Client - AWS SDK S3Client (works with S3, R2, MinIO, etc.)
|
|
247
|
+
* @param bucket - The S3 bucket name
|
|
248
|
+
* @param config - Scheduled backup configuration
|
|
249
|
+
* @returns CloudBackupManager instance ready to start
|
|
250
|
+
*
|
|
251
|
+
* @example AWS S3
|
|
252
|
+
* ```typescript
|
|
253
|
+
* import { S3Client } from '@aws-sdk/client-s3';
|
|
254
|
+
* import { createCloudBackupManager } from '@framers/sql-storage-adapter';
|
|
255
|
+
*
|
|
256
|
+
* const s3 = new S3Client({ region: 'us-east-1' });
|
|
257
|
+
* const manager = createCloudBackupManager(db, s3, 'my-bucket', {
|
|
258
|
+
* interval: 60 * 60 * 1000, // 1 hour
|
|
259
|
+
* maxBackups: 24,
|
|
260
|
+
* options: { compression: 'gzip' }
|
|
261
|
+
* });
|
|
262
|
+
*
|
|
263
|
+
* manager.start();
|
|
264
|
+
* ```
|
|
265
|
+
*
|
|
266
|
+
* @example Cloudflare R2
|
|
267
|
+
* ```typescript
|
|
268
|
+
* import { S3Client } from '@aws-sdk/client-s3';
|
|
269
|
+
*
|
|
270
|
+
* const r2 = new S3Client({
|
|
271
|
+
* region: 'auto',
|
|
272
|
+
* endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
|
|
273
|
+
* credentials: {
|
|
274
|
+
* accessKeyId: process.env.R2_ACCESS_KEY_ID,
|
|
275
|
+
* secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,
|
|
276
|
+
* },
|
|
277
|
+
* });
|
|
278
|
+
*
|
|
279
|
+
* const manager = createCloudBackupManager(db, r2, 'backups', {
|
|
280
|
+
* interval: 24 * 60 * 60 * 1000, // Daily
|
|
281
|
+
* maxBackups: 7
|
|
282
|
+
* });
|
|
283
|
+
* ```
|
|
284
|
+
*/
|
|
285
|
+
export function createCloudBackupManager(adapter, s3Client, bucket, config) {
|
|
286
|
+
const storage = new S3StorageProvider(s3Client, bucket);
|
|
287
|
+
return new CloudBackupManager(adapter, storage, config);
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=cloudBackup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudBackup.js","sourceRoot":"","sources":["../../src/utils/cloudBackup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data export utilities for cross-adapter migration and backup.
|
|
3
|
+
* Supports exporting data to portable formats (JSON, SQL, CSV).
|
|
4
|
+
*/
|
|
5
|
+
import type { StorageAdapter } from '../types';
|
|
6
|
+
/**
|
|
7
|
+
* Export format types.
|
|
8
|
+
*/
|
|
9
|
+
export type ExportFormat = 'json' | 'sql' | 'csv';
|
|
10
|
+
/**
|
|
11
|
+
* Options for data export.
|
|
12
|
+
*/
|
|
13
|
+
export interface DataExportOptions {
|
|
14
|
+
/** Tables to export (all if not specified) */
|
|
15
|
+
tables?: string[];
|
|
16
|
+
/** Include schema/DDL statements */
|
|
17
|
+
includeSchema?: boolean;
|
|
18
|
+
/** Format for export */
|
|
19
|
+
format?: ExportFormat;
|
|
20
|
+
/** Batch size for large exports */
|
|
21
|
+
batchSize?: number;
|
|
22
|
+
/** Whether to pretty-print JSON */
|
|
23
|
+
pretty?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Exported data structure.
|
|
27
|
+
*/
|
|
28
|
+
export interface ExportedData {
|
|
29
|
+
version: string;
|
|
30
|
+
exportedAt: string;
|
|
31
|
+
adapter: string;
|
|
32
|
+
schema?: TableSchema[];
|
|
33
|
+
data: Record<string, unknown[]>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Table schema information.
|
|
37
|
+
*/
|
|
38
|
+
export interface TableSchema {
|
|
39
|
+
name: string;
|
|
40
|
+
columns: ColumnInfo[];
|
|
41
|
+
primaryKeys?: string[];
|
|
42
|
+
indexes?: IndexInfo[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Column information.
|
|
46
|
+
*/
|
|
47
|
+
export interface ColumnInfo {
|
|
48
|
+
name: string;
|
|
49
|
+
type: string;
|
|
50
|
+
nullable?: boolean;
|
|
51
|
+
defaultValue?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Index information.
|
|
55
|
+
*/
|
|
56
|
+
export interface IndexInfo {
|
|
57
|
+
name: string;
|
|
58
|
+
columns: string[];
|
|
59
|
+
unique?: boolean;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Export data from an adapter to a portable format.
|
|
63
|
+
*/
|
|
64
|
+
export declare function exportData(adapter: StorageAdapter, options?: DataExportOptions): Promise<ExportedData>;
|
|
65
|
+
/**
|
|
66
|
+
* Export data as JSON string.
|
|
67
|
+
*/
|
|
68
|
+
export declare function exportAsJSON(adapter: StorageAdapter, options?: DataExportOptions): Promise<string>;
|
|
69
|
+
/**
|
|
70
|
+
* Export data as SQL statements.
|
|
71
|
+
*/
|
|
72
|
+
export declare function exportAsSQL(adapter: StorageAdapter, options?: DataExportOptions): Promise<string>;
|
|
73
|
+
/**
|
|
74
|
+
* Export data as CSV (one file per table).
|
|
75
|
+
*/
|
|
76
|
+
export declare function exportAsCSV(adapter: StorageAdapter, options?: DataExportOptions): Promise<Record<string, string>>;
|
|
77
|
+
//# sourceMappingURL=dataExport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataExport.d.ts","sourceRoot":"","sources":["../../src/utils/dataExport.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,oCAAoC;IACpC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,wBAAwB;IACxB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,mCAAmC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,YAAY,CAAC,CAuCvB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,CAAC,CA6BjB;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CA2BjC"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data export utilities for cross-adapter migration and backup.
|
|
3
|
+
* Supports exporting data to portable formats (JSON, SQL, CSV).
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Export data from an adapter to a portable format.
|
|
7
|
+
*/
|
|
8
|
+
export async function exportData(adapter, options = {}) {
|
|
9
|
+
const { tables, includeSchema = true, batchSize = 1000 } = options;
|
|
10
|
+
const exportedData = {
|
|
11
|
+
version: '1.0.0',
|
|
12
|
+
exportedAt: new Date().toISOString(),
|
|
13
|
+
adapter: 'sql-storage-adapter',
|
|
14
|
+
data: {},
|
|
15
|
+
};
|
|
16
|
+
// Get list of tables
|
|
17
|
+
const tablesToExport = tables || (await getTables(adapter));
|
|
18
|
+
// Export schema if requested
|
|
19
|
+
if (includeSchema) {
|
|
20
|
+
exportedData.schema = await Promise.all(tablesToExport.map(table => getTableSchema(adapter, table)));
|
|
21
|
+
}
|
|
22
|
+
// Export data from each table
|
|
23
|
+
for (const table of tablesToExport) {
|
|
24
|
+
const rows = [];
|
|
25
|
+
let offset = 0;
|
|
26
|
+
let batch;
|
|
27
|
+
// Fetch data in batches
|
|
28
|
+
do {
|
|
29
|
+
batch = await adapter.all(`SELECT * FROM ${escapeIdentifier(table)} LIMIT ${batchSize} OFFSET ${offset}`);
|
|
30
|
+
rows.push(...batch);
|
|
31
|
+
offset += batchSize;
|
|
32
|
+
} while (batch.length === batchSize);
|
|
33
|
+
exportedData.data[table] = rows;
|
|
34
|
+
}
|
|
35
|
+
return exportedData;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Export data as JSON string.
|
|
39
|
+
*/
|
|
40
|
+
export async function exportAsJSON(adapter, options = {}) {
|
|
41
|
+
const data = await exportData(adapter, options);
|
|
42
|
+
return JSON.stringify(data, null, options.pretty ? 2 : 0);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Export data as SQL statements.
|
|
46
|
+
*/
|
|
47
|
+
export async function exportAsSQL(adapter, options = {}) {
|
|
48
|
+
const data = await exportData(adapter, options);
|
|
49
|
+
const lines = [];
|
|
50
|
+
lines.push('-- SQL Export from sql-storage-adapter');
|
|
51
|
+
lines.push(`-- Generated at: ${data.exportedAt}`);
|
|
52
|
+
lines.push('');
|
|
53
|
+
// Export schema
|
|
54
|
+
if (data.schema) {
|
|
55
|
+
for (const table of data.schema) {
|
|
56
|
+
lines.push(`-- Table: ${table.name}`);
|
|
57
|
+
lines.push(generateCreateTableSQL(table));
|
|
58
|
+
lines.push('');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Export data
|
|
62
|
+
for (const [tableName, rows] of Object.entries(data.data)) {
|
|
63
|
+
if (rows.length === 0)
|
|
64
|
+
continue;
|
|
65
|
+
lines.push(`-- Data for table: ${tableName}`);
|
|
66
|
+
for (const row of rows) {
|
|
67
|
+
lines.push(generateInsertSQL(tableName, row));
|
|
68
|
+
}
|
|
69
|
+
lines.push('');
|
|
70
|
+
}
|
|
71
|
+
return lines.join('\n');
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Export data as CSV (one file per table).
|
|
75
|
+
*/
|
|
76
|
+
export async function exportAsCSV(adapter, options = {}) {
|
|
77
|
+
const data = await exportData(adapter, options);
|
|
78
|
+
const csvFiles = {};
|
|
79
|
+
for (const [tableName, rows] of Object.entries(data.data)) {
|
|
80
|
+
if (rows.length === 0) {
|
|
81
|
+
csvFiles[tableName] = '';
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const firstRow = rows[0];
|
|
85
|
+
const headers = Object.keys(firstRow);
|
|
86
|
+
const lines = [];
|
|
87
|
+
lines.push(headers.map(escapeCSVValue).join(','));
|
|
88
|
+
for (const row of rows) {
|
|
89
|
+
const values = headers.map(header => escapeCSVValue(String(row[header] ?? '')));
|
|
90
|
+
lines.push(values.join(','));
|
|
91
|
+
}
|
|
92
|
+
csvFiles[tableName] = lines.join('\n');
|
|
93
|
+
}
|
|
94
|
+
return csvFiles;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Get list of tables from adapter.
|
|
98
|
+
*/
|
|
99
|
+
async function getTables(adapter) {
|
|
100
|
+
// Try SQLite/PostgreSQL table query
|
|
101
|
+
try {
|
|
102
|
+
const rows = await adapter.all(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'`);
|
|
103
|
+
return rows.map(r => r.name);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
// Try PostgreSQL
|
|
107
|
+
try {
|
|
108
|
+
const rows = await adapter.all(`SELECT tablename AS name FROM pg_tables WHERE schemaname = 'public'`);
|
|
109
|
+
return rows.map(r => r.name);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
throw new Error('Unable to retrieve table list from adapter');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Get schema for a specific table.
|
|
118
|
+
*/
|
|
119
|
+
async function getTableSchema(adapter, table) {
|
|
120
|
+
try {
|
|
121
|
+
// Try SQLite PRAGMA
|
|
122
|
+
const columns = await adapter.all(`PRAGMA table_info(${escapeIdentifier(table)})`);
|
|
123
|
+
return {
|
|
124
|
+
name: table,
|
|
125
|
+
columns: columns.map(col => ({
|
|
126
|
+
name: col.name,
|
|
127
|
+
type: col.type,
|
|
128
|
+
nullable: col.notnull === 0,
|
|
129
|
+
defaultValue: col.dflt_value ?? undefined,
|
|
130
|
+
})),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Try PostgreSQL information_schema
|
|
135
|
+
try {
|
|
136
|
+
const columns = await adapter.all(`SELECT column_name, data_type, is_nullable, column_default
|
|
137
|
+
FROM information_schema.columns
|
|
138
|
+
WHERE table_name = $1`, [table]);
|
|
139
|
+
return {
|
|
140
|
+
name: table,
|
|
141
|
+
columns: columns.map(col => ({
|
|
142
|
+
name: col.column_name,
|
|
143
|
+
type: col.data_type,
|
|
144
|
+
nullable: col.is_nullable === 'YES',
|
|
145
|
+
defaultValue: col.column_default ?? undefined,
|
|
146
|
+
})),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Fallback: no schema info
|
|
151
|
+
return {
|
|
152
|
+
name: table,
|
|
153
|
+
columns: [],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Generate CREATE TABLE SQL from schema.
|
|
160
|
+
*/
|
|
161
|
+
function generateCreateTableSQL(schema) {
|
|
162
|
+
if (schema.columns.length === 0) {
|
|
163
|
+
return `CREATE TABLE ${escapeIdentifier(schema.name)} ();`;
|
|
164
|
+
}
|
|
165
|
+
const columnDefs = schema.columns.map(col => {
|
|
166
|
+
let def = ` ${escapeIdentifier(col.name)} ${col.type}`;
|
|
167
|
+
if (!col.nullable)
|
|
168
|
+
def += ' NOT NULL';
|
|
169
|
+
if (col.defaultValue)
|
|
170
|
+
def += ` DEFAULT ${col.defaultValue}`;
|
|
171
|
+
return def;
|
|
172
|
+
});
|
|
173
|
+
return `CREATE TABLE ${escapeIdentifier(schema.name)} (\n${columnDefs.join(',\n')}\n);`;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Generate INSERT SQL for a row.
|
|
177
|
+
*/
|
|
178
|
+
function generateInsertSQL(table, row) {
|
|
179
|
+
const columns = Object.keys(row);
|
|
180
|
+
const values = columns.map(col => escapeSQLValue(row[col]));
|
|
181
|
+
return `INSERT INTO ${escapeIdentifier(table)} (${columns.map(escapeIdentifier).join(', ')}) VALUES (${values.join(', ')});`;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Escape SQL identifier (table/column name).
|
|
185
|
+
*/
|
|
186
|
+
function escapeIdentifier(identifier) {
|
|
187
|
+
return `"${identifier.replace(/"/g, '""')}"`;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Escape SQL value for INSERT statement.
|
|
191
|
+
*/
|
|
192
|
+
function escapeSQLValue(value) {
|
|
193
|
+
if (value === null || value === undefined)
|
|
194
|
+
return 'NULL';
|
|
195
|
+
if (typeof value === 'number')
|
|
196
|
+
return String(value);
|
|
197
|
+
if (typeof value === 'boolean')
|
|
198
|
+
return value ? '1' : '0';
|
|
199
|
+
if (value instanceof Date)
|
|
200
|
+
return `'${value.toISOString()}'`;
|
|
201
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Escape CSV value.
|
|
205
|
+
*/
|
|
206
|
+
function escapeCSVValue(value) {
|
|
207
|
+
if (value.includes(',') || value.includes('"') || value.includes('\n')) {
|
|
208
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
209
|
+
}
|
|
210
|
+
return value;
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=dataExport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataExport.js","sourceRoot":"","sources":["../../src/utils/dataExport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data import utilities for cross-adapter migration and restoration.
|
|
3
|
+
* Supports importing from JSON, SQL dumps, and CSV files.
|
|
4
|
+
*/
|
|
5
|
+
import type { StorageAdapter } from '../types';
|
|
6
|
+
import type { ExportedData } from './dataExport';
|
|
7
|
+
/**
|
|
8
|
+
* Options for data import.
|
|
9
|
+
*/
|
|
10
|
+
export interface DataImportOptions {
|
|
11
|
+
/** Drop existing tables before import */
|
|
12
|
+
dropTables?: boolean;
|
|
13
|
+
/** Skip schema creation (data only) */
|
|
14
|
+
skipSchema?: boolean;
|
|
15
|
+
/** Skip data import (schema only) */
|
|
16
|
+
skipData?: boolean;
|
|
17
|
+
/** Batch size for inserts */
|
|
18
|
+
batchSize?: number;
|
|
19
|
+
/** Tables to import (all if not specified) */
|
|
20
|
+
tables?: string[];
|
|
21
|
+
/** On conflict strategy */
|
|
22
|
+
onConflict?: 'replace' | 'ignore' | 'error';
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Import result with statistics.
|
|
26
|
+
*/
|
|
27
|
+
export interface ImportResult {
|
|
28
|
+
success: boolean;
|
|
29
|
+
tablesImported: number;
|
|
30
|
+
rowsImported: number;
|
|
31
|
+
errors?: string[];
|
|
32
|
+
duration: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Import data from exported JSON format.
|
|
36
|
+
*/
|
|
37
|
+
export declare function importData(adapter: StorageAdapter, data: ExportedData, options?: DataImportOptions): Promise<ImportResult>;
|
|
38
|
+
/**
|
|
39
|
+
* Import data from JSON string.
|
|
40
|
+
*/
|
|
41
|
+
export declare function importFromJSON(adapter: StorageAdapter, jsonString: string, options?: DataImportOptions): Promise<ImportResult>;
|
|
42
|
+
/**
|
|
43
|
+
* Import data from SQL dump.
|
|
44
|
+
*/
|
|
45
|
+
export declare function importFromSQL(adapter: StorageAdapter, sqlDump: string, options?: DataImportOptions): Promise<ImportResult>;
|
|
46
|
+
/**
|
|
47
|
+
* Import data from CSV.
|
|
48
|
+
*/
|
|
49
|
+
export declare function importFromCSV(adapter: StorageAdapter, tableName: string, csvContent: string, options?: DataImportOptions): Promise<ImportResult>;
|
|
50
|
+
/**
|
|
51
|
+
* Migrate data from one adapter to another.
|
|
52
|
+
*/
|
|
53
|
+
export declare function migrateAdapter(sourceAdapter: StorageAdapter, targetAdapter: StorageAdapter, options?: DataImportOptions): Promise<ImportResult>;
|
|
54
|
+
//# sourceMappingURL=dataImport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dataImport.d.ts","sourceRoot":"","sources":["../../src/utils/dataImport.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAe,MAAM,cAAc,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uCAAuC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,YAAY,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,YAAY,CAAC,CA4FvB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,YAAY,CAAC,CAavB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,YAAY,CAAC,CAqDvB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,YAAY,CAAC,CAkCvB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,aAAa,EAAE,cAAc,EAC7B,aAAa,EAAE,cAAc,EAC7B,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,YAAY,CAAC,CAWvB"}
|