@push.rocks/smartdb 1.0.1
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/.smartconfig.json +38 -0
- 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 +5 -0
- package/dist_ts/index.js +8 -0
- package/dist_ts/ts_local/classes.localsmartdb.d.ts +78 -0
- package/dist_ts/ts_local/classes.localsmartdb.js +115 -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 +2 -0
- package/dist_ts/ts_local/plugins.js +3 -0
- package/dist_ts/ts_smartdb/engine/AggregationEngine.d.ts +66 -0
- package/dist_ts/ts_smartdb/engine/AggregationEngine.js +189 -0
- package/dist_ts/ts_smartdb/engine/IndexEngine.d.ts +97 -0
- package/dist_ts/ts_smartdb/engine/IndexEngine.js +678 -0
- package/dist_ts/ts_smartdb/engine/QueryEngine.d.ts +54 -0
- package/dist_ts/ts_smartdb/engine/QueryEngine.js +271 -0
- package/dist_ts/ts_smartdb/engine/QueryPlanner.d.ts +64 -0
- package/dist_ts/ts_smartdb/engine/QueryPlanner.js +308 -0
- package/dist_ts/ts_smartdb/engine/SessionEngine.d.ts +117 -0
- package/dist_ts/ts_smartdb/engine/SessionEngine.js +232 -0
- package/dist_ts/ts_smartdb/engine/TransactionEngine.d.ts +85 -0
- package/dist_ts/ts_smartdb/engine/TransactionEngine.js +287 -0
- package/dist_ts/ts_smartdb/engine/UpdateEngine.d.ts +47 -0
- package/dist_ts/ts_smartdb/engine/UpdateEngine.js +461 -0
- package/dist_ts/ts_smartdb/errors/SmartdbErrors.d.ts +100 -0
- package/dist_ts/ts_smartdb/errors/SmartdbErrors.js +155 -0
- package/dist_ts/ts_smartdb/index.d.ts +26 -0
- package/dist_ts/ts_smartdb/index.js +31 -0
- package/dist_ts/ts_smartdb/plugins.d.ts +10 -0
- package/dist_ts/ts_smartdb/plugins.js +14 -0
- package/dist_ts/ts_smartdb/server/CommandRouter.d.ts +87 -0
- package/dist_ts/ts_smartdb/server/CommandRouter.js +222 -0
- package/dist_ts/ts_smartdb/server/SmartdbServer.d.ts +102 -0
- package/dist_ts/ts_smartdb/server/SmartdbServer.js +279 -0
- package/dist_ts/ts_smartdb/server/WireProtocol.d.ts +117 -0
- package/dist_ts/ts_smartdb/server/WireProtocol.js +298 -0
- package/dist_ts/ts_smartdb/server/handlers/AdminHandler.d.ts +100 -0
- package/dist_ts/ts_smartdb/server/handlers/AdminHandler.js +668 -0
- package/dist_ts/ts_smartdb/server/handlers/AggregateHandler.d.ts +31 -0
- package/dist_ts/ts_smartdb/server/handlers/AggregateHandler.js +277 -0
- package/dist_ts/ts_smartdb/server/handlers/DeleteHandler.d.ts +8 -0
- package/dist_ts/ts_smartdb/server/handlers/DeleteHandler.js +95 -0
- package/dist_ts/ts_smartdb/server/handlers/FindHandler.d.ts +31 -0
- package/dist_ts/ts_smartdb/server/handlers/FindHandler.js +291 -0
- package/dist_ts/ts_smartdb/server/handlers/HelloHandler.d.ts +11 -0
- package/dist_ts/ts_smartdb/server/handlers/HelloHandler.js +62 -0
- package/dist_ts/ts_smartdb/server/handlers/IndexHandler.d.ts +20 -0
- package/dist_ts/ts_smartdb/server/handlers/IndexHandler.js +183 -0
- package/dist_ts/ts_smartdb/server/handlers/InsertHandler.d.ts +8 -0
- package/dist_ts/ts_smartdb/server/handlers/InsertHandler.js +79 -0
- package/dist_ts/ts_smartdb/server/handlers/UpdateHandler.d.ts +24 -0
- package/dist_ts/ts_smartdb/server/handlers/UpdateHandler.js +296 -0
- package/dist_ts/ts_smartdb/server/handlers/index.d.ts +8 -0
- package/dist_ts/ts_smartdb/server/handlers/index.js +10 -0
- package/dist_ts/ts_smartdb/server/index.d.ts +6 -0
- package/dist_ts/ts_smartdb/server/index.js +7 -0
- package/dist_ts/ts_smartdb/storage/FileStorageAdapter.d.ts +85 -0
- package/dist_ts/ts_smartdb/storage/FileStorageAdapter.js +465 -0
- package/dist_ts/ts_smartdb/storage/IStorageAdapter.d.ts +145 -0
- package/dist_ts/ts_smartdb/storage/IStorageAdapter.js +2 -0
- package/dist_ts/ts_smartdb/storage/MemoryStorageAdapter.d.ts +67 -0
- package/dist_ts/ts_smartdb/storage/MemoryStorageAdapter.js +378 -0
- package/dist_ts/ts_smartdb/storage/OpLog.d.ts +93 -0
- package/dist_ts/ts_smartdb/storage/OpLog.js +221 -0
- package/dist_ts/ts_smartdb/storage/WAL.d.ts +117 -0
- package/dist_ts/ts_smartdb/storage/WAL.js +286 -0
- package/dist_ts/ts_smartdb/types/interfaces.d.ts +363 -0
- package/dist_ts/ts_smartdb/types/interfaces.js +2 -0
- package/dist_ts/ts_smartdb/utils/checksum.d.ts +30 -0
- package/dist_ts/ts_smartdb/utils/checksum.js +77 -0
- package/dist_ts/ts_smartdb/utils/index.d.ts +1 -0
- package/dist_ts/ts_smartdb/utils/index.js +2 -0
- package/license +19 -0
- package/package.json +69 -0
- package/readme.md +529 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/index.ts +11 -0
- package/ts/ts_local/classes.localsmartdb.ts +143 -0
- package/ts/ts_local/index.ts +2 -0
- package/ts/ts_local/plugins.ts +3 -0
- package/ts/ts_smartdb/engine/AggregationEngine.ts +283 -0
- package/ts/ts_smartdb/engine/IndexEngine.ts +798 -0
- package/ts/ts_smartdb/engine/QueryEngine.ts +301 -0
- package/ts/ts_smartdb/engine/QueryPlanner.ts +393 -0
- package/ts/ts_smartdb/engine/SessionEngine.ts +292 -0
- package/ts/ts_smartdb/engine/TransactionEngine.ts +351 -0
- package/ts/ts_smartdb/engine/UpdateEngine.ts +506 -0
- package/ts/ts_smartdb/errors/SmartdbErrors.ts +181 -0
- package/ts/ts_smartdb/index.ts +46 -0
- package/ts/ts_smartdb/plugins.ts +17 -0
- package/ts/ts_smartdb/server/CommandRouter.ts +289 -0
- package/ts/ts_smartdb/server/SmartdbServer.ts +354 -0
- package/ts/ts_smartdb/server/WireProtocol.ts +416 -0
- package/ts/ts_smartdb/server/handlers/AdminHandler.ts +719 -0
- package/ts/ts_smartdb/server/handlers/AggregateHandler.ts +342 -0
- package/ts/ts_smartdb/server/handlers/DeleteHandler.ts +115 -0
- package/ts/ts_smartdb/server/handlers/FindHandler.ts +330 -0
- package/ts/ts_smartdb/server/handlers/HelloHandler.ts +78 -0
- package/ts/ts_smartdb/server/handlers/IndexHandler.ts +207 -0
- package/ts/ts_smartdb/server/handlers/InsertHandler.ts +97 -0
- package/ts/ts_smartdb/server/handlers/UpdateHandler.ts +344 -0
- package/ts/ts_smartdb/server/handlers/index.ts +10 -0
- package/ts/ts_smartdb/server/index.ts +10 -0
- package/ts/ts_smartdb/storage/FileStorageAdapter.ts +562 -0
- package/ts/ts_smartdb/storage/IStorageAdapter.ts +208 -0
- package/ts/ts_smartdb/storage/MemoryStorageAdapter.ts +455 -0
- package/ts/ts_smartdb/storage/OpLog.ts +282 -0
- package/ts/ts_smartdb/storage/WAL.ts +375 -0
- package/ts/ts_smartdb/types/interfaces.ts +433 -0
- package/ts/ts_smartdb/utils/checksum.ts +88 -0
- package/ts/ts_smartdb/utils/index.ts +1 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"@git.zone/cli": {
|
|
3
|
+
"projectType": "npm",
|
|
4
|
+
"module": {
|
|
5
|
+
"githost": "code.foss.global",
|
|
6
|
+
"gitscope": "push.rocks",
|
|
7
|
+
"gitrepo": "smartdb",
|
|
8
|
+
"description": "A pure TypeScript MongoDB wire-protocol-compatible database server with pluggable storage, indexing, transactions, and zero external binary dependencies.",
|
|
9
|
+
"npmPackagename": "@push.rocks/smartdb",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"projectDomain": "push.rocks",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"mongodb",
|
|
14
|
+
"wire protocol",
|
|
15
|
+
"typescript database",
|
|
16
|
+
"in-memory database",
|
|
17
|
+
"testing",
|
|
18
|
+
"local database",
|
|
19
|
+
"database server",
|
|
20
|
+
"typescript"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"release": {
|
|
24
|
+
"registries": [
|
|
25
|
+
"https://verdaccio.lossless.digital",
|
|
26
|
+
"https://registry.npmjs.org"
|
|
27
|
+
],
|
|
28
|
+
"accessLevel": "public"
|
|
29
|
+
},
|
|
30
|
+
"services": []
|
|
31
|
+
},
|
|
32
|
+
"@git.zone/tsdoc": {
|
|
33
|
+
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository. \n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.\n\n### Company Information\n\nTask Venture Capital GmbH \nRegistered at District court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or if you require further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
|
34
|
+
},
|
|
35
|
+
"@ship.zone/szci": {
|
|
36
|
+
"npmGlobalTools": []
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* autocreated commitinfo by @push.rocks/commitinfo
|
|
3
|
+
*/
|
|
4
|
+
export const commitinfo = {
|
|
5
|
+
name: '@push.rocks/smartdb',
|
|
6
|
+
version: '1.0.1',
|
|
7
|
+
description: 'A pure TypeScript MongoDB wire-protocol-compatible database server with pluggable storage, indexing, transactions, and zero external binary dependencies.'
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxxQkFBcUI7SUFDM0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLDJKQUEySjtDQUN6SyxDQUFBIn0=
|
package/dist_ts/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
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 commitinfo
|
|
7
|
+
export { commitinfo };
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFckQsNkJBQTZCO0FBQzdCLGNBQWMsdUJBQXVCLENBQUM7QUFFdEMsc0JBQXNCO0FBQ3RCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUduRCxvQkFBb0I7QUFDcEIsT0FBTyxFQUFFLFVBQVUsRUFBRSxDQUFDIn0=
|
|
@@ -0,0 +1,78 @@
|
|
|
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
|
+
/** MongoDB connection URI 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 MongoDB-compatible server. Returns connection
|
|
22
|
+
* info that you can use with your own MongoDB 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 your own MongoDB client
|
|
33
|
+
* const client = new MongoClient(connectionUri, { directConnection: true });
|
|
34
|
+
* await client.connect();
|
|
35
|
+
*
|
|
36
|
+
* // Use the MongoDB 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
|
+
* Start the local SmartDB server and return connection info
|
|
56
|
+
*/
|
|
57
|
+
start(): Promise<ILocalSmartDbConnectionInfo>;
|
|
58
|
+
/**
|
|
59
|
+
* Get connection info (throws if not started)
|
|
60
|
+
*/
|
|
61
|
+
getConnectionInfo(): ILocalSmartDbConnectionInfo;
|
|
62
|
+
/**
|
|
63
|
+
* Get the underlying SmartdbServer instance (throws if not started)
|
|
64
|
+
*/
|
|
65
|
+
getServer(): SmartdbServer;
|
|
66
|
+
/**
|
|
67
|
+
* Get the connection URI
|
|
68
|
+
*/
|
|
69
|
+
getConnectionUri(): string;
|
|
70
|
+
/**
|
|
71
|
+
* Check if the server is running
|
|
72
|
+
*/
|
|
73
|
+
get running(): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Stop the local SmartDB server
|
|
76
|
+
*/
|
|
77
|
+
stop(): Promise<void>;
|
|
78
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import * as crypto from 'crypto';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import * as os from 'os';
|
|
5
|
+
import { SmartdbServer } from '../ts_smartdb/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* LocalSmartDb - Lightweight local MongoDB-compatible database using Unix sockets
|
|
8
|
+
*
|
|
9
|
+
* This class wraps SmartdbServer and provides a simple interface for
|
|
10
|
+
* starting a local file-based MongoDB-compatible server. Returns connection
|
|
11
|
+
* info that you can use with your own MongoDB driver instance.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* import { LocalSmartDb } from '@push.rocks/smartdb';
|
|
16
|
+
* import { MongoClient } from 'mongodb';
|
|
17
|
+
*
|
|
18
|
+
* const db = new LocalSmartDb({ folderPath: './data' });
|
|
19
|
+
* const { connectionUri } = await db.start();
|
|
20
|
+
*
|
|
21
|
+
* // Connect with your own MongoDB client
|
|
22
|
+
* const client = new MongoClient(connectionUri, { directConnection: true });
|
|
23
|
+
* await client.connect();
|
|
24
|
+
*
|
|
25
|
+
* // Use the MongoDB client
|
|
26
|
+
* const collection = client.db('mydb').collection('users');
|
|
27
|
+
* await collection.insertOne({ name: 'Alice' });
|
|
28
|
+
*
|
|
29
|
+
* // When done
|
|
30
|
+
* await client.close();
|
|
31
|
+
* await db.stop();
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export class LocalSmartDb {
|
|
35
|
+
options;
|
|
36
|
+
server = null;
|
|
37
|
+
generatedSocketPath = null;
|
|
38
|
+
constructor(options) {
|
|
39
|
+
this.options = options;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Generate a unique socket path in /tmp
|
|
43
|
+
*/
|
|
44
|
+
generateSocketPath() {
|
|
45
|
+
const randomId = crypto.randomBytes(8).toString('hex');
|
|
46
|
+
return path.join(os.tmpdir(), `smartdb-${randomId}.sock`);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Start the local SmartDB server and return connection info
|
|
50
|
+
*/
|
|
51
|
+
async start() {
|
|
52
|
+
if (this.server) {
|
|
53
|
+
throw new Error('LocalSmartDb is already running');
|
|
54
|
+
}
|
|
55
|
+
// Use provided socket path or generate one
|
|
56
|
+
this.generatedSocketPath = this.options.socketPath ?? this.generateSocketPath();
|
|
57
|
+
this.server = new SmartdbServer({
|
|
58
|
+
socketPath: this.generatedSocketPath,
|
|
59
|
+
storage: 'file',
|
|
60
|
+
storagePath: this.options.folderPath,
|
|
61
|
+
});
|
|
62
|
+
await this.server.start();
|
|
63
|
+
return {
|
|
64
|
+
socketPath: this.generatedSocketPath,
|
|
65
|
+
connectionUri: this.server.getConnectionUri(),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get connection info (throws if not started)
|
|
70
|
+
*/
|
|
71
|
+
getConnectionInfo() {
|
|
72
|
+
if (!this.server || !this.generatedSocketPath) {
|
|
73
|
+
throw new Error('LocalSmartDb is not running. Call start() first.');
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
socketPath: this.generatedSocketPath,
|
|
77
|
+
connectionUri: this.server.getConnectionUri(),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get the underlying SmartdbServer instance (throws if not started)
|
|
82
|
+
*/
|
|
83
|
+
getServer() {
|
|
84
|
+
if (!this.server) {
|
|
85
|
+
throw new Error('LocalSmartDb is not running. Call start() first.');
|
|
86
|
+
}
|
|
87
|
+
return this.server;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get the connection URI
|
|
91
|
+
*/
|
|
92
|
+
getConnectionUri() {
|
|
93
|
+
if (!this.server) {
|
|
94
|
+
throw new Error('LocalSmartDb is not running. Call start() first.');
|
|
95
|
+
}
|
|
96
|
+
return this.server.getConnectionUri();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check if the server is running
|
|
100
|
+
*/
|
|
101
|
+
get running() {
|
|
102
|
+
return this.server !== null && this.server.running;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Stop the local SmartDB server
|
|
106
|
+
*/
|
|
107
|
+
async stop() {
|
|
108
|
+
if (this.server) {
|
|
109
|
+
await this.server.stop();
|
|
110
|
+
this.server = null;
|
|
111
|
+
this.generatedSocketPath = null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5sb2NhbHNtYXJ0ZGIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy90c19sb2NhbC9jbGFzc2VzLmxvY2Fsc21hcnRkYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUNqQyxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQztBQUN6QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFtQnZEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0EyQkc7QUFDSCxNQUFNLE9BQU8sWUFBWTtJQUNmLE9BQU8sQ0FBdUI7SUFDOUIsTUFBTSxHQUF5QixJQUFJLENBQUM7SUFDcEMsbUJBQW1CLEdBQWtCLElBQUksQ0FBQztJQUVsRCxZQUFZLE9BQTZCO1FBQ3ZDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDO0lBQ3pCLENBQUM7SUFFRDs7T0FFRztJQUNLLGtCQUFrQjtRQUN4QixNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN2RCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFLFdBQVcsUUFBUSxPQUFPLENBQUMsQ0FBQztJQUM1RCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsS0FBSztRQUNULElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsaUNBQWlDLENBQUMsQ0FBQztRQUNyRCxDQUFDO1FBRUQsMkNBQTJDO1FBQzNDLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUVoRixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksYUFBYSxDQUFDO1lBQzlCLFVBQVUsRUFBRSxJQUFJLENBQUMsbUJBQW1CO1lBQ3BDLE9BQU8sRUFBRSxNQUFNO1lBQ2YsV0FBVyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVTtTQUNyQyxDQUFDLENBQUM7UUFDSCxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFMUIsT0FBTztZQUNMLFVBQVUsRUFBRSxJQUFJLENBQUMsbUJBQW1CO1lBQ3BDLGFBQWEsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixFQUFFO1NBQzlDLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxpQkFBaUI7UUFDZixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQzlDLE1BQU0sSUFBSSxLQUFLLENBQUMsa0RBQWtELENBQUMsQ0FBQztRQUN0RSxDQUFDO1FBQ0QsT0FBTztZQUNMLFVBQVUsRUFBRSxJQUFJLENBQUMsbUJBQW1CO1lBQ3BDLGFBQWEsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixFQUFFO1NBQzlDLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxTQUFTO1FBQ1AsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLGtEQUFrRCxDQUFDLENBQUM7UUFDdEUsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUNyQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxnQkFBZ0I7UUFDZCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2pCLE1BQU0sSUFBSSxLQUFLLENBQUMsa0RBQWtELENBQUMsQ0FBQztRQUN0RSxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDeEMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxPQUFPO1FBQ1QsT0FBTyxJQUFJLENBQUMsTUFBTSxLQUFLLElBQUksSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQztJQUNyRCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsSUFBSTtRQUNSLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2hCLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztZQUNuQixJQUFJLENBQUMsbUJBQW1CLEdBQUcsSUFBSSxDQUFDO1FBQ2xDLENBQUM7SUFDSCxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { LocalSmartDb } from './classes.localsmartdb.js';
|
|
2
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy90c19sb2NhbC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUMifQ==
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import * as smartpromise from '@push.rocks/smartpromise';
|
|
2
|
+
export { smartpromise };
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2lucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3RzX2xvY2FsL3BsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLFlBQVksTUFBTSwwQkFBMEIsQ0FBQztBQUV6RCxPQUFPLEVBQUUsWUFBWSxFQUFFLENBQUMifQ==
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Document, IStoredDocument, IAggregateOptions } from '../types/interfaces.js';
|
|
2
|
+
/**
|
|
3
|
+
* Aggregation engine using mingo for MongoDB-compatible aggregation pipeline execution
|
|
4
|
+
*/
|
|
5
|
+
export declare class AggregationEngine {
|
|
6
|
+
/**
|
|
7
|
+
* Execute an aggregation pipeline on a collection of documents
|
|
8
|
+
*/
|
|
9
|
+
static aggregate(documents: IStoredDocument[], pipeline: Document[], options?: IAggregateOptions): Document[];
|
|
10
|
+
/**
|
|
11
|
+
* Execute aggregation and return an iterator for lazy evaluation
|
|
12
|
+
*/
|
|
13
|
+
static aggregateIterator(documents: IStoredDocument[], pipeline: Document[], options?: IAggregateOptions): Generator<Document>;
|
|
14
|
+
/**
|
|
15
|
+
* Execute a $lookup stage manually (for cross-collection lookups)
|
|
16
|
+
* This is used when the lookup references another collection in the same database
|
|
17
|
+
*/
|
|
18
|
+
static executeLookup(documents: IStoredDocument[], lookupSpec: {
|
|
19
|
+
from: string;
|
|
20
|
+
localField: string;
|
|
21
|
+
foreignField: string;
|
|
22
|
+
as: string;
|
|
23
|
+
}, foreignCollection: IStoredDocument[]): Document[];
|
|
24
|
+
/**
|
|
25
|
+
* Execute a $graphLookup stage manually
|
|
26
|
+
*/
|
|
27
|
+
static executeGraphLookup(documents: IStoredDocument[], graphLookupSpec: {
|
|
28
|
+
from: string;
|
|
29
|
+
startWith: string | Document;
|
|
30
|
+
connectFromField: string;
|
|
31
|
+
connectToField: string;
|
|
32
|
+
as: string;
|
|
33
|
+
maxDepth?: number;
|
|
34
|
+
depthField?: string;
|
|
35
|
+
restrictSearchWithMatch?: Document;
|
|
36
|
+
}, foreignCollection: IStoredDocument[]): Document[];
|
|
37
|
+
/**
|
|
38
|
+
* Execute a $facet stage manually
|
|
39
|
+
*/
|
|
40
|
+
static executeFacet(documents: IStoredDocument[], facetSpec: Record<string, Document[]>): Document;
|
|
41
|
+
/**
|
|
42
|
+
* Execute a $unionWith stage
|
|
43
|
+
*/
|
|
44
|
+
static executeUnionWith(documents: IStoredDocument[], otherDocuments: IStoredDocument[], pipeline?: Document[]): Document[];
|
|
45
|
+
/**
|
|
46
|
+
* Execute a $merge stage (output to another collection)
|
|
47
|
+
* Returns the documents that would be inserted/updated
|
|
48
|
+
*/
|
|
49
|
+
static prepareMerge(documents: Document[], mergeSpec: {
|
|
50
|
+
into: string;
|
|
51
|
+
on?: string | string[];
|
|
52
|
+
whenMatched?: 'replace' | 'keepExisting' | 'merge' | 'fail' | Document[];
|
|
53
|
+
whenNotMatched?: 'insert' | 'discard' | 'fail';
|
|
54
|
+
}): {
|
|
55
|
+
toInsert: Document[];
|
|
56
|
+
toUpdate: Array<{
|
|
57
|
+
filter: Document;
|
|
58
|
+
update: Document;
|
|
59
|
+
}>;
|
|
60
|
+
onField: string | string[];
|
|
61
|
+
whenMatched: string | Document[];
|
|
62
|
+
whenNotMatched: string;
|
|
63
|
+
};
|
|
64
|
+
private static getNestedValue;
|
|
65
|
+
private static valuesMatch;
|
|
66
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
// Import mingo Aggregator
|
|
3
|
+
import { Aggregator } from 'mingo';
|
|
4
|
+
/**
|
|
5
|
+
* Aggregation engine using mingo for MongoDB-compatible aggregation pipeline execution
|
|
6
|
+
*/
|
|
7
|
+
export class AggregationEngine {
|
|
8
|
+
/**
|
|
9
|
+
* Execute an aggregation pipeline on a collection of documents
|
|
10
|
+
*/
|
|
11
|
+
static aggregate(documents, pipeline, options) {
|
|
12
|
+
if (!pipeline || pipeline.length === 0) {
|
|
13
|
+
return documents;
|
|
14
|
+
}
|
|
15
|
+
// Create mingo aggregator with the pipeline
|
|
16
|
+
const aggregator = new Aggregator(pipeline, {
|
|
17
|
+
collation: options?.collation,
|
|
18
|
+
});
|
|
19
|
+
// Run the aggregation
|
|
20
|
+
const result = aggregator.run(documents);
|
|
21
|
+
return Array.isArray(result) ? result : [];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Execute aggregation and return an iterator for lazy evaluation
|
|
25
|
+
*/
|
|
26
|
+
static *aggregateIterator(documents, pipeline, options) {
|
|
27
|
+
const aggregator = new Aggregator(pipeline, {
|
|
28
|
+
collation: options?.collation,
|
|
29
|
+
});
|
|
30
|
+
// Get the cursor from mingo
|
|
31
|
+
const cursor = aggregator.stream(documents);
|
|
32
|
+
for (const doc of cursor) {
|
|
33
|
+
yield doc;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Execute a $lookup stage manually (for cross-collection lookups)
|
|
38
|
+
* This is used when the lookup references another collection in the same database
|
|
39
|
+
*/
|
|
40
|
+
static executeLookup(documents, lookupSpec, foreignCollection) {
|
|
41
|
+
const { localField, foreignField, as } = lookupSpec;
|
|
42
|
+
return documents.map(doc => {
|
|
43
|
+
const localValue = this.getNestedValue(doc, localField);
|
|
44
|
+
const matches = foreignCollection.filter(foreignDoc => {
|
|
45
|
+
const foreignValue = this.getNestedValue(foreignDoc, foreignField);
|
|
46
|
+
return this.valuesMatch(localValue, foreignValue);
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
...doc,
|
|
50
|
+
[as]: matches,
|
|
51
|
+
};
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Execute a $graphLookup stage manually
|
|
56
|
+
*/
|
|
57
|
+
static executeGraphLookup(documents, graphLookupSpec, foreignCollection) {
|
|
58
|
+
const { startWith, connectFromField, connectToField, as, maxDepth = 10, depthField, restrictSearchWithMatch, } = graphLookupSpec;
|
|
59
|
+
return documents.map(doc => {
|
|
60
|
+
const startValue = typeof startWith === 'string' && startWith.startsWith('$')
|
|
61
|
+
? this.getNestedValue(doc, startWith.slice(1))
|
|
62
|
+
: startWith;
|
|
63
|
+
const results = [];
|
|
64
|
+
const visited = new Set();
|
|
65
|
+
const queue = [];
|
|
66
|
+
// Initialize with start value(s)
|
|
67
|
+
const startValues = Array.isArray(startValue) ? startValue : [startValue];
|
|
68
|
+
for (const val of startValues) {
|
|
69
|
+
queue.push({ value: val, depth: 0 });
|
|
70
|
+
}
|
|
71
|
+
while (queue.length > 0) {
|
|
72
|
+
const { value, depth } = queue.shift();
|
|
73
|
+
if (depth > maxDepth)
|
|
74
|
+
continue;
|
|
75
|
+
const valueKey = JSON.stringify(value);
|
|
76
|
+
if (visited.has(valueKey))
|
|
77
|
+
continue;
|
|
78
|
+
visited.add(valueKey);
|
|
79
|
+
// Find matching documents
|
|
80
|
+
for (const foreignDoc of foreignCollection) {
|
|
81
|
+
const foreignValue = this.getNestedValue(foreignDoc, connectToField);
|
|
82
|
+
if (this.valuesMatch(value, foreignValue)) {
|
|
83
|
+
// Check restrictSearchWithMatch
|
|
84
|
+
if (restrictSearchWithMatch) {
|
|
85
|
+
const matchQuery = new plugins.mingo.Query(restrictSearchWithMatch);
|
|
86
|
+
if (!matchQuery.test(foreignDoc))
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const resultDoc = depthField
|
|
90
|
+
? { ...foreignDoc, [depthField]: depth }
|
|
91
|
+
: { ...foreignDoc };
|
|
92
|
+
// Avoid duplicates in results
|
|
93
|
+
const docKey = foreignDoc._id.toHexString();
|
|
94
|
+
if (!results.some(r => r._id?.toHexString?.() === docKey)) {
|
|
95
|
+
results.push(resultDoc);
|
|
96
|
+
// Add connected values to queue
|
|
97
|
+
const nextValue = this.getNestedValue(foreignDoc, connectFromField);
|
|
98
|
+
if (nextValue !== undefined) {
|
|
99
|
+
const nextValues = Array.isArray(nextValue) ? nextValue : [nextValue];
|
|
100
|
+
for (const nv of nextValues) {
|
|
101
|
+
queue.push({ value: nv, depth: depth + 1 });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return {
|
|
109
|
+
...doc,
|
|
110
|
+
[as]: results,
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Execute a $facet stage manually
|
|
116
|
+
*/
|
|
117
|
+
static executeFacet(documents, facetSpec) {
|
|
118
|
+
const result = {};
|
|
119
|
+
for (const [facetName, pipeline] of Object.entries(facetSpec)) {
|
|
120
|
+
result[facetName] = this.aggregate(documents, pipeline);
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Execute a $unionWith stage
|
|
126
|
+
*/
|
|
127
|
+
static executeUnionWith(documents, otherDocuments, pipeline) {
|
|
128
|
+
let unionDocs = otherDocuments;
|
|
129
|
+
if (pipeline && pipeline.length > 0) {
|
|
130
|
+
unionDocs = this.aggregate(otherDocuments, pipeline);
|
|
131
|
+
}
|
|
132
|
+
return [...documents, ...unionDocs];
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Execute a $merge stage (output to another collection)
|
|
136
|
+
* Returns the documents that would be inserted/updated
|
|
137
|
+
*/
|
|
138
|
+
static prepareMerge(documents, mergeSpec) {
|
|
139
|
+
const onField = mergeSpec.on || '_id';
|
|
140
|
+
const whenMatched = mergeSpec.whenMatched || 'merge';
|
|
141
|
+
const whenNotMatched = mergeSpec.whenNotMatched || 'insert';
|
|
142
|
+
return {
|
|
143
|
+
toInsert: [],
|
|
144
|
+
toUpdate: [],
|
|
145
|
+
onField,
|
|
146
|
+
whenMatched,
|
|
147
|
+
whenNotMatched,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
// ============================================================================
|
|
151
|
+
// Helper Methods
|
|
152
|
+
// ============================================================================
|
|
153
|
+
static getNestedValue(obj, path) {
|
|
154
|
+
const parts = path.split('.');
|
|
155
|
+
let current = obj;
|
|
156
|
+
for (const part of parts) {
|
|
157
|
+
if (current === null || current === undefined) {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
current = current[part];
|
|
161
|
+
}
|
|
162
|
+
return current;
|
|
163
|
+
}
|
|
164
|
+
static valuesMatch(a, b) {
|
|
165
|
+
if (a === b)
|
|
166
|
+
return true;
|
|
167
|
+
// Handle ObjectId comparison
|
|
168
|
+
if (a instanceof plugins.bson.ObjectId && b instanceof plugins.bson.ObjectId) {
|
|
169
|
+
return a.equals(b);
|
|
170
|
+
}
|
|
171
|
+
// Handle array contains check
|
|
172
|
+
if (Array.isArray(a)) {
|
|
173
|
+
return a.some(item => this.valuesMatch(item, b));
|
|
174
|
+
}
|
|
175
|
+
if (Array.isArray(b)) {
|
|
176
|
+
return b.some(item => this.valuesMatch(a, item));
|
|
177
|
+
}
|
|
178
|
+
// Handle Date comparison
|
|
179
|
+
if (a instanceof Date && b instanceof Date) {
|
|
180
|
+
return a.getTime() === b.getTime();
|
|
181
|
+
}
|
|
182
|
+
// Handle object comparison
|
|
183
|
+
if (typeof a === 'object' && typeof b === 'object' && a !== null && b !== null) {
|
|
184
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
185
|
+
}
|
|
186
|
+
return false;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQWdncmVnYXRpb25FbmdpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy90c19zbWFydGRiL2VuZ2luZS9BZ2dyZWdhdGlvbkVuZ2luZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUd6QywwQkFBMEI7QUFDMUIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLE9BQU8sQ0FBQztBQUVuQzs7R0FFRztBQUNILE1BQU0sT0FBTyxpQkFBaUI7SUFDNUI7O09BRUc7SUFDSCxNQUFNLENBQUMsU0FBUyxDQUNkLFNBQTRCLEVBQzVCLFFBQW9CLEVBQ3BCLE9BQTJCO1FBRTNCLElBQUksQ0FBQyxRQUFRLElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN2QyxPQUFPLFNBQVMsQ0FBQztRQUNuQixDQUFDO1FBRUQsNENBQTRDO1FBQzVDLE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxDQUFDLFFBQVEsRUFBRTtZQUMxQyxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQWdCO1NBQ3JDLENBQUMsQ0FBQztRQUVILHNCQUFzQjtRQUN0QixNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRXpDLE9BQU8sS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDN0MsQ0FBQztJQUVEOztPQUVHO0lBQ0gsTUFBTSxDQUFDLENBQUMsaUJBQWlCLENBQ3ZCLFNBQTRCLEVBQzVCLFFBQW9CLEVBQ3BCLE9BQTJCO1FBRTNCLE1BQU0sVUFBVSxHQUFHLElBQUksVUFBVSxDQUFDLFFBQVEsRUFBRTtZQUMxQyxTQUFTLEVBQUUsT0FBTyxFQUFFLFNBQWdCO1NBQ3JDLENBQUMsQ0FBQztRQUVILDRCQUE0QjtRQUM1QixNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBRTVDLEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxFQUFFLENBQUM7WUFDekIsTUFBTSxHQUFlLENBQUM7UUFDeEIsQ0FBQztJQUNILENBQUM7SUFFRDs7O09BR0c7SUFDSCxNQUFNLENBQUMsYUFBYSxDQUNsQixTQUE0QixFQUM1QixVQUtDLEVBQ0QsaUJBQW9DO1FBRXBDLE1BQU0sRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxHQUFHLFVBQVUsQ0FBQztRQUVwRCxPQUFPLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDekIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDeEQsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxFQUFFO2dCQUNwRCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFVBQVUsRUFBRSxZQUFZLENBQUMsQ0FBQztnQkFDbkUsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsRUFBRSxZQUFZLENBQUMsQ0FBQztZQUNwRCxDQUFDLENBQUMsQ0FBQztZQUVILE9BQU87Z0JBQ0wsR0FBRyxHQUFHO2dCQUNOLENBQUMsRUFBRSxDQUFDLEVBQUUsT0FBTzthQUNkLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxrQkFBa0IsQ0FDdkIsU0FBNEIsRUFDNUIsZUFTQyxFQUNELGlCQUFvQztRQUVwQyxNQUFNLEVBQ0osU0FBUyxFQUNULGdCQUFnQixFQUNoQixjQUFjLEVBQ2QsRUFBRSxFQUNGLFFBQVEsR0FBRyxFQUFFLEVBQ2IsVUFBVSxFQUNWLHVCQUF1QixHQUN4QixHQUFHLGVBQWUsQ0FBQztRQUVwQixPQUFPLFNBQVMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDekIsTUFBTSxVQUFVLEdBQUcsT0FBTyxTQUFTLEtBQUssUUFBUSxJQUFJLFNBQVMsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDO2dCQUMzRSxDQUFDLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLEVBQUUsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDOUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUVkLE1BQU0sT0FBTyxHQUFlLEVBQUUsQ0FBQztZQUMvQixNQUFNLE9BQU8sR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1lBQ2xDLE1BQU0sS0FBSyxHQUF5QyxFQUFFLENBQUM7WUFFdkQsaUNBQWlDO1lBQ2pDLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUMxRSxLQUFLLE1BQU0sR0FBRyxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUM5QixLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN2QyxDQUFDO1lBRUQsT0FBTyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN4QixNQUFNLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxHQUFHLEtBQUssQ0FBQyxLQUFLLEVBQUcsQ0FBQztnQkFDeEMsSUFBSSxLQUFLLEdBQUcsUUFBUTtvQkFBRSxTQUFTO2dCQUUvQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUN2QyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO29CQUFFLFNBQVM7Z0JBQ3BDLE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7Z0JBRXRCLDBCQUEwQjtnQkFDMUIsS0FBSyxNQUFNLFVBQVUsSUFBSSxpQkFBaUIsRUFBRSxDQUFDO29CQUMzQyxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLFVBQVUsRUFBRSxjQUFjLENBQUMsQ0FBQztvQkFFckUsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxZQUFZLENBQUMsRUFBRSxDQUFDO3dCQUMxQyxnQ0FBZ0M7d0JBQ2hDLElBQUksdUJBQXVCLEVBQUUsQ0FBQzs0QkFDNUIsTUFBTSxVQUFVLEdBQUcsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDOzRCQUNwRSxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUM7Z0NBQUUsU0FBUzt3QkFDN0MsQ0FBQzt3QkFFRCxNQUFNLFNBQVMsR0FBRyxVQUFVOzRCQUMxQixDQUFDLENBQUMsRUFBRSxHQUFHLFVBQVUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEtBQUssRUFBRTs0QkFDeEMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxVQUFVLEVBQUUsQ0FBQzt3QkFFdEIsOEJBQThCO3dCQUM5QixNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO3dCQUM1QyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsV0FBVyxFQUFFLEVBQUUsS0FBSyxNQUFNLENBQUMsRUFBRSxDQUFDOzRCQUMxRCxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDOzRCQUV4QixnQ0FBZ0M7NEJBQ2hDLE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsVUFBVSxFQUFFLGdCQUFnQixDQUFDLENBQUM7NEJBQ3BFLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dDQUM1QixNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUM7Z0NBQ3RFLEtBQUssTUFBTSxFQUFFLElBQUksVUFBVSxFQUFFLENBQUM7b0NBQzVCLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQ0FDOUMsQ0FBQzs0QkFDSCxDQUFDO3dCQUNILENBQUM7b0JBQ0gsQ0FBQztnQkFDSCxDQUFDO1lBQ0gsQ0FBQztZQUVELE9BQU87Z0JBQ0wsR0FBRyxHQUFHO2dCQUNOLENBQUMsRUFBRSxDQUFDLEVBQUUsT0FBTzthQUNkLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxZQUFZLENBQ2pCLFNBQTRCLEVBQzVCLFNBQXFDO1FBRXJDLE1BQU0sTUFBTSxHQUFhLEVBQUUsQ0FBQztRQUU1QixLQUFLLE1BQU0sQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQzlELE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUMxRCxDQUFDO1FBRUQsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsTUFBTSxDQUFDLGdCQUFnQixDQUNyQixTQUE0QixFQUM1QixjQUFpQyxFQUNqQyxRQUFxQjtRQUVyQixJQUFJLFNBQVMsR0FBZSxjQUFjLENBQUM7UUFDM0MsSUFBSSxRQUFRLElBQUksUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNwQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxjQUFjLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDdkQsQ0FBQztRQUNELE9BQU8sQ0FBQyxHQUFHLFNBQVMsRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFRDs7O09BR0c7SUFDSCxNQUFNLENBQUMsWUFBWSxDQUNqQixTQUFxQixFQUNyQixTQUtDO1FBUUQsTUFBTSxPQUFPLEdBQUcsU0FBUyxDQUFDLEVBQUUsSUFBSSxLQUFLLENBQUM7UUFDdEMsTUFBTSxXQUFXLEdBQUcsU0FBUyxDQUFDLFdBQVcsSUFBSSxPQUFPLENBQUM7UUFDckQsTUFBTSxjQUFjLEdBQUcsU0FBUyxDQUFDLGNBQWMsSUFBSSxRQUFRLENBQUM7UUFFNUQsT0FBTztZQUNMLFFBQVEsRUFBRSxFQUFFO1lBQ1osUUFBUSxFQUFFLEVBQUU7WUFDWixPQUFPO1lBQ1AsV0FBVztZQUNYLGNBQWM7U0FDZixDQUFDO0lBQ0osQ0FBQztJQUVELCtFQUErRTtJQUMvRSxpQkFBaUI7SUFDakIsK0VBQStFO0lBRXZFLE1BQU0sQ0FBQyxjQUFjLENBQUMsR0FBUSxFQUFFLElBQVk7UUFDbEQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUM5QixJQUFJLE9BQU8sR0FBRyxHQUFHLENBQUM7UUFFbEIsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUN6QixJQUFJLE9BQU8sS0FBSyxJQUFJLElBQUksT0FBTyxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUM5QyxPQUFPLFNBQVMsQ0FBQztZQUNuQixDQUFDO1lBQ0QsT0FBTyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMxQixDQUFDO1FBRUQsT0FBTyxPQUFPLENBQUM7SUFDakIsQ0FBQztJQUVPLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBTSxFQUFFLENBQU07UUFDdkMsSUFBSSxDQUFDLEtBQUssQ0FBQztZQUFFLE9BQU8sSUFBSSxDQUFDO1FBRXpCLDZCQUE2QjtRQUM3QixJQUFJLENBQUMsWUFBWSxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsSUFBSSxDQUFDLFlBQVksT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUM3RSxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckIsQ0FBQztRQUVELDhCQUE4QjtRQUM5QixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNyQixPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25ELENBQUM7UUFDRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUNyQixPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ25ELENBQUM7UUFFRCx5QkFBeUI7UUFDekIsSUFBSSxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQztZQUMzQyxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDckMsQ0FBQztRQUVELDJCQUEyQjtRQUMzQixJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDL0UsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDakQsQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztDQUNGIn0=
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { IStorageAdapter } from '../storage/IStorageAdapter.js';
|
|
2
|
+
declare class SimpleBTree<K, V> {
|
|
3
|
+
private entries;
|
|
4
|
+
private sortedKeys;
|
|
5
|
+
private comparator;
|
|
6
|
+
constructor(_unused?: undefined, comparator?: (a: K, b: K) => number);
|
|
7
|
+
private keyToString;
|
|
8
|
+
set(key: K, value: V): boolean;
|
|
9
|
+
get(key: K): V | undefined;
|
|
10
|
+
delete(key: K): boolean;
|
|
11
|
+
forRange(lowKey: K | undefined, highKey: K | undefined, lowInclusive: boolean, highInclusive: boolean, callback: (value: V, key: K) => void): void;
|
|
12
|
+
}
|
|
13
|
+
import type { Document, IStoredDocument, IIndexInfo, ICreateIndexOptions } from '../types/interfaces.js';
|
|
14
|
+
/**
|
|
15
|
+
* Index data structure using B-Tree for range queries
|
|
16
|
+
*/
|
|
17
|
+
interface IIndexData {
|
|
18
|
+
name: string;
|
|
19
|
+
key: Record<string, 1 | -1 | string>;
|
|
20
|
+
unique: boolean;
|
|
21
|
+
sparse: boolean;
|
|
22
|
+
expireAfterSeconds?: number;
|
|
23
|
+
btree: SimpleBTree<any, Set<string>>;
|
|
24
|
+
hashMap: Map<string, Set<string>>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Index engine for managing indexes and query optimization
|
|
28
|
+
*/
|
|
29
|
+
export declare class IndexEngine {
|
|
30
|
+
private dbName;
|
|
31
|
+
private collName;
|
|
32
|
+
private storage;
|
|
33
|
+
private indexes;
|
|
34
|
+
private initialized;
|
|
35
|
+
constructor(dbName: string, collName: string, storage: IStorageAdapter);
|
|
36
|
+
/**
|
|
37
|
+
* Initialize indexes from storage
|
|
38
|
+
*/
|
|
39
|
+
initialize(): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Create a new index
|
|
42
|
+
*/
|
|
43
|
+
createIndex(key: Record<string, 1 | -1 | 'text' | '2dsphere'>, options?: ICreateIndexOptions): Promise<string>;
|
|
44
|
+
/**
|
|
45
|
+
* Drop an index
|
|
46
|
+
*/
|
|
47
|
+
dropIndex(name: string): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Drop all indexes except _id
|
|
50
|
+
*/
|
|
51
|
+
dropAllIndexes(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* List all indexes
|
|
54
|
+
*/
|
|
55
|
+
listIndexes(): Promise<IIndexInfo[]>;
|
|
56
|
+
/**
|
|
57
|
+
* Check if an index exists
|
|
58
|
+
*/
|
|
59
|
+
indexExists(name: string): Promise<boolean>;
|
|
60
|
+
/**
|
|
61
|
+
* Update index entries after document insert
|
|
62
|
+
*/
|
|
63
|
+
onInsert(doc: IStoredDocument): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Update index entries after document update
|
|
66
|
+
*/
|
|
67
|
+
onUpdate(oldDoc: IStoredDocument, newDoc: IStoredDocument): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Update index entries after document delete
|
|
70
|
+
*/
|
|
71
|
+
onDelete(doc: IStoredDocument): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Find the best index for a query
|
|
74
|
+
*/
|
|
75
|
+
selectIndex(filter: Document): {
|
|
76
|
+
name: string;
|
|
77
|
+
data: IIndexData;
|
|
78
|
+
} | null;
|
|
79
|
+
/**
|
|
80
|
+
* Analyze filter to extract field operators
|
|
81
|
+
*/
|
|
82
|
+
private analyzeFilter;
|
|
83
|
+
/**
|
|
84
|
+
* Use index to find candidate document IDs (supports range queries with B-tree)
|
|
85
|
+
*/
|
|
86
|
+
findCandidateIds(filter: Document): Promise<Set<string> | null>;
|
|
87
|
+
/**
|
|
88
|
+
* Find candidates using B-tree range scan
|
|
89
|
+
*/
|
|
90
|
+
private findRangeCandidates;
|
|
91
|
+
private generateIndexName;
|
|
92
|
+
private extractKeyValue;
|
|
93
|
+
private buildKeyValue;
|
|
94
|
+
private getFilterFields;
|
|
95
|
+
private getFilterValue;
|
|
96
|
+
}
|
|
97
|
+
export {};
|