@push.rocks/smartmongo 2.2.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/index.d.ts +1 -1
- package/dist_ts/index.js +3 -3
- package/dist_ts/tsmdb/engine/AggregationEngine.js +189 -0
- package/dist_ts/tsmdb/engine/IndexEngine.js +376 -0
- package/dist_ts/tsmdb/engine/QueryEngine.js +271 -0
- package/dist_ts/{congodb → tsmdb}/engine/TransactionEngine.d.ts +1 -1
- package/dist_ts/tsmdb/engine/TransactionEngine.js +287 -0
- package/dist_ts/tsmdb/engine/UpdateEngine.js +461 -0
- package/dist_ts/{congodb/errors/CongoErrors.d.ts → tsmdb/errors/TsmdbErrors.d.ts} +16 -16
- package/dist_ts/tsmdb/errors/TsmdbErrors.js +155 -0
- package/dist_ts/{congodb → tsmdb}/index.d.ts +4 -4
- package/dist_ts/tsmdb/index.js +26 -0
- package/dist_ts/{congodb → tsmdb}/server/CommandRouter.d.ts +4 -4
- package/dist_ts/tsmdb/server/CommandRouter.js +132 -0
- package/dist_ts/{congodb/server/CongoServer.d.ts → tsmdb/server/TsmdbServer.d.ts} +6 -6
- package/dist_ts/tsmdb/server/TsmdbServer.js +227 -0
- package/dist_ts/{congodb → tsmdb}/server/WireProtocol.d.ts +1 -1
- package/dist_ts/tsmdb/server/WireProtocol.js +298 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/AdminHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/AdminHandler.js +568 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/AggregateHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/AggregateHandler.js +277 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/DeleteHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/DeleteHandler.js +83 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/FindHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/FindHandler.js +261 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/HelloHandler.d.ts +1 -1
- package/dist_ts/{congodb → tsmdb}/server/handlers/HelloHandler.js +2 -2
- package/dist_ts/{congodb → tsmdb}/server/handlers/IndexHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/IndexHandler.js +183 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/InsertHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/InsertHandler.js +76 -0
- package/dist_ts/{congodb → tsmdb}/server/handlers/UpdateHandler.d.ts +1 -1
- package/dist_ts/tsmdb/server/handlers/UpdateHandler.js +270 -0
- package/dist_ts/tsmdb/server/handlers/index.js +10 -0
- package/dist_ts/{congodb → tsmdb}/server/index.d.ts +2 -2
- package/dist_ts/tsmdb/server/index.js +7 -0
- package/dist_ts/{congodb → tsmdb}/storage/FileStorageAdapter.d.ts +2 -2
- package/dist_ts/tsmdb/storage/FileStorageAdapter.js +396 -0
- package/dist_ts/{congodb → tsmdb}/storage/IStorageAdapter.d.ts +2 -2
- package/dist_ts/{congodb → tsmdb}/storage/IStorageAdapter.js +1 -1
- package/dist_ts/{congodb → tsmdb}/storage/MemoryStorageAdapter.d.ts +2 -2
- package/dist_ts/tsmdb/storage/MemoryStorageAdapter.js +367 -0
- package/dist_ts/{congodb → tsmdb}/storage/OpLog.d.ts +1 -1
- package/dist_ts/tsmdb/storage/OpLog.js +221 -0
- package/dist_ts/tsmdb/tsmdb.plugins.js +14 -0
- package/dist_ts/{congodb → tsmdb}/types/interfaces.d.ts +3 -3
- package/dist_ts/{congodb → tsmdb}/types/interfaces.js +1 -1
- package/package.json +1 -1
- package/readme.hints.md +7 -12
- package/readme.md +25 -25
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/index.ts +2 -2
- package/ts/{congodb → tsmdb}/engine/AggregationEngine.ts +1 -1
- package/ts/{congodb → tsmdb}/engine/IndexEngine.ts +7 -7
- package/ts/{congodb → tsmdb}/engine/QueryEngine.ts +1 -1
- package/ts/{congodb → tsmdb}/engine/TransactionEngine.ts +12 -12
- package/ts/{congodb → tsmdb}/engine/UpdateEngine.ts +1 -1
- package/ts/{congodb/errors/CongoErrors.ts → tsmdb/errors/TsmdbErrors.ts} +34 -34
- package/ts/{congodb → tsmdb}/index.ts +7 -7
- package/ts/{congodb → tsmdb}/server/CommandRouter.ts +5 -5
- package/ts/{congodb/server/CongoServer.ts → tsmdb/server/TsmdbServer.ts} +8 -8
- package/ts/{congodb → tsmdb}/server/WireProtocol.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/AdminHandler.ts +6 -6
- package/ts/{congodb → tsmdb}/server/handlers/AggregateHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/DeleteHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/FindHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/HelloHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/IndexHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/InsertHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/handlers/UpdateHandler.ts +1 -1
- package/ts/{congodb → tsmdb}/server/index.ts +2 -2
- package/ts/{congodb → tsmdb}/storage/FileStorageAdapter.ts +2 -2
- package/ts/{congodb → tsmdb}/storage/IStorageAdapter.ts +2 -2
- package/ts/{congodb → tsmdb}/storage/MemoryStorageAdapter.ts +2 -2
- package/ts/{congodb → tsmdb}/storage/OpLog.ts +1 -1
- package/ts/{congodb → tsmdb}/types/interfaces.ts +3 -3
- package/dist_ts/congodb/congodb.plugins.js +0 -14
- package/dist_ts/congodb/engine/AggregationEngine.js +0 -189
- package/dist_ts/congodb/engine/IndexEngine.js +0 -376
- package/dist_ts/congodb/engine/QueryEngine.js +0 -271
- package/dist_ts/congodb/engine/TransactionEngine.js +0 -287
- package/dist_ts/congodb/engine/UpdateEngine.js +0 -461
- package/dist_ts/congodb/errors/CongoErrors.js +0 -155
- package/dist_ts/congodb/index.js +0 -26
- package/dist_ts/congodb/server/CommandRouter.js +0 -132
- package/dist_ts/congodb/server/CongoServer.js +0 -227
- package/dist_ts/congodb/server/WireProtocol.js +0 -298
- package/dist_ts/congodb/server/handlers/AdminHandler.js +0 -568
- package/dist_ts/congodb/server/handlers/AggregateHandler.js +0 -277
- package/dist_ts/congodb/server/handlers/DeleteHandler.js +0 -83
- package/dist_ts/congodb/server/handlers/FindHandler.js +0 -261
- package/dist_ts/congodb/server/handlers/IndexHandler.js +0 -183
- package/dist_ts/congodb/server/handlers/InsertHandler.js +0 -76
- package/dist_ts/congodb/server/handlers/UpdateHandler.js +0 -270
- package/dist_ts/congodb/server/handlers/index.js +0 -10
- package/dist_ts/congodb/server/index.js +0 -7
- package/dist_ts/congodb/storage/FileStorageAdapter.js +0 -396
- package/dist_ts/congodb/storage/MemoryStorageAdapter.js +0 -367
- package/dist_ts/congodb/storage/OpLog.js +0 -221
- /package/dist_ts/{congodb → tsmdb}/engine/AggregationEngine.d.ts +0 -0
- /package/dist_ts/{congodb → tsmdb}/engine/IndexEngine.d.ts +0 -0
- /package/dist_ts/{congodb → tsmdb}/engine/QueryEngine.d.ts +0 -0
- /package/dist_ts/{congodb → tsmdb}/engine/UpdateEngine.d.ts +0 -0
- /package/dist_ts/{congodb → tsmdb}/server/handlers/index.d.ts +0 -0
- /package/dist_ts/{congodb/congodb.plugins.d.ts → tsmdb/tsmdb.plugins.d.ts} +0 -0
- /package/ts/{congodb → tsmdb}/server/handlers/index.ts +0 -0
- /package/ts/{congodb/congodb.plugins.ts → tsmdb/tsmdb.plugins.ts} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import * as plugins from '../
|
|
1
|
+
import * as plugins from '../tsmdb.plugins.js';
|
|
2
2
|
import type { IStorageAdapter } from '../storage/IStorageAdapter.js';
|
|
3
3
|
import type { IParsedCommand } from './WireProtocol.js';
|
|
4
|
-
import type {
|
|
4
|
+
import type { TsmdbServer } from './TsmdbServer.js';
|
|
5
5
|
|
|
6
6
|
// Import handlers
|
|
7
7
|
import { HelloHandler } from './handlers/HelloHandler.js';
|
|
@@ -18,7 +18,7 @@ import { AdminHandler } from './handlers/AdminHandler.js';
|
|
|
18
18
|
*/
|
|
19
19
|
export interface IHandlerContext {
|
|
20
20
|
storage: IStorageAdapter;
|
|
21
|
-
server:
|
|
21
|
+
server: TsmdbServer;
|
|
22
22
|
database: string;
|
|
23
23
|
command: plugins.bson.Document;
|
|
24
24
|
documentSequences?: Map<string, plugins.bson.Document[]>;
|
|
@@ -36,14 +36,14 @@ export interface ICommandHandler {
|
|
|
36
36
|
*/
|
|
37
37
|
export class CommandRouter {
|
|
38
38
|
private storage: IStorageAdapter;
|
|
39
|
-
private server:
|
|
39
|
+
private server: TsmdbServer;
|
|
40
40
|
private handlers: Map<string, ICommandHandler> = new Map();
|
|
41
41
|
|
|
42
42
|
// Cursor state for getMore operations
|
|
43
43
|
private cursors: Map<bigint, ICursorState> = new Map();
|
|
44
44
|
private cursorIdCounter: bigint = BigInt(1);
|
|
45
45
|
|
|
46
|
-
constructor(storage: IStorageAdapter, server:
|
|
46
|
+
constructor(storage: IStorageAdapter, server: TsmdbServer) {
|
|
47
47
|
this.storage = storage;
|
|
48
48
|
this.server = server;
|
|
49
49
|
this.registerHandlers();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as net from 'net';
|
|
2
|
-
import * as plugins from '../
|
|
2
|
+
import * as plugins from '../tsmdb.plugins.js';
|
|
3
3
|
import { WireProtocol, OP_QUERY } from './WireProtocol.js';
|
|
4
4
|
import { CommandRouter } from './CommandRouter.js';
|
|
5
5
|
import { MemoryStorageAdapter } from '../storage/MemoryStorageAdapter.js';
|
|
@@ -9,7 +9,7 @@ import type { IStorageAdapter } from '../storage/IStorageAdapter.js';
|
|
|
9
9
|
/**
|
|
10
10
|
* Server configuration options
|
|
11
11
|
*/
|
|
12
|
-
export interface
|
|
12
|
+
export interface ITsmdbServerOptions {
|
|
13
13
|
/** Port to listen on (default: 27017) */
|
|
14
14
|
port?: number;
|
|
15
15
|
/** Host to bind to (default: 127.0.0.1) */
|
|
@@ -36,25 +36,25 @@ interface IConnectionState {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
*
|
|
39
|
+
* TsmdbServer - MongoDB Wire Protocol compatible server
|
|
40
40
|
*
|
|
41
41
|
* This server implements the MongoDB wire protocol (OP_MSG) to allow
|
|
42
42
|
* official MongoDB drivers to connect and perform operations.
|
|
43
43
|
*
|
|
44
44
|
* @example
|
|
45
45
|
* ```typescript
|
|
46
|
-
* import {
|
|
46
|
+
* import { TsmdbServer } from '@push.rocks/smartmongo/tsmdb';
|
|
47
47
|
* import { MongoClient } from 'mongodb';
|
|
48
48
|
*
|
|
49
|
-
* const server = new
|
|
49
|
+
* const server = new TsmdbServer({ port: 27017 });
|
|
50
50
|
* await server.start();
|
|
51
51
|
*
|
|
52
52
|
* const client = new MongoClient('mongodb://127.0.0.1:27017');
|
|
53
53
|
* await client.connect();
|
|
54
54
|
* ```
|
|
55
55
|
*/
|
|
56
|
-
export class
|
|
57
|
-
private options: Required<
|
|
56
|
+
export class TsmdbServer {
|
|
57
|
+
private options: Required<ITsmdbServerOptions>;
|
|
58
58
|
private server: net.Server | null = null;
|
|
59
59
|
private storage: IStorageAdapter;
|
|
60
60
|
private commandRouter: CommandRouter;
|
|
@@ -63,7 +63,7 @@ export class CongoServer {
|
|
|
63
63
|
private isRunning = false;
|
|
64
64
|
private startTime: Date = new Date();
|
|
65
65
|
|
|
66
|
-
constructor(options:
|
|
66
|
+
constructor(options: ITsmdbServerOptions = {}) {
|
|
67
67
|
this.options = {
|
|
68
68
|
port: options.port ?? 27017,
|
|
69
69
|
host: options.host ?? '127.0.0.1',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as plugins from '../../
|
|
1
|
+
import * as plugins from '../../tsmdb.plugins.js';
|
|
2
2
|
import type { ICommandHandler, IHandlerContext } from '../CommandRouter.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -246,7 +246,7 @@ export class AdminHandler implements ICommandHandler {
|
|
|
246
246
|
ok: 1,
|
|
247
247
|
host: `${server.host}:${server.port}`,
|
|
248
248
|
version: '7.0.0',
|
|
249
|
-
process: '
|
|
249
|
+
process: 'tsmdb',
|
|
250
250
|
pid: process.pid,
|
|
251
251
|
uptime,
|
|
252
252
|
uptimeMillis: uptime * 1000,
|
|
@@ -269,7 +269,7 @@ export class AdminHandler implements ICommandHandler {
|
|
|
269
269
|
numRequests: 0,
|
|
270
270
|
},
|
|
271
271
|
storageEngine: {
|
|
272
|
-
name: '
|
|
272
|
+
name: 'tsmdb',
|
|
273
273
|
supportsCommittedReads: true,
|
|
274
274
|
persistent: false,
|
|
275
275
|
},
|
|
@@ -283,7 +283,7 @@ export class AdminHandler implements ICommandHandler {
|
|
|
283
283
|
return {
|
|
284
284
|
ok: 1,
|
|
285
285
|
version: '7.0.0',
|
|
286
|
-
gitVersion: '
|
|
286
|
+
gitVersion: 'tsmdb',
|
|
287
287
|
modules: [],
|
|
288
288
|
allocator: 'system',
|
|
289
289
|
javascriptEngine: 'none',
|
|
@@ -294,7 +294,7 @@ export class AdminHandler implements ICommandHandler {
|
|
|
294
294
|
compiled: 'disabled',
|
|
295
295
|
},
|
|
296
296
|
buildEnvironment: {
|
|
297
|
-
distmod: '
|
|
297
|
+
distmod: 'tsmdb',
|
|
298
298
|
distarch: process.arch,
|
|
299
299
|
cc: '',
|
|
300
300
|
ccflags: '',
|
|
@@ -307,7 +307,7 @@ export class AdminHandler implements ICommandHandler {
|
|
|
307
307
|
bits: 64,
|
|
308
308
|
debug: false,
|
|
309
309
|
maxBsonObjectSize: 16777216,
|
|
310
|
-
storageEngines: ['
|
|
310
|
+
storageEngines: ['tsmdb'],
|
|
311
311
|
};
|
|
312
312
|
}
|
|
313
313
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as plugins from '../../
|
|
1
|
+
import * as plugins from '../../tsmdb.plugins.js';
|
|
2
2
|
import type { ICommandHandler, IHandlerContext, ICursorState } from '../CommandRouter.js';
|
|
3
3
|
import { AggregationEngine } from '../../engine/AggregationEngine.js';
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as plugins from '../../
|
|
1
|
+
import * as plugins from '../../tsmdb.plugins.js';
|
|
2
2
|
import type { ICommandHandler, IHandlerContext } from '../CommandRouter.js';
|
|
3
3
|
import { QueryEngine } from '../../engine/QueryEngine.js';
|
|
4
4
|
import { UpdateEngine } from '../../engine/UpdateEngine.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Server module exports
|
|
2
2
|
|
|
3
|
-
export {
|
|
4
|
-
export type {
|
|
3
|
+
export { TsmdbServer } from './TsmdbServer.js';
|
|
4
|
+
export type { ITsmdbServerOptions } from './TsmdbServer.js';
|
|
5
5
|
export { WireProtocol } from './WireProtocol.js';
|
|
6
6
|
export { CommandRouter } from './CommandRouter.js';
|
|
7
7
|
export type { ICommandHandler, IHandlerContext, ICursorState } from './CommandRouter.js';
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as plugins from '../
|
|
1
|
+
import * as plugins from '../tsmdb.plugins.js';
|
|
2
2
|
import type { IStorageAdapter } from './IStorageAdapter.js';
|
|
3
3
|
import type { IStoredDocument, IOpLogEntry, Document } from '../types/interfaces.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* File-based storage adapter for
|
|
6
|
+
* File-based storage adapter for TsmDB
|
|
7
7
|
* Stores data in JSON files on disk for persistence
|
|
8
8
|
*/
|
|
9
9
|
export class FileStorageAdapter implements IStorageAdapter {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type * as plugins from '../
|
|
1
|
+
import type * as plugins from '../tsmdb.plugins.js';
|
|
2
2
|
import type { IStoredDocument, IOpLogEntry, Document } from '../types/interfaces.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Storage adapter interface for
|
|
5
|
+
* Storage adapter interface for TsmDB
|
|
6
6
|
* Implementations can provide different storage backends (memory, file, etc.)
|
|
7
7
|
*/
|
|
8
8
|
export interface IStorageAdapter {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import * as plugins from '../
|
|
1
|
+
import * as plugins from '../tsmdb.plugins.js';
|
|
2
2
|
import type { IStorageAdapter } from './IStorageAdapter.js';
|
|
3
3
|
import type { IStoredDocument, IOpLogEntry, Document } from '../types/interfaces.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* In-memory storage adapter for
|
|
6
|
+
* In-memory storage adapter for TsmDB
|
|
7
7
|
* Optionally supports persistence to a file
|
|
8
8
|
*/
|
|
9
9
|
export class MemoryStorageAdapter implements IStorageAdapter {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as plugins from '../
|
|
1
|
+
import * as plugins from '../tsmdb.plugins.js';
|
|
2
2
|
import type { IStorageAdapter } from './IStorageAdapter.js';
|
|
3
3
|
import type { IOpLogEntry, Document, IResumeToken, ChangeStreamOperationType } from '../types/interfaces.js';
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type * as plugins from '../
|
|
1
|
+
import type * as plugins from '../tsmdb.plugins.js';
|
|
2
2
|
|
|
3
3
|
// ============================================================================
|
|
4
4
|
// Document Types
|
|
@@ -14,7 +14,7 @@ export interface WithId<TSchema> {
|
|
|
14
14
|
// Client Options
|
|
15
15
|
// ============================================================================
|
|
16
16
|
|
|
17
|
-
export interface
|
|
17
|
+
export interface ITsmdbClientOptions {
|
|
18
18
|
/** Storage adapter type: 'memory' or 'file' */
|
|
19
19
|
storageType?: 'memory' | 'file';
|
|
20
20
|
/** Path for file-based storage */
|
|
@@ -30,7 +30,7 @@ export interface ICongoClientOptions {
|
|
|
30
30
|
// ============================================================================
|
|
31
31
|
|
|
32
32
|
export interface IParsedConnectionString {
|
|
33
|
-
protocol: '
|
|
33
|
+
protocol: 'tsmdb';
|
|
34
34
|
storageType: 'memory' | 'file';
|
|
35
35
|
options: {
|
|
36
36
|
persist?: string;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
// @push.rocks scope
|
|
2
|
-
import * as smartfs from '@push.rocks/smartfs';
|
|
3
|
-
import * as smartpath from '@push.rocks/smartpath';
|
|
4
|
-
import * as smartpromise from '@push.rocks/smartpromise';
|
|
5
|
-
import * as smartrx from '@push.rocks/smartrx';
|
|
6
|
-
export { smartfs, smartpath, smartpromise, smartrx };
|
|
7
|
-
// thirdparty
|
|
8
|
-
import * as bson from 'bson';
|
|
9
|
-
import * as mingo from 'mingo';
|
|
10
|
-
export { bson, mingo };
|
|
11
|
-
// Re-export commonly used mingo classes
|
|
12
|
-
export { Query } from 'mingo';
|
|
13
|
-
export { Aggregator } from 'mingo';
|
|
14
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZ29kYi5wbHVnaW5zLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvY29uZ29kYi9jb25nb2RiLnBsdWdpbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsb0JBQW9CO0FBQ3BCLE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFDL0MsT0FBTyxLQUFLLFNBQVMsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRCxPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxPQUFPLE1BQU0scUJBQXFCLENBQUM7QUFFL0MsT0FBTyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxDQUFDO0FBRXJELGFBQWE7QUFDYixPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEtBQUssS0FBSyxNQUFNLE9BQU8sQ0FBQztBQUUvQixPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDO0FBRXZCLHdDQUF3QztBQUN4QyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBQzlCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxPQUFPLENBQUMifQ==
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import * as plugins from '../congodb.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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQWdncmVnYXRpb25FbmdpbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb25nb2RiL2VuZ2luZS9BZ2dyZWdhdGlvbkVuZ2luZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLHVCQUF1QixDQUFDO0FBR2pELDBCQUEwQjtBQUMxQixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sT0FBTyxDQUFDO0FBRW5DOztHQUVHO0FBQ0gsTUFBTSxPQUFPLGlCQUFpQjtJQUM1Qjs7T0FFRztJQUNILE1BQU0sQ0FBQyxTQUFTLENBQ2QsU0FBNEIsRUFDNUIsUUFBb0IsRUFDcEIsT0FBMkI7UUFFM0IsSUFBSSxDQUFDLFFBQVEsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUM7UUFFRCw0Q0FBNEM7UUFDNUMsTUFBTSxVQUFVLEdBQUcsSUFBSSxVQUFVLENBQUMsUUFBUSxFQUFFO1lBQzFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsU0FBZ0I7U0FDckMsQ0FBQyxDQUFDO1FBRUgsc0JBQXNCO1FBQ3RCLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFekMsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUM3QyxDQUFDO0lBRUQ7O09BRUc7SUFDSCxNQUFNLENBQUMsQ0FBQyxpQkFBaUIsQ0FDdkIsU0FBNEIsRUFDNUIsUUFBb0IsRUFDcEIsT0FBMkI7UUFFM0IsTUFBTSxVQUFVLEdBQUcsSUFBSSxVQUFVLENBQUMsUUFBUSxFQUFFO1lBQzFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsU0FBZ0I7U0FDckMsQ0FBQyxDQUFDO1FBRUgsNEJBQTRCO1FBQzVCLE1BQU0sTUFBTSxHQUFH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
|