@push.rocks/smartdb 2.5.5 → 2.5.7
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/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/index.d.ts +7 -0
- package/dist_ts/index.js +10 -0
- package/dist_ts/ts_local/classes.localsmartdb.d.ts +87 -0
- package/dist_ts/ts_local/classes.localsmartdb.js +169 -0
- package/dist_ts/ts_local/index.d.ts +2 -0
- package/dist_ts/ts_local/index.js +2 -0
- package/dist_ts/ts_local/plugins.d.ts +1 -0
- package/dist_ts/ts_local/plugins.js +3 -0
- package/dist_ts/ts_migration/classes.storagemigrator.d.ts +24 -0
- package/dist_ts/ts_migration/classes.storagemigrator.js +75 -0
- package/dist_ts/ts_migration/index.d.ts +1 -0
- package/dist_ts/ts_migration/index.js +2 -0
- package/dist_ts/ts_migration/migrators/v0_to_v1.d.ts +9 -0
- package/dist_ts/ts_migration/migrators/v0_to_v1.js +225 -0
- package/dist_ts/ts_smartdb/index.d.ts +4 -0
- package/dist_ts/ts_smartdb/index.js +6 -0
- package/dist_ts/ts_smartdb/plugins.d.ts +2 -0
- package/dist_ts/ts_smartdb/plugins.js +4 -0
- package/dist_ts/ts_smartdb/rust-db-bridge.d.ts +122 -0
- package/dist_ts/ts_smartdb/rust-db-bridge.js +113 -0
- package/dist_ts/ts_smartdb/server/SmartdbServer.d.ts +104 -0
- package/dist_ts/ts_smartdb/server/SmartdbServer.js +166 -0
- package/dist_ts/ts_smartdb/server/index.d.ts +2 -0
- package/dist_ts/ts_smartdb/server/index.js +3 -0
- package/dist_ts_debugserver/bundled.d.ts +4 -0
- package/dist_ts_debugserver/bundled.js +12 -0
- package/dist_ts_debugserver/classes.debugserver.d.ts +36 -0
- package/dist_ts_debugserver/classes.debugserver.js +95 -0
- package/dist_ts_debugserver/index.d.ts +2 -0
- package/dist_ts_debugserver/index.js +2 -0
- package/dist_ts_debugserver/plugins.d.ts +2 -0
- package/dist_ts_debugserver/plugins.js +3 -0
- package/dist_ts_debugui/index.d.ts +2 -0
- package/dist_ts_debugui/index.js +2 -0
- package/dist_ts_debugui/plugins.d.ts +1 -0
- package/dist_ts_debugui/plugins.js +2 -0
- package/dist_ts_debugui/smartdb-debugui.d.ts +62 -0
- package/dist_ts_debugui/smartdb-debugui.js +1132 -0
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* autocreated commitinfo by @push.rocks/commitinfo
|
|
3
|
+
*/
|
|
4
|
+
export const commitinfo = {
|
|
5
|
+
name: '@push.rocks/smartdb',
|
|
6
|
+
version: '2.5.7',
|
|
7
|
+
description: 'A MongoDB-compatible embedded database server with wire protocol support, backed by a high-performance Rust engine.'
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxxQkFBcUI7SUFDM0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFIQUFxSDtDQUNuSSxDQUFBIn0=
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { commitinfo } from './00_commitinfo_data.js';
|
|
2
|
+
export * from './ts_smartdb/index.js';
|
|
3
|
+
export { LocalSmartDb } from './ts_local/index.js';
|
|
4
|
+
export type { ILocalSmartDbOptions, ILocalSmartDbConnectionInfo } from './ts_local/index.js';
|
|
5
|
+
export { StorageMigrator } from './ts_migration/index.js';
|
|
6
|
+
export { commitinfo };
|
|
7
|
+
export type { IOpLogEntry, IOpLogResult, IOpLogStats, IRevertResult, ICollectionInfo, IDocumentsResult, ISmartDbMetrics, } from './ts_smartdb/index.js';
|
package/dist_ts/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { commitinfo } from './00_commitinfo_data.js';
|
|
2
|
+
// Export core SmartDB module
|
|
3
|
+
export * from './ts_smartdb/index.js';
|
|
4
|
+
// Export LocalSmartDb
|
|
5
|
+
export { LocalSmartDb } from './ts_local/index.js';
|
|
6
|
+
// Export migration
|
|
7
|
+
export { StorageMigrator } from './ts_migration/index.js';
|
|
8
|
+
// Export commitinfo
|
|
9
|
+
export { commitinfo };
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFckQsNkJBQTZCO0FBQzdCLGNBQWMsdUJBQXVCLENBQUM7QUFFdEMsc0JBQXNCO0FBQ3RCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUduRCxtQkFBbUI7QUFDbkIsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRTFELG9CQUFvQjtBQUNwQixPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUMifQ==
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { SmartdbServer } from '../ts_smartdb/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Connection information returned by LocalSmartDb.start()
|
|
4
|
+
*/
|
|
5
|
+
export interface ILocalSmartDbConnectionInfo {
|
|
6
|
+
/** The Unix socket file path */
|
|
7
|
+
socketPath: string;
|
|
8
|
+
/** Connection URI (mongodb:// scheme) ready for MongoClient */
|
|
9
|
+
connectionUri: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ILocalSmartDbOptions {
|
|
12
|
+
/** Required: where to store data */
|
|
13
|
+
folderPath: string;
|
|
14
|
+
/** Optional: custom socket path (default: auto-generated in /tmp) */
|
|
15
|
+
socketPath?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* LocalSmartDb - Lightweight local MongoDB-compatible database using Unix sockets
|
|
19
|
+
*
|
|
20
|
+
* This class wraps SmartdbServer and provides a simple interface for
|
|
21
|
+
* starting a local file-based database server. Returns connection
|
|
22
|
+
* info that you can use with any compatible driver instance.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import { LocalSmartDb } from '@push.rocks/smartdb';
|
|
27
|
+
* import { MongoClient } from 'mongodb';
|
|
28
|
+
*
|
|
29
|
+
* const db = new LocalSmartDb({ folderPath: './data' });
|
|
30
|
+
* const { connectionUri } = await db.start();
|
|
31
|
+
*
|
|
32
|
+
* // Connect with the driver
|
|
33
|
+
* const client = new MongoClient(connectionUri, { directConnection: true });
|
|
34
|
+
* await client.connect();
|
|
35
|
+
*
|
|
36
|
+
* // Use the client
|
|
37
|
+
* const collection = client.db('mydb').collection('users');
|
|
38
|
+
* await collection.insertOne({ name: 'Alice' });
|
|
39
|
+
*
|
|
40
|
+
* // When done
|
|
41
|
+
* await client.close();
|
|
42
|
+
* await db.stop();
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare class LocalSmartDb {
|
|
46
|
+
private options;
|
|
47
|
+
private server;
|
|
48
|
+
private generatedSocketPath;
|
|
49
|
+
constructor(options: ILocalSmartDbOptions);
|
|
50
|
+
/**
|
|
51
|
+
* Generate a unique socket path in /tmp
|
|
52
|
+
*/
|
|
53
|
+
private generateSocketPath;
|
|
54
|
+
/**
|
|
55
|
+
* Check if a Unix socket is alive by attempting to connect.
|
|
56
|
+
*/
|
|
57
|
+
private static isSocketAlive;
|
|
58
|
+
/**
|
|
59
|
+
* Remove stale smartdb-*.sock files from /tmp.
|
|
60
|
+
* A socket is considered stale if connecting to it fails.
|
|
61
|
+
*/
|
|
62
|
+
private static cleanStaleSockets;
|
|
63
|
+
/**
|
|
64
|
+
* Start the local SmartDB server and return connection info
|
|
65
|
+
*/
|
|
66
|
+
start(): Promise<ILocalSmartDbConnectionInfo>;
|
|
67
|
+
/**
|
|
68
|
+
* Get connection info (throws if not started)
|
|
69
|
+
*/
|
|
70
|
+
getConnectionInfo(): ILocalSmartDbConnectionInfo;
|
|
71
|
+
/**
|
|
72
|
+
* Get the underlying SmartdbServer instance (throws if not started)
|
|
73
|
+
*/
|
|
74
|
+
getServer(): SmartdbServer;
|
|
75
|
+
/**
|
|
76
|
+
* Get the connection URI
|
|
77
|
+
*/
|
|
78
|
+
getConnectionUri(): string;
|
|
79
|
+
/**
|
|
80
|
+
* Check if the server is running
|
|
81
|
+
*/
|
|
82
|
+
get running(): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Stop the local SmartDB server
|
|
85
|
+
*/
|
|
86
|
+
stop(): Promise<void>;
|
|
87
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import * as crypto from 'crypto';
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
import * as net from 'net';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import * as os from 'os';
|
|
6
|
+
import { SmartdbServer } from '../ts_smartdb/index.js';
|
|
7
|
+
import { StorageMigrator } from '../ts_migration/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* LocalSmartDb - Lightweight local MongoDB-compatible database using Unix sockets
|
|
10
|
+
*
|
|
11
|
+
* This class wraps SmartdbServer and provides a simple interface for
|
|
12
|
+
* starting a local file-based database server. Returns connection
|
|
13
|
+
* info that you can use with any compatible driver instance.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { LocalSmartDb } from '@push.rocks/smartdb';
|
|
18
|
+
* import { MongoClient } from 'mongodb';
|
|
19
|
+
*
|
|
20
|
+
* const db = new LocalSmartDb({ folderPath: './data' });
|
|
21
|
+
* const { connectionUri } = await db.start();
|
|
22
|
+
*
|
|
23
|
+
* // Connect with the driver
|
|
24
|
+
* const client = new MongoClient(connectionUri, { directConnection: true });
|
|
25
|
+
* await client.connect();
|
|
26
|
+
*
|
|
27
|
+
* // Use the client
|
|
28
|
+
* const collection = client.db('mydb').collection('users');
|
|
29
|
+
* await collection.insertOne({ name: 'Alice' });
|
|
30
|
+
*
|
|
31
|
+
* // When done
|
|
32
|
+
* await client.close();
|
|
33
|
+
* await db.stop();
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export class LocalSmartDb {
|
|
37
|
+
constructor(options) {
|
|
38
|
+
this.server = null;
|
|
39
|
+
this.generatedSocketPath = null;
|
|
40
|
+
this.options = options;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Generate a unique socket path in /tmp
|
|
44
|
+
*/
|
|
45
|
+
generateSocketPath() {
|
|
46
|
+
const randomId = crypto.randomBytes(8).toString('hex');
|
|
47
|
+
return path.join(os.tmpdir(), `smartdb-${randomId}.sock`);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if a Unix socket is alive by attempting to connect.
|
|
51
|
+
*/
|
|
52
|
+
static isSocketAlive(socketPath) {
|
|
53
|
+
return new Promise((resolve) => {
|
|
54
|
+
const client = net.createConnection({ path: socketPath }, () => {
|
|
55
|
+
client.destroy();
|
|
56
|
+
resolve(true);
|
|
57
|
+
});
|
|
58
|
+
client.on('error', () => {
|
|
59
|
+
resolve(false);
|
|
60
|
+
});
|
|
61
|
+
client.setTimeout(500, () => {
|
|
62
|
+
client.destroy();
|
|
63
|
+
resolve(false);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Remove stale smartdb-*.sock files from /tmp.
|
|
69
|
+
* A socket is considered stale if connecting to it fails.
|
|
70
|
+
*/
|
|
71
|
+
static async cleanStaleSockets() {
|
|
72
|
+
const tmpDir = os.tmpdir();
|
|
73
|
+
let entries;
|
|
74
|
+
try {
|
|
75
|
+
entries = await fs.readdir(tmpDir);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const socketFiles = entries.filter((f) => f.startsWith('smartdb-') && f.endsWith('.sock'));
|
|
81
|
+
for (const name of socketFiles) {
|
|
82
|
+
const fullPath = path.join(tmpDir, name);
|
|
83
|
+
try {
|
|
84
|
+
const stat = await fs.stat(fullPath);
|
|
85
|
+
if (!stat.isSocket())
|
|
86
|
+
continue;
|
|
87
|
+
const alive = await LocalSmartDb.isSocketAlive(fullPath);
|
|
88
|
+
if (!alive) {
|
|
89
|
+
await fs.unlink(fullPath);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// File may have been removed already; ignore
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Start the local SmartDB server and return connection info
|
|
99
|
+
*/
|
|
100
|
+
async start() {
|
|
101
|
+
if (this.server) {
|
|
102
|
+
throw new Error('LocalSmartDb is already running');
|
|
103
|
+
}
|
|
104
|
+
// Clean up stale sockets from previous crashed instances
|
|
105
|
+
await LocalSmartDb.cleanStaleSockets();
|
|
106
|
+
// Run storage migration before starting the Rust engine
|
|
107
|
+
const migrator = new StorageMigrator(this.options.folderPath);
|
|
108
|
+
await migrator.run();
|
|
109
|
+
// Use provided socket path or generate one
|
|
110
|
+
this.generatedSocketPath = this.options.socketPath ?? this.generateSocketPath();
|
|
111
|
+
this.server = new SmartdbServer({
|
|
112
|
+
socketPath: this.generatedSocketPath,
|
|
113
|
+
storage: 'file',
|
|
114
|
+
storagePath: this.options.folderPath,
|
|
115
|
+
});
|
|
116
|
+
await this.server.start();
|
|
117
|
+
return {
|
|
118
|
+
socketPath: this.generatedSocketPath,
|
|
119
|
+
connectionUri: this.server.getConnectionUri(),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Get connection info (throws if not started)
|
|
124
|
+
*/
|
|
125
|
+
getConnectionInfo() {
|
|
126
|
+
if (!this.server || !this.generatedSocketPath) {
|
|
127
|
+
throw new Error('LocalSmartDb is not running. Call start() first.');
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
socketPath: this.generatedSocketPath,
|
|
131
|
+
connectionUri: this.server.getConnectionUri(),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get the underlying SmartdbServer instance (throws if not started)
|
|
136
|
+
*/
|
|
137
|
+
getServer() {
|
|
138
|
+
if (!this.server) {
|
|
139
|
+
throw new Error('LocalSmartDb is not running. Call start() first.');
|
|
140
|
+
}
|
|
141
|
+
return this.server;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Get the connection URI
|
|
145
|
+
*/
|
|
146
|
+
getConnectionUri() {
|
|
147
|
+
if (!this.server) {
|
|
148
|
+
throw new Error('LocalSmartDb is not running. Call start() first.');
|
|
149
|
+
}
|
|
150
|
+
return this.server.getConnectionUri();
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Check if the server is running
|
|
154
|
+
*/
|
|
155
|
+
get running() {
|
|
156
|
+
return this.server !== null && this.server.running;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Stop the local SmartDB server
|
|
160
|
+
*/
|
|
161
|
+
async stop() {
|
|
162
|
+
if (this.server) {
|
|
163
|
+
await this.server.stop();
|
|
164
|
+
this.server = null;
|
|
165
|
+
this.generatedSocketPath = null;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5sb2NhbHNtYXJ0ZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy90c19sb2NhbC9jbGFzc2VzLmxvY2Fsc21hcnRkYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUNqQyxPQUFPLEtBQUssRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEtBQUssR0FBRyxNQUFNLEtBQUssQ0FBQztBQUMzQixPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBbUIzRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBMkJHO0FBQ0gsTUFBTSxPQUFPLFlBQVk7SUFLdkIsWUFBWSxPQUE2QjtRQUhqQyxXQUFNLEdBQXlCLElBQUksQ0FBQztRQUNwQyx3QkFBbUIsR0FBa0IsSUFBSSxDQUFDO1FBR2hELElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQ3pCLENBQUM7SUFFRDs7T0FFRztJQUNLLGtCQUFrQjtRQUN4QixNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2RCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLFdBQVcsUUFBUSxPQUFPLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQ7O09BRUc7SUFDSyxNQUFNLENBQUMsYUFBYSxDQUFDLFVBQWtCO1FBQzdDLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUM3QixNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMs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
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { LocalSmartDb } from './classes.localsmartdb.js';
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy90c19sb2NhbC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUMifQ==
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export {};
|
|
2
|
+
// Local module plugins - currently no external dependencies needed
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3RzX2xvY2FsL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLG1FQUFtRSJ9
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StorageMigrator — runs before the Rust engine starts.
|
|
3
|
+
*
|
|
4
|
+
* Detects the current storage format version and runs the appropriate
|
|
5
|
+
* migration chain. The Rust engine only knows the current format (v1).
|
|
6
|
+
*
|
|
7
|
+
* Migration is safe: original files are never modified or deleted.
|
|
8
|
+
* On success, a console hint is printed about which old files can be removed.
|
|
9
|
+
*/
|
|
10
|
+
export declare class StorageMigrator {
|
|
11
|
+
private storagePath;
|
|
12
|
+
constructor(storagePath: string);
|
|
13
|
+
/**
|
|
14
|
+
* Run any needed migrations. Safe to call even if storage is already current.
|
|
15
|
+
*/
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Detect the storage format version by inspecting the directory structure.
|
|
19
|
+
*
|
|
20
|
+
* v0: {db}/{coll}.json files exist
|
|
21
|
+
* v1: {db}/{coll}/data.rdb directories exist
|
|
22
|
+
*/
|
|
23
|
+
private detectVersion;
|
|
24
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { migrateV0ToV1 } from './migrators/v0_to_v1.js';
|
|
4
|
+
/**
|
|
5
|
+
* StorageMigrator — runs before the Rust engine starts.
|
|
6
|
+
*
|
|
7
|
+
* Detects the current storage format version and runs the appropriate
|
|
8
|
+
* migration chain. The Rust engine only knows the current format (v1).
|
|
9
|
+
*
|
|
10
|
+
* Migration is safe: original files are never modified or deleted.
|
|
11
|
+
* On success, a console hint is printed about which old files can be removed.
|
|
12
|
+
*/
|
|
13
|
+
export class StorageMigrator {
|
|
14
|
+
constructor(storagePath) {
|
|
15
|
+
this.storagePath = storagePath;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Run any needed migrations. Safe to call even if storage is already current.
|
|
19
|
+
*/
|
|
20
|
+
async run() {
|
|
21
|
+
if (!fs.existsSync(this.storagePath)) {
|
|
22
|
+
return; // No data yet — nothing to migrate
|
|
23
|
+
}
|
|
24
|
+
const version = this.detectVersion();
|
|
25
|
+
if (version === 1) {
|
|
26
|
+
return; // Already current
|
|
27
|
+
}
|
|
28
|
+
if (version === 0) {
|
|
29
|
+
console.log(`[smartdb] Detected v0 (JSON) storage format at ${this.storagePath}`);
|
|
30
|
+
console.log(`[smartdb] Running migration v0 → v1 (Bitcask binary format)...`);
|
|
31
|
+
const deletableFiles = await migrateV0ToV1(this.storagePath);
|
|
32
|
+
if (deletableFiles.length > 0) {
|
|
33
|
+
console.log(`[smartdb] Migration v0 → v1 complete.`);
|
|
34
|
+
console.log(`[smartdb] The following old files can be safely deleted:`);
|
|
35
|
+
for (const f of deletableFiles) {
|
|
36
|
+
console.log(`[smartdb] ${f}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.log(`[smartdb] Migration v0 → v1 complete. No old files to clean up.`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Detect the storage format version by inspecting the directory structure.
|
|
46
|
+
*
|
|
47
|
+
* v0: {db}/{coll}.json files exist
|
|
48
|
+
* v1: {db}/{coll}/data.rdb directories exist
|
|
49
|
+
*/
|
|
50
|
+
detectVersion() {
|
|
51
|
+
const entries = fs.readdirSync(this.storagePath, { withFileTypes: true });
|
|
52
|
+
for (const entry of entries) {
|
|
53
|
+
if (!entry.isDirectory())
|
|
54
|
+
continue;
|
|
55
|
+
const dbDir = path.join(this.storagePath, entry.name);
|
|
56
|
+
const dbEntries = fs.readdirSync(dbDir, { withFileTypes: true });
|
|
57
|
+
for (const dbEntry of dbEntries) {
|
|
58
|
+
// v1: subdirectory with data.rdb
|
|
59
|
+
if (dbEntry.isDirectory()) {
|
|
60
|
+
const dataRdb = path.join(dbDir, dbEntry.name, 'data.rdb');
|
|
61
|
+
if (fs.existsSync(dataRdb)) {
|
|
62
|
+
return 1;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// v0: .json file (not .indexes.json)
|
|
66
|
+
if (dbEntry.isFile() && dbEntry.name.endsWith('.json') && !dbEntry.name.endsWith('.indexes.json')) {
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Empty or unrecognized — treat as v1 (fresh start)
|
|
72
|
+
return 1;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zdG9yYWdlbWlncmF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy90c19taWdyYXRpb24vY2xhc3Nlcy5zdG9yYWdlbWlncmF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUM7QUFDekIsT0FBTyxLQUFLLElBQUksTUFBTSxNQUFNLENBQUM7QUFDN0IsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBU3hEOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxPQUFPLGVBQWU7SUFHMUIsWUFBWSxXQUFtQjtRQUM3QixJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsR0FBRztRQUNQLElBQUksQ0FBQyxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO1lBQ3JDLE9BQU8sQ0FBQyxtQ0FBbUM7UUFDN0MsQ0FBQztRQUVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUVyQyxJQUFJLE9BQU8sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNsQixPQUFPLENBQUMsa0JBQWtCO1FBQzVCLENBQUM7UUFFRCxJQUFJLE9BQU8sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNsQixPQUFPLENBQUMsR0FBRyxDQUFDLGtEQUFrRCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUNsRixPQUFPLENBQUMsR0FBRyxDQUFDLGdFQUFnRSxDQUFDLENBQUM7WUFFOUUsTUFBTSxjQUFjLEdBQUcsTUFBTSxhQUFhLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBRTdELElBQUksY0FBYyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDOUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFDO2dCQUNyRCxPQUFPLENBQUMsR0FBRyxDQUFDLDBEQUEwRCxDQUFDLENBQUM7Z0JBQ3hFLEtBQUssTUFBTSxDQUFDLElBQUksY0FBYyxFQUFFLENBQUM7b0JBQy9CLE9BQU8sQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNsQyxDQUFDO1lBQ0gsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUVBQWlFLENBQUMsQ0FBQztZQUNqRixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLGFBQWE7UUFDbkIsTUFBTSxPQUFPLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLEVBQUUsYUFBYSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFFMUUsS0FBSyxNQUFNLEtBQUssSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUM1QixJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRTtnQkFBRSxTQUFTO1lBRW5DLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdEQsTUFBTSxTQUFTLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUVqRSxLQUFLLE1BQU0sT0FBTyxJQUFJLFNBQVMsRUFBRSxDQUFDO2dCQUNoQyxpQ0FBaUM7Z0JBQ2pDLElBQUksT0FBTyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7b0JBQzFCLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7b0JBQzNELElBQUksRUFBRSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO3dCQUMzQixPQUFPLENBQUMsQ0FBQztvQkFDWCxDQUFDO2dCQUNILENBQUM7Z0JBQ0QscUNBQXFDO2dCQUNyQyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGVBQWUsQ0FBQyxFQUFFLENBQUM7b0JBQ2xHLE9BQU8sQ0FBQyxDQUFDO2dCQUNYLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUVELG9EQUFvRDtRQUNwRCxPQUFPLENBQUMsQ0FBQztJQUNYLENBQUM7Q0FDRiJ9
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StorageMigrator } from './classes.storagemigrator.js';
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { StorageMigrator } from './classes.storagemigrator.js';
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy90c19taWdyYXRpb24vaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDhCQUE4QixDQUFDIn0=
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Migrate a storage directory from v0 (JSON-per-collection) to v1 (Bitcask binary).
|
|
3
|
+
*
|
|
4
|
+
* - Original .json files are NOT modified or deleted.
|
|
5
|
+
* - New v1 files are written into {db}/{coll}/ subdirectories.
|
|
6
|
+
* - Returns a list of old files that can be safely deleted.
|
|
7
|
+
* - On failure, cleans up any partial new files and throws.
|
|
8
|
+
*/
|
|
9
|
+
export declare function migrateV0ToV1(storagePath: string): Promise<string[]>;
|