@push.rocks/smartdb 2.8.0 → 2.10.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/dist_rust/rustdb_linux_amd64 +0 -0
- package/dist_rust/rustdb_linux_arm64 +0 -0
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/index.d.ts +1 -1
- package/dist_ts/ts_smartdb/index.d.ts +1 -0
- package/dist_ts/ts_smartdb/rust-db-bridge.d.ts +15 -1
- package/dist_ts/ts_smartdb/rust-db-bridge.js +27 -2
- package/dist_ts/ts_smartdb/server/SmartdbServer.d.ts +40 -0
- package/dist_ts/ts_smartdb/server/SmartdbServer.js +80 -1
- package/dist_ts/ts_smartdb/service-types.d.ts +57 -0
- package/dist_ts/ts_smartdb/service-types.js +2 -0
- package/dist_ts_debugserver/bundled.js +1 -1
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +10 -0
- package/ts/ts_smartdb/index.ts +14 -0
- package/ts/ts_smartdb/rust-db-bridge.ts +96 -1
- package/ts/ts_smartdb/server/SmartdbServer.ts +112 -0
- package/ts/ts_smartdb/service-types.ts +66 -0
package/package.json
CHANGED
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/index.ts
CHANGED
|
@@ -22,4 +22,14 @@ export type {
|
|
|
22
22
|
ICollectionInfo,
|
|
23
23
|
IDocumentsResult,
|
|
24
24
|
ISmartDbMetrics,
|
|
25
|
+
ISmartDbHealth,
|
|
26
|
+
ISmartDbDatabaseTenantInput,
|
|
27
|
+
ISmartDbDeleteDatabaseTenantInput,
|
|
28
|
+
ISmartDbRotateDatabaseTenantPasswordInput,
|
|
29
|
+
ISmartDbDatabaseTenantDescriptor,
|
|
30
|
+
ISmartDbDeleteDatabaseTenantResult,
|
|
31
|
+
ISmartDbDatabaseExportCollection,
|
|
32
|
+
ISmartDbDatabaseExport,
|
|
33
|
+
ISmartDbImportDatabaseInput,
|
|
34
|
+
ISmartDbImportDatabaseResult,
|
|
25
35
|
} from './ts_smartdb/index.js';
|
package/ts/ts_smartdb/index.ts
CHANGED
|
@@ -22,3 +22,17 @@ export type {
|
|
|
22
22
|
IDocumentsResult,
|
|
23
23
|
ISmartDbMetrics,
|
|
24
24
|
} from './rust-db-bridge.js';
|
|
25
|
+
|
|
26
|
+
// Export service API types
|
|
27
|
+
export type {
|
|
28
|
+
ISmartDbHealth,
|
|
29
|
+
ISmartDbDatabaseTenantInput,
|
|
30
|
+
ISmartDbDeleteDatabaseTenantInput,
|
|
31
|
+
ISmartDbRotateDatabaseTenantPasswordInput,
|
|
32
|
+
ISmartDbDatabaseTenantDescriptor,
|
|
33
|
+
ISmartDbDeleteDatabaseTenantResult,
|
|
34
|
+
ISmartDbDatabaseExportCollection,
|
|
35
|
+
ISmartDbDatabaseExport,
|
|
36
|
+
ISmartDbImportDatabaseInput,
|
|
37
|
+
ISmartDbImportDatabaseResult,
|
|
38
|
+
} from './service-types.js';
|
|
@@ -2,6 +2,30 @@ import * as plugins from './plugins.js';
|
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import * as url from 'url';
|
|
4
4
|
import { EventEmitter } from 'events';
|
|
5
|
+
import type {
|
|
6
|
+
ISmartDbHealth,
|
|
7
|
+
ISmartDbDatabaseTenantInput,
|
|
8
|
+
ISmartDbDeleteDatabaseTenantInput,
|
|
9
|
+
ISmartDbRotateDatabaseTenantPasswordInput,
|
|
10
|
+
ISmartDbDatabaseTenantDescriptor,
|
|
11
|
+
ISmartDbDeleteDatabaseTenantResult,
|
|
12
|
+
ISmartDbDatabaseExport,
|
|
13
|
+
ISmartDbImportDatabaseInput,
|
|
14
|
+
ISmartDbImportDatabaseResult,
|
|
15
|
+
} from './service-types.js';
|
|
16
|
+
|
|
17
|
+
export type {
|
|
18
|
+
ISmartDbHealth,
|
|
19
|
+
ISmartDbDatabaseTenantInput,
|
|
20
|
+
ISmartDbDeleteDatabaseTenantInput,
|
|
21
|
+
ISmartDbRotateDatabaseTenantPasswordInput,
|
|
22
|
+
ISmartDbDatabaseTenantDescriptor,
|
|
23
|
+
ISmartDbDeleteDatabaseTenantResult,
|
|
24
|
+
ISmartDbDatabaseExportCollection,
|
|
25
|
+
ISmartDbDatabaseExport,
|
|
26
|
+
ISmartDbImportDatabaseInput,
|
|
27
|
+
ISmartDbImportDatabaseResult,
|
|
28
|
+
} from './service-types.js';
|
|
5
29
|
|
|
6
30
|
/**
|
|
7
31
|
* A single oplog entry returned from the Rust engine.
|
|
@@ -90,7 +114,36 @@ type TSmartDbCommands = {
|
|
|
90
114
|
start: { params: { config: ISmartDbRustConfig }; result: { connectionUri: string } };
|
|
91
115
|
stop: { params: Record<string, never>; result: void };
|
|
92
116
|
getStatus: { params: Record<string, never>; result: { running: boolean } };
|
|
117
|
+
getHealth: { params: Record<string, never>; result: ISmartDbHealth };
|
|
93
118
|
getMetrics: { params: Record<string, never>; result: ISmartDbMetrics };
|
|
119
|
+
createDatabaseTenant: {
|
|
120
|
+
params: ISmartDbDatabaseTenantInput;
|
|
121
|
+
result: ISmartDbDatabaseTenantDescriptor;
|
|
122
|
+
};
|
|
123
|
+
deleteDatabaseTenant: {
|
|
124
|
+
params: ISmartDbDeleteDatabaseTenantInput;
|
|
125
|
+
result: ISmartDbDeleteDatabaseTenantResult;
|
|
126
|
+
};
|
|
127
|
+
rotateDatabaseTenantPassword: {
|
|
128
|
+
params: ISmartDbRotateDatabaseTenantPasswordInput;
|
|
129
|
+
result: ISmartDbDatabaseTenantDescriptor;
|
|
130
|
+
};
|
|
131
|
+
listDatabaseTenants: {
|
|
132
|
+
params: Record<string, never>;
|
|
133
|
+
result: { tenants: ISmartDbDatabaseTenantDescriptor[] };
|
|
134
|
+
};
|
|
135
|
+
getDatabaseTenantDescriptor: {
|
|
136
|
+
params: { databaseName: string; username: string };
|
|
137
|
+
result: ISmartDbDatabaseTenantDescriptor;
|
|
138
|
+
};
|
|
139
|
+
exportDatabase: {
|
|
140
|
+
params: { databaseName: string };
|
|
141
|
+
result: ISmartDbDatabaseExport;
|
|
142
|
+
};
|
|
143
|
+
importDatabase: {
|
|
144
|
+
params: ISmartDbImportDatabaseInput;
|
|
145
|
+
result: ISmartDbImportDatabaseResult;
|
|
146
|
+
};
|
|
94
147
|
getOpLog: {
|
|
95
148
|
params: { sinceSeq?: number; limit?: number; db?: string; collection?: string };
|
|
96
149
|
result: IOpLogResult;
|
|
@@ -202,7 +255,7 @@ export class RustDbBridge extends EventEmitter {
|
|
|
202
255
|
envVarName: 'SMARTDB_RUST_BINARY',
|
|
203
256
|
platformPackagePrefix: '@push.rocks/smartdb',
|
|
204
257
|
localPaths: buildLocalPaths(),
|
|
205
|
-
maxPayloadSize:
|
|
258
|
+
maxPayloadSize: 100 * 1024 * 1024, // database exports/imports can be larger than command replies
|
|
206
259
|
});
|
|
207
260
|
|
|
208
261
|
// Forward events from the inner bridge
|
|
@@ -251,6 +304,48 @@ export class RustDbBridge extends EventEmitter {
|
|
|
251
304
|
return this.bridge.sendCommand('getMetrics', {} as Record<string, never>) as Promise<ISmartDbMetrics>;
|
|
252
305
|
}
|
|
253
306
|
|
|
307
|
+
public async getHealth(): Promise<ISmartDbHealth> {
|
|
308
|
+
return this.bridge.sendCommand('getHealth', {} as Record<string, never>) as Promise<ISmartDbHealth>;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
public async createDatabaseTenant(
|
|
312
|
+
params: ISmartDbDatabaseTenantInput,
|
|
313
|
+
): Promise<ISmartDbDatabaseTenantDescriptor> {
|
|
314
|
+
return this.bridge.sendCommand('createDatabaseTenant', params) as Promise<ISmartDbDatabaseTenantDescriptor>;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
public async deleteDatabaseTenant(
|
|
318
|
+
params: ISmartDbDeleteDatabaseTenantInput,
|
|
319
|
+
): Promise<ISmartDbDeleteDatabaseTenantResult> {
|
|
320
|
+
return this.bridge.sendCommand('deleteDatabaseTenant', params) as Promise<ISmartDbDeleteDatabaseTenantResult>;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
public async rotateDatabaseTenantPassword(
|
|
324
|
+
params: ISmartDbRotateDatabaseTenantPasswordInput,
|
|
325
|
+
): Promise<ISmartDbDatabaseTenantDescriptor> {
|
|
326
|
+
return this.bridge.sendCommand('rotateDatabaseTenantPassword', params) as Promise<ISmartDbDatabaseTenantDescriptor>;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
public async listDatabaseTenants(): Promise<ISmartDbDatabaseTenantDescriptor[]> {
|
|
330
|
+
const result = await this.bridge.sendCommand('listDatabaseTenants', {} as Record<string, never>) as { tenants: ISmartDbDatabaseTenantDescriptor[] };
|
|
331
|
+
return result.tenants;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
public async getDatabaseTenantDescriptor(params: {
|
|
335
|
+
databaseName: string;
|
|
336
|
+
username: string;
|
|
337
|
+
}): Promise<ISmartDbDatabaseTenantDescriptor> {
|
|
338
|
+
return this.bridge.sendCommand('getDatabaseTenantDescriptor', params) as Promise<ISmartDbDatabaseTenantDescriptor>;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
public async exportDatabase(params: { databaseName: string }): Promise<ISmartDbDatabaseExport> {
|
|
342
|
+
return this.bridge.sendCommand('exportDatabase', params) as Promise<ISmartDbDatabaseExport>;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
public async importDatabase(params: ISmartDbImportDatabaseInput): Promise<ISmartDbImportDatabaseResult> {
|
|
346
|
+
return this.bridge.sendCommand('importDatabase', params) as Promise<ISmartDbImportDatabaseResult>;
|
|
347
|
+
}
|
|
348
|
+
|
|
254
349
|
public async getOpLog(params: {
|
|
255
350
|
sinceSeq?: number;
|
|
256
351
|
limit?: number;
|
|
@@ -9,6 +9,17 @@ import type {
|
|
|
9
9
|
IDocumentsResult,
|
|
10
10
|
ISmartDbMetrics,
|
|
11
11
|
} from '../rust-db-bridge.js';
|
|
12
|
+
import type {
|
|
13
|
+
ISmartDbHealth,
|
|
14
|
+
ISmartDbDatabaseTenantInput,
|
|
15
|
+
ISmartDbDeleteDatabaseTenantInput,
|
|
16
|
+
ISmartDbRotateDatabaseTenantPasswordInput,
|
|
17
|
+
ISmartDbDatabaseTenantDescriptor,
|
|
18
|
+
ISmartDbDeleteDatabaseTenantResult,
|
|
19
|
+
ISmartDbDatabaseExport,
|
|
20
|
+
ISmartDbImportDatabaseInput,
|
|
21
|
+
ISmartDbImportDatabaseResult,
|
|
22
|
+
} from '../service-types.js';
|
|
12
23
|
|
|
13
24
|
/**
|
|
14
25
|
* Server configuration options
|
|
@@ -204,6 +215,85 @@ export class SmartdbServer {
|
|
|
204
215
|
return this.options.host ?? '127.0.0.1';
|
|
205
216
|
}
|
|
206
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Create an isolated database/user pair for an application tenant.
|
|
220
|
+
*/
|
|
221
|
+
async createDatabaseTenant(
|
|
222
|
+
params: ISmartDbDatabaseTenantInput,
|
|
223
|
+
): Promise<ISmartDbDatabaseTenantDescriptor> {
|
|
224
|
+
const descriptor = await this.bridge.createDatabaseTenant(params);
|
|
225
|
+
return this.withTenantMongoUri(descriptor, params.password);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Delete a tenant database and its tenant user(s).
|
|
230
|
+
*/
|
|
231
|
+
async deleteDatabaseTenant(
|
|
232
|
+
params: ISmartDbDeleteDatabaseTenantInput,
|
|
233
|
+
): Promise<ISmartDbDeleteDatabaseTenantResult> {
|
|
234
|
+
return this.bridge.deleteDatabaseTenant(params);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Rotate a tenant user's password without restarting the server.
|
|
239
|
+
*/
|
|
240
|
+
async rotateDatabaseTenantPassword(
|
|
241
|
+
params: ISmartDbRotateDatabaseTenantPasswordInput,
|
|
242
|
+
): Promise<ISmartDbDatabaseTenantDescriptor> {
|
|
243
|
+
const descriptor = await this.bridge.rotateDatabaseTenantPassword(params);
|
|
244
|
+
return this.withTenantMongoUri(descriptor, params.password);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* List known database tenants.
|
|
249
|
+
*/
|
|
250
|
+
async listDatabaseTenants(): Promise<ISmartDbDatabaseTenantDescriptor[]> {
|
|
251
|
+
return this.bridge.listDatabaseTenants();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Get a tenant descriptor without exposing a password.
|
|
256
|
+
*/
|
|
257
|
+
async getDatabaseTenantDescriptor(params: {
|
|
258
|
+
databaseName: string;
|
|
259
|
+
username: string;
|
|
260
|
+
}): Promise<ISmartDbDatabaseTenantDescriptor> {
|
|
261
|
+
return this.bridge.getDatabaseTenantDescriptor(params);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Export one database as an Extended JSON snapshot.
|
|
266
|
+
*/
|
|
267
|
+
async exportDatabase(params: { databaseName: string }): Promise<ISmartDbDatabaseExport> {
|
|
268
|
+
return this.bridge.exportDatabase(params);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Replace one database with a previously exported snapshot.
|
|
273
|
+
*/
|
|
274
|
+
async importDatabase(params: ISmartDbImportDatabaseInput): Promise<ISmartDbImportDatabaseResult> {
|
|
275
|
+
return this.bridge.importDatabase(params);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Get readiness/health details for long-running service use.
|
|
280
|
+
*/
|
|
281
|
+
async getHealth(): Promise<ISmartDbHealth> {
|
|
282
|
+
if (!this.isRunning) {
|
|
283
|
+
return {
|
|
284
|
+
running: false,
|
|
285
|
+
storage: this.options.storage,
|
|
286
|
+
storagePath: this.options.storage === 'file' ? this.options.storagePath : this.options.persistPath,
|
|
287
|
+
authEnabled: Boolean(this.options.auth?.enabled),
|
|
288
|
+
authUsers: this.options.auth?.users?.length ?? 0,
|
|
289
|
+
usersPathConfigured: Boolean(this.options.auth?.usersPath),
|
|
290
|
+
databaseCount: 0,
|
|
291
|
+
collectionCount: 0,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
return this.bridge.getHealth();
|
|
295
|
+
}
|
|
296
|
+
|
|
207
297
|
// --- OpLog / Debug API ---
|
|
208
298
|
|
|
209
299
|
/**
|
|
@@ -258,4 +348,26 @@ export class SmartdbServer {
|
|
|
258
348
|
async getMetrics(): Promise<ISmartDbMetrics> {
|
|
259
349
|
return this.bridge.getMetrics();
|
|
260
350
|
}
|
|
351
|
+
|
|
352
|
+
private withTenantMongoUri(
|
|
353
|
+
descriptor: ISmartDbDatabaseTenantDescriptor,
|
|
354
|
+
password: string,
|
|
355
|
+
): ISmartDbDatabaseTenantDescriptor {
|
|
356
|
+
return {
|
|
357
|
+
...descriptor,
|
|
358
|
+
mongodbUri: this.buildTenantMongoUri(descriptor.databaseName, descriptor.username, password),
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
private buildTenantMongoUri(databaseName: string, username: string, password: string): string {
|
|
363
|
+
const host = this.options.socketPath
|
|
364
|
+
? encodeURIComponent(this.options.socketPath)
|
|
365
|
+
: `${this.options.host ?? '127.0.0.1'}:${this.options.port ?? 27017}`;
|
|
366
|
+
const auth = `${encodeURIComponent(username)}:${encodeURIComponent(password)}@`;
|
|
367
|
+
const query = new URLSearchParams({ authSource: databaseName });
|
|
368
|
+
if (this.options.tls?.enabled) {
|
|
369
|
+
query.set('tls', 'true');
|
|
370
|
+
}
|
|
371
|
+
return `mongodb://${auth}${host}/${encodeURIComponent(databaseName)}?${query.toString()}`;
|
|
372
|
+
}
|
|
261
373
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export interface ISmartDbHealth {
|
|
2
|
+
running: boolean;
|
|
3
|
+
storage?: 'memory' | 'file';
|
|
4
|
+
storagePath?: string;
|
|
5
|
+
authEnabled?: boolean;
|
|
6
|
+
authUsers?: number;
|
|
7
|
+
usersPathConfigured?: boolean;
|
|
8
|
+
databaseCount: number;
|
|
9
|
+
collectionCount: number;
|
|
10
|
+
uptimeSeconds?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface ISmartDbDatabaseTenantInput {
|
|
14
|
+
databaseName: string;
|
|
15
|
+
username: string;
|
|
16
|
+
password: string;
|
|
17
|
+
roles?: string[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ISmartDbDeleteDatabaseTenantInput {
|
|
21
|
+
databaseName: string;
|
|
22
|
+
username?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ISmartDbRotateDatabaseTenantPasswordInput {
|
|
26
|
+
username: string;
|
|
27
|
+
password: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ISmartDbDatabaseTenantDescriptor {
|
|
31
|
+
databaseName: string;
|
|
32
|
+
username: string;
|
|
33
|
+
roles: string[];
|
|
34
|
+
authSource: string;
|
|
35
|
+
mongodbUri?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ISmartDbDeleteDatabaseTenantResult {
|
|
39
|
+
databaseName: string;
|
|
40
|
+
deletedUsers: number;
|
|
41
|
+
databaseDropped: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface ISmartDbDatabaseExportCollection {
|
|
45
|
+
name: string;
|
|
46
|
+
documents: Record<string, any>[];
|
|
47
|
+
indexes: Record<string, any>[];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface ISmartDbDatabaseExport {
|
|
51
|
+
format: 'smartdb.database.export.v1';
|
|
52
|
+
databaseName: string;
|
|
53
|
+
exportedAtMs: number;
|
|
54
|
+
collections: ISmartDbDatabaseExportCollection[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface ISmartDbImportDatabaseInput {
|
|
58
|
+
databaseName: string;
|
|
59
|
+
source: ISmartDbDatabaseExport;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface ISmartDbImportDatabaseResult {
|
|
63
|
+
databaseName: string;
|
|
64
|
+
collections: number;
|
|
65
|
+
documents: number;
|
|
66
|
+
}
|