@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,102 @@
|
|
|
1
|
+
import type { IStorageAdapter } from '../storage/IStorageAdapter.js';
|
|
2
|
+
/**
|
|
3
|
+
* Server configuration options
|
|
4
|
+
*/
|
|
5
|
+
export interface ISmartdbServerOptions {
|
|
6
|
+
/** Port to listen on (default: 27017) - ignored if socketPath is set */
|
|
7
|
+
port?: number;
|
|
8
|
+
/** Host to bind to (default: 127.0.0.1) - ignored if socketPath is set */
|
|
9
|
+
host?: string;
|
|
10
|
+
/** Unix socket path - if set, server listens on socket instead of TCP */
|
|
11
|
+
socketPath?: string;
|
|
12
|
+
/** Storage type: 'memory' or 'file' (default: 'memory') */
|
|
13
|
+
storage?: 'memory' | 'file';
|
|
14
|
+
/** Path for file storage (required if storage is 'file') */
|
|
15
|
+
storagePath?: string;
|
|
16
|
+
/** Enable persistence for memory storage */
|
|
17
|
+
persistPath?: string;
|
|
18
|
+
/** Persistence interval in ms (default: 60000) */
|
|
19
|
+
persistIntervalMs?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* SmartdbServer - MongoDB Wire Protocol compatible server
|
|
23
|
+
*
|
|
24
|
+
* This server implements the MongoDB wire protocol (OP_MSG) to allow
|
|
25
|
+
* official MongoDB drivers to connect and perform operations.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import { SmartdbServer } from '@push.rocks/smartmongo/smartdb';
|
|
30
|
+
* import { MongoClient } from 'mongodb';
|
|
31
|
+
*
|
|
32
|
+
* const server = new SmartdbServer({ port: 27017 });
|
|
33
|
+
* await server.start();
|
|
34
|
+
*
|
|
35
|
+
* const client = new MongoClient('mongodb://127.0.0.1:27017');
|
|
36
|
+
* await client.connect();
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare class SmartdbServer {
|
|
40
|
+
private options;
|
|
41
|
+
private server;
|
|
42
|
+
private storage;
|
|
43
|
+
private commandRouter;
|
|
44
|
+
private connections;
|
|
45
|
+
private connectionIdCounter;
|
|
46
|
+
private isRunning;
|
|
47
|
+
private startTime;
|
|
48
|
+
private useSocket;
|
|
49
|
+
constructor(options?: ISmartdbServerOptions);
|
|
50
|
+
/**
|
|
51
|
+
* Get the storage adapter (for testing/debugging)
|
|
52
|
+
*/
|
|
53
|
+
getStorage(): IStorageAdapter;
|
|
54
|
+
/**
|
|
55
|
+
* Get server uptime in seconds
|
|
56
|
+
*/
|
|
57
|
+
getUptime(): number;
|
|
58
|
+
/**
|
|
59
|
+
* Get current connection count
|
|
60
|
+
*/
|
|
61
|
+
getConnectionCount(): number;
|
|
62
|
+
/**
|
|
63
|
+
* Start the server
|
|
64
|
+
*/
|
|
65
|
+
start(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Stop the server
|
|
68
|
+
*/
|
|
69
|
+
stop(): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Handle a new client connection
|
|
72
|
+
*/
|
|
73
|
+
private handleConnection;
|
|
74
|
+
/**
|
|
75
|
+
* Handle incoming data from a client
|
|
76
|
+
*/
|
|
77
|
+
private handleData;
|
|
78
|
+
/**
|
|
79
|
+
* Process complete messages from the buffer
|
|
80
|
+
*/
|
|
81
|
+
private processMessages;
|
|
82
|
+
/**
|
|
83
|
+
* Get the connection URI for this server
|
|
84
|
+
*/
|
|
85
|
+
getConnectionUri(): string;
|
|
86
|
+
/**
|
|
87
|
+
* Get the socket path (if using Unix socket mode)
|
|
88
|
+
*/
|
|
89
|
+
get socketPath(): string | undefined;
|
|
90
|
+
/**
|
|
91
|
+
* Check if the server is running
|
|
92
|
+
*/
|
|
93
|
+
get running(): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Get the port the server is listening on
|
|
96
|
+
*/
|
|
97
|
+
get port(): number;
|
|
98
|
+
/**
|
|
99
|
+
* Get the host the server is bound to
|
|
100
|
+
*/
|
|
101
|
+
get host(): string;
|
|
102
|
+
}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import * as net from 'net';
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
import * as plugins from '../plugins.js';
|
|
4
|
+
import { WireProtocol, OP_QUERY } from './WireProtocol.js';
|
|
5
|
+
import { CommandRouter } from './CommandRouter.js';
|
|
6
|
+
import { MemoryStorageAdapter } from '../storage/MemoryStorageAdapter.js';
|
|
7
|
+
import { FileStorageAdapter } from '../storage/FileStorageAdapter.js';
|
|
8
|
+
/**
|
|
9
|
+
* SmartdbServer - MongoDB Wire Protocol compatible server
|
|
10
|
+
*
|
|
11
|
+
* This server implements the MongoDB wire protocol (OP_MSG) to allow
|
|
12
|
+
* official MongoDB drivers to connect and perform operations.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* import { SmartdbServer } from '@push.rocks/smartmongo/smartdb';
|
|
17
|
+
* import { MongoClient } from 'mongodb';
|
|
18
|
+
*
|
|
19
|
+
* const server = new SmartdbServer({ port: 27017 });
|
|
20
|
+
* await server.start();
|
|
21
|
+
*
|
|
22
|
+
* const client = new MongoClient('mongodb://127.0.0.1:27017');
|
|
23
|
+
* await client.connect();
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export class SmartdbServer {
|
|
27
|
+
options;
|
|
28
|
+
server = null;
|
|
29
|
+
storage;
|
|
30
|
+
commandRouter;
|
|
31
|
+
connections = new Map();
|
|
32
|
+
connectionIdCounter = 0;
|
|
33
|
+
isRunning = false;
|
|
34
|
+
startTime = new Date();
|
|
35
|
+
useSocket;
|
|
36
|
+
constructor(options = {}) {
|
|
37
|
+
this.useSocket = !!options.socketPath;
|
|
38
|
+
this.options = {
|
|
39
|
+
port: options.port ?? 27017,
|
|
40
|
+
host: options.host ?? '127.0.0.1',
|
|
41
|
+
socketPath: options.socketPath ?? '',
|
|
42
|
+
storage: options.storage ?? 'memory',
|
|
43
|
+
storagePath: options.storagePath ?? './data',
|
|
44
|
+
persistPath: options.persistPath ?? '',
|
|
45
|
+
persistIntervalMs: options.persistIntervalMs ?? 60000,
|
|
46
|
+
};
|
|
47
|
+
// Create storage adapter
|
|
48
|
+
if (this.options.storage === 'file') {
|
|
49
|
+
this.storage = new FileStorageAdapter(this.options.storagePath);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
this.storage = new MemoryStorageAdapter({
|
|
53
|
+
persistPath: this.options.persistPath || undefined,
|
|
54
|
+
persistIntervalMs: this.options.persistPath ? this.options.persistIntervalMs : undefined,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
// Create command router
|
|
58
|
+
this.commandRouter = new CommandRouter(this.storage, this);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get the storage adapter (for testing/debugging)
|
|
62
|
+
*/
|
|
63
|
+
getStorage() {
|
|
64
|
+
return this.storage;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get server uptime in seconds
|
|
68
|
+
*/
|
|
69
|
+
getUptime() {
|
|
70
|
+
return Math.floor((Date.now() - this.startTime.getTime()) / 1000);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get current connection count
|
|
74
|
+
*/
|
|
75
|
+
getConnectionCount() {
|
|
76
|
+
return this.connections.size;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Start the server
|
|
80
|
+
*/
|
|
81
|
+
async start() {
|
|
82
|
+
if (this.isRunning) {
|
|
83
|
+
throw new Error('Server is already running');
|
|
84
|
+
}
|
|
85
|
+
// Initialize storage
|
|
86
|
+
await this.storage.initialize();
|
|
87
|
+
// Clean up stale socket file if using Unix socket
|
|
88
|
+
if (this.useSocket && this.options.socketPath) {
|
|
89
|
+
try {
|
|
90
|
+
await fs.unlink(this.options.socketPath);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
// Ignore ENOENT (file doesn't exist)
|
|
94
|
+
if (err.code !== 'ENOENT') {
|
|
95
|
+
throw err;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
this.server = net.createServer((socket) => {
|
|
101
|
+
this.handleConnection(socket);
|
|
102
|
+
});
|
|
103
|
+
this.server.on('error', (err) => {
|
|
104
|
+
if (!this.isRunning) {
|
|
105
|
+
reject(err);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
console.error('Server error:', err);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
if (this.useSocket && this.options.socketPath) {
|
|
112
|
+
// Listen on Unix socket
|
|
113
|
+
this.server.listen(this.options.socketPath, () => {
|
|
114
|
+
this.isRunning = true;
|
|
115
|
+
this.startTime = new Date();
|
|
116
|
+
resolve();
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
// Listen on TCP
|
|
121
|
+
this.server.listen(this.options.port, this.options.host, () => {
|
|
122
|
+
this.isRunning = true;
|
|
123
|
+
this.startTime = new Date();
|
|
124
|
+
resolve();
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Stop the server
|
|
131
|
+
*/
|
|
132
|
+
async stop() {
|
|
133
|
+
if (!this.isRunning || !this.server) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Close all connections
|
|
137
|
+
for (const conn of this.connections.values()) {
|
|
138
|
+
conn.socket.destroy();
|
|
139
|
+
}
|
|
140
|
+
this.connections.clear();
|
|
141
|
+
// Close command router (cleans up session engine, cursors, etc.)
|
|
142
|
+
this.commandRouter.close();
|
|
143
|
+
// Close storage
|
|
144
|
+
await this.storage.close();
|
|
145
|
+
return new Promise((resolve) => {
|
|
146
|
+
this.server.close(async () => {
|
|
147
|
+
this.isRunning = false;
|
|
148
|
+
this.server = null;
|
|
149
|
+
// Clean up socket file if using Unix socket
|
|
150
|
+
if (this.useSocket && this.options.socketPath) {
|
|
151
|
+
try {
|
|
152
|
+
await fs.unlink(this.options.socketPath);
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
// Ignore ENOENT (file doesn't exist)
|
|
156
|
+
if (err.code !== 'ENOENT') {
|
|
157
|
+
console.error('Failed to remove socket file:', err);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
resolve();
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Handle a new client connection
|
|
167
|
+
*/
|
|
168
|
+
handleConnection(socket) {
|
|
169
|
+
const connectionId = ++this.connectionIdCounter;
|
|
170
|
+
const state = {
|
|
171
|
+
id: connectionId,
|
|
172
|
+
socket,
|
|
173
|
+
buffer: Buffer.alloc(0),
|
|
174
|
+
authenticated: true, // No auth required for now
|
|
175
|
+
database: 'test',
|
|
176
|
+
};
|
|
177
|
+
this.connections.set(connectionId, state);
|
|
178
|
+
socket.on('data', (data) => {
|
|
179
|
+
this.handleData(state, Buffer.isBuffer(data) ? data : Buffer.from(data));
|
|
180
|
+
});
|
|
181
|
+
socket.on('close', () => {
|
|
182
|
+
this.connections.delete(connectionId);
|
|
183
|
+
});
|
|
184
|
+
socket.on('error', (err) => {
|
|
185
|
+
// Connection errors are expected when clients disconnect
|
|
186
|
+
this.connections.delete(connectionId);
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Handle incoming data from a client
|
|
191
|
+
*/
|
|
192
|
+
handleData(state, data) {
|
|
193
|
+
// Append new data to buffer
|
|
194
|
+
state.buffer = Buffer.concat([state.buffer, data]);
|
|
195
|
+
// Process messages from buffer
|
|
196
|
+
this.processMessages(state);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Process complete messages from the buffer
|
|
200
|
+
*/
|
|
201
|
+
async processMessages(state) {
|
|
202
|
+
while (state.buffer.length >= 16) {
|
|
203
|
+
try {
|
|
204
|
+
const result = WireProtocol.parseMessage(state.buffer);
|
|
205
|
+
if (!result) {
|
|
206
|
+
// Not enough data for a complete message
|
|
207
|
+
break;
|
|
208
|
+
}
|
|
209
|
+
const { command, bytesConsumed } = result;
|
|
210
|
+
// Remove processed bytes from buffer
|
|
211
|
+
state.buffer = state.buffer.subarray(bytesConsumed);
|
|
212
|
+
// Process the command
|
|
213
|
+
const response = await this.commandRouter.route(command);
|
|
214
|
+
// Encode and send response
|
|
215
|
+
let responseBuffer;
|
|
216
|
+
if (command.opCode === OP_QUERY) {
|
|
217
|
+
// Legacy OP_QUERY gets OP_REPLY response
|
|
218
|
+
responseBuffer = WireProtocol.encodeOpReplyResponse(command.requestID, [response]);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
// OP_MSG gets OP_MSG response
|
|
222
|
+
responseBuffer = WireProtocol.encodeOpMsgResponse(command.requestID, response);
|
|
223
|
+
}
|
|
224
|
+
if (!state.socket.destroyed) {
|
|
225
|
+
state.socket.write(responseBuffer);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
catch (error) {
|
|
229
|
+
// Send error response
|
|
230
|
+
const errorResponse = WireProtocol.encodeErrorResponse(0, // We don't have the requestID at this point
|
|
231
|
+
1, error.message || 'Internal error');
|
|
232
|
+
if (!state.socket.destroyed) {
|
|
233
|
+
state.socket.write(errorResponse);
|
|
234
|
+
}
|
|
235
|
+
// Clear buffer on parse errors to avoid infinite loops
|
|
236
|
+
if (error.message?.includes('opCode') || error.message?.includes('section')) {
|
|
237
|
+
state.buffer = Buffer.alloc(0);
|
|
238
|
+
}
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Get the connection URI for this server
|
|
245
|
+
*/
|
|
246
|
+
getConnectionUri() {
|
|
247
|
+
if (this.useSocket && this.options.socketPath) {
|
|
248
|
+
// URL-encode the socket path (replace / with %2F)
|
|
249
|
+
const encodedPath = encodeURIComponent(this.options.socketPath);
|
|
250
|
+
return `mongodb://${encodedPath}`;
|
|
251
|
+
}
|
|
252
|
+
return `mongodb://${this.options.host}:${this.options.port}`;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Get the socket path (if using Unix socket mode)
|
|
256
|
+
*/
|
|
257
|
+
get socketPath() {
|
|
258
|
+
return this.useSocket ? this.options.socketPath : undefined;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Check if the server is running
|
|
262
|
+
*/
|
|
263
|
+
get running() {
|
|
264
|
+
return this.isRunning;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Get the port the server is listening on
|
|
268
|
+
*/
|
|
269
|
+
get port() {
|
|
270
|
+
return this.options.port;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Get the host the server is bound to
|
|
274
|
+
*/
|
|
275
|
+
get host() {
|
|
276
|
+
return this.options.host;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU21hcnRkYlNlcnZlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzL3RzX3NtYXJ0ZGIvc2VydmVyL1NtYXJ0ZGJTZXJ2ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEdBQUcsTUFBTSxLQUFLLENBQUM7QUFDM0IsT0FBTyxLQUFLLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbEMsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbkQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDMUUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFrQ3RFOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBQ2hCLE9BQU8sQ0FBK0U7SUFDdEYsTUFBTSxHQUFzQixJQUFJLENBQUM7SUFDakMsT0FBTyxDQUFrQjtJQUN6QixhQUFhLENBQWdCO0lBQzdCLFdBQVcsR0FBa0MsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUN2RCxtQkFBbUIsR0FBRyxDQUFDLENBQUM7SUFDeEIsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNsQixTQUFTLEdBQVMsSUFBSSxJQUFJLEVBQUUsQ0FBQztJQUM3QixTQUFTLENBQVU7SUFFM0IsWUFBWSxVQUFpQyxFQUFFO1FBQzdDLElBQUksQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUM7UUFDdEMsSUFBSSxDQUFDLE9BQU8sR0FBRztZQUNiLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxJQUFJLEtBQUs7WUFDM0IsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJLElBQUksV0FBVztZQUNqQyxVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVUsSUFBSSxFQUFFO1lBQ3BDLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTyxJQUFJLFFBQVE7WUFDcEMsV0FBVyxFQUFFLE9BQU8sQ0FBQyxXQUFXLElBQUksUUFBUTtZQUM1QyxXQUFXLEVBQUUsT0FBTyxDQUFDLFdBQVcsSUFBSSxFQUFFO1lBQ3RDLGlCQUFpQixFQUFFLE9BQU8sQ0FBQyxpQkFBaUIsSUFBSSxLQUFLO1NBQ3RELENBQUM7UUFFRix5QkFBeUI7UUFDekIsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUNwQyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksa0JBQWtCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNsRSxDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxvQkFBb0IsQ0FBQztnQkFDdEMsV0FBVyxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxJQUFJLFNBQVM7Z0JBQ2xELGlCQUFpQixFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxTQUFTO2FBQ3pGLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCx3QkFBd0I7UUFDeEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLGFBQWEsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFFRDs7T0FFRztJQUNILFVBQVU7UUFDUixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDdEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUztRQUNQLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDcEUsQ0FBQztJQUVEOztPQUVHO0lBQ0gsa0JBQWtCO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7SUFDL0IsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLEtBQUs7UUFDVCxJQUFJLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNuQixNQUFNLElBQUksS0FBSyxDQUFDLDJCQUEyQixDQUFDLENBQUM7UUFDL0MsQ0FBQztRQUVELHFCQUFxQjtRQUNyQixNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUM7UUFFaEMsa0RBQWtEO1FBQ2xELElBQUksSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzlDLElBQUksQ0FBQztnQkFDSCxNQUFNLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUMzQyxDQUFDO1lBQUMsT0FBTyxHQUFRLEVBQUUsQ0FBQztnQkFDbEIscUNBQXFDO2dCQUNyQyxJQUFJLEdBQUcsQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7b0JBQzFCLE1BQU0sR0FBRyxDQUFDO2dCQUNaLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUVELE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7WUFDckMsSUFBSSxDQUFDLE1BQU0sR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7Z0JBQ3hDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNoQyxDQUFDLENBQUMsQ0FBQztZQUVILElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUM5QixJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO29CQUNwQixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ2QsQ0FBQztxQkFBTSxDQUFDO29CQUNOLE9BQU8sQ0FBQyxLQUFLLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUN0QyxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7WUFFSCxJQUFJLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDOUMsd0JBQXdCO2dCQUN4QixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxHQUFHLEVBQUU7b0JBQy9DLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO29CQUN0QixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7b0JBQzVCLE9BQU8sRUFBRSxDQUFDO2dCQUNaLENBQUMsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLGdCQUFnQjtnQkFDaEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFO29CQUM1RCxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztvQkFDdEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO29CQUM1QixPQUFPLEVBQUUsQ0FBQztnQkFDWixDQUFDLENBQUMsQ0FBQztZQUNMLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNILEtBQUssQ0FBQyxJQUFJO1FBQ1IsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDcEMsT0FBTztRQUNULENBQUM7UUFFRCx3QkFBd0I7UUFDeEIsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDN0MsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN4QixDQUFDO1FBQ0QsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUV6QixpRUFBaUU7UUFDakUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUUzQixnQkFBZ0I7UUFDaEIsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBRTNCLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUM3QixJQUFJLENBQUMsTUFBTyxDQUFDLEtBQUssQ0FBQyxLQUFLLElBQUksRUFBRTtnQkFDNUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUM7Z0JBQ3ZCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO2dCQUVuQiw0Q0FBNEM7Z0JBQzVDLElBQUksSUFBSSxDQUFDLFNBQVMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDO29CQUM5QyxJQUFJLENBQUM7d0JBQ0gsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQzNDLENBQUM7b0JBQUMsT0FBTyxHQUFRLEVBQUUsQ0FBQzt3QkFDbEIscUNBQXFDO3dCQUNyQyxJQUFJLEdBQUcsQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7NEJBQzFCLE9BQU8sQ0FBQyxLQUFLLENBQUMsK0JBQStCLEVBQUUsR0FBRyxDQUFDLENBQUM7d0JBQ3RELENBQUM7b0JBQ0gsQ0FBQztnQkFDSCxDQUFDO2dCQUVELE9BQU8sRUFBRSxDQUFDO1lBQ1osQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNLLGdCQUFnQixDQUFDLE1BQWtCO1FBQ3pDLE1BQU0sWUFBWSxHQUFHLEVBQUUsSUFBSSxDQUFDLG1CQUFtQixDQUFDO1FBRWhELE1BQU0sS0FBSyxHQUFxQjtZQUM5QixFQUFFLEVBQUUsWUFBWTtZQUNoQixNQUFNO1lBQ04sTUFBTSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1lBQ3ZCLGFBQWEsRUFBRSxJQUFJLEVBQUUsMkJBQTJCO1lBQ2hELFFBQVEsRUFBRSxNQUFNO1NBQ2pCLENBQUM7UUFFRixJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFFMUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUN6QixJQUFJLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUMzRSxDQUFDLENBQUMsQ0FBQztRQUVILE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRTtZQUN0QixJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUN4QyxDQUFDLENBQUMsQ0FBQztRQUVILE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsR0FBRyxFQUFFLEVBQUU7WUFDekIseURBQXlEO1lBQ3pELElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3hDLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0ssVUFBVSxDQUFDLEtBQXVCLEVBQUUsSUFBWTtRQUN0RCw0QkFBNEI7UUFDNUIsS0FBSyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBRW5ELCtCQUErQjtRQUMvQixJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzlCLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxlQUFlLENBQUMsS0FBdUI7UUFDbkQsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sSUFBSSxFQUFFLEVBQUUsQ0FBQztZQUNqQyxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBRXZELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztvQkFDWix5Q0FBeUM7b0JBQ3pDLE1BQU07Z0JBQ1IsQ0FBQztnQkFFRCxNQUFNLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxHQUFHLE1BQU0sQ0FBQztnQkFFMUMscUNBQXFDO2dCQUNyQyxLQUFLLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDO2dCQUVwRCxzQkFBc0I7Z0JBQ3RCLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBRXpELDJCQUEyQjtnQkFDM0IsSUFBSSxjQUFzQixDQUFDO2dCQUMzQixJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7b0JBQ2hDLHlDQUF5QztvQkFDekMsY0FBYyxHQUFHLFlBQVksQ0FBQyxxQkFBcUIsQ0FDakQsT0FBTyxDQUFDLFNBQVMsRUFDakIsQ0FBQyxRQUFRLENBQUMsQ0FDWCxDQUFDO2dCQUNKLENBQUM7cUJBQU0sQ0FBQztvQkFDTiw4QkFBOEI7b0JBQzlCLGNBQWMsR0FBRyxZQUFZLENBQUMsbUJBQW1CLENBQy9DLE9BQU8sQ0FBQyxTQUFTLEVBQ2pCLFFBQVEsQ0FDVCxDQUFDO2dCQUNKLENBQUM7Z0JBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7b0JBQzVCLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxDQUFDO2dCQUNyQyxDQUFDO1lBQ0gsQ0FBQztZQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7Z0JBQ3BCLHNCQUFzQjtnQkFDdEIsTUFBTSxhQUFhLEdBQUcsWUFBWSxDQUFDLG1CQUFtQixDQUNwRCxDQUFDLEVBQUUsNENBQTRDO2dCQUMvQyxDQUFDLEVBQ0QsS0FBSyxDQUFDLE9BQU8sSUFBSSxnQkFBZ0IsQ0FDbEMsQ0FBQztnQkFFRixJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztvQkFDNUIsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBQ3BDLENBQUM7Z0JBRUQsdURBQXVEO2dCQUN2RCxJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7b0JBQzVFLEtBQUssQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDakMsQ0FBQztnQkFDRCxNQUFNO1lBQ1IsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxnQkFBZ0I7UUFDZCxJQUFJLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUM5QyxrREFBa0Q7WUFDbEQsTUFBTSxXQUFXLEdBQUcsa0JBQWtCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNoRSxPQUFPLGFBQWEsV0FBVyxFQUFFLENBQUM7UUFDcEMsQ0FBQztRQUNELE9BQU8sYUFBYSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO0lBQy9ELENBQUM7SUFFRDs7T0FFRztJQUNILElBQUksVUFBVTtRQUNaLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztJQUM5RCxDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLE9BQU87UUFDVCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDeEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBSSxJQUFJO1FBQ04sT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztJQUMzQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxJQUFJLElBQUk7UUFDTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDO0lBQzNCLENBQUM7Q0FDRiJ9
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
/**
|
|
3
|
+
* MongoDB Wire Protocol Implementation
|
|
4
|
+
* Handles parsing and encoding of MongoDB wire protocol messages (OP_MSG primarily)
|
|
5
|
+
*
|
|
6
|
+
* Wire Protocol Message Format:
|
|
7
|
+
* - Header (16 bytes): messageLength (4), requestID (4), responseTo (4), opCode (4)
|
|
8
|
+
* - OP_MSG: flagBits (4), sections[], optional checksum (4)
|
|
9
|
+
*
|
|
10
|
+
* References:
|
|
11
|
+
* - https://www.mongodb.com/docs/manual/reference/mongodb-wire-protocol/
|
|
12
|
+
*/
|
|
13
|
+
export declare const OP_REPLY = 1;
|
|
14
|
+
export declare const OP_UPDATE = 2001;
|
|
15
|
+
export declare const OP_INSERT = 2002;
|
|
16
|
+
export declare const OP_QUERY = 2004;
|
|
17
|
+
export declare const OP_GET_MORE = 2005;
|
|
18
|
+
export declare const OP_DELETE = 2006;
|
|
19
|
+
export declare const OP_KILL_CURSORS = 2007;
|
|
20
|
+
export declare const OP_COMPRESSED = 2012;
|
|
21
|
+
export declare const OP_MSG = 2013;
|
|
22
|
+
export declare const SECTION_BODY = 0;
|
|
23
|
+
export declare const SECTION_DOCUMENT_SEQUENCE = 1;
|
|
24
|
+
export declare const MSG_FLAG_CHECKSUM_PRESENT: number;
|
|
25
|
+
export declare const MSG_FLAG_MORE_TO_COME: number;
|
|
26
|
+
export declare const MSG_FLAG_EXHAUST_ALLOWED: number;
|
|
27
|
+
/**
|
|
28
|
+
* Parsed message header
|
|
29
|
+
*/
|
|
30
|
+
export interface IMessageHeader {
|
|
31
|
+
messageLength: number;
|
|
32
|
+
requestID: number;
|
|
33
|
+
responseTo: number;
|
|
34
|
+
opCode: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Parsed OP_MSG message
|
|
38
|
+
*/
|
|
39
|
+
export interface IOpMsgMessage {
|
|
40
|
+
header: IMessageHeader;
|
|
41
|
+
flagBits: number;
|
|
42
|
+
sections: IOpMsgSection[];
|
|
43
|
+
checksum?: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* OP_MSG section (either body or document sequence)
|
|
47
|
+
*/
|
|
48
|
+
export interface IOpMsgSection {
|
|
49
|
+
type: number;
|
|
50
|
+
payload: plugins.bson.Document;
|
|
51
|
+
sequenceIdentifier?: string;
|
|
52
|
+
documents?: plugins.bson.Document[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Parsed OP_QUERY message (legacy, but used for initial handshake)
|
|
56
|
+
*/
|
|
57
|
+
export interface IOpQueryMessage {
|
|
58
|
+
header: IMessageHeader;
|
|
59
|
+
flags: number;
|
|
60
|
+
fullCollectionName: string;
|
|
61
|
+
numberToSkip: number;
|
|
62
|
+
numberToReturn: number;
|
|
63
|
+
query: plugins.bson.Document;
|
|
64
|
+
returnFieldsSelector?: plugins.bson.Document;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Parsed command from any message type
|
|
68
|
+
*/
|
|
69
|
+
export interface IParsedCommand {
|
|
70
|
+
commandName: string;
|
|
71
|
+
command: plugins.bson.Document;
|
|
72
|
+
database: string;
|
|
73
|
+
requestID: number;
|
|
74
|
+
opCode: number;
|
|
75
|
+
documentSequences?: Map<string, plugins.bson.Document[]>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Wire Protocol parser and encoder
|
|
79
|
+
*/
|
|
80
|
+
export declare class WireProtocol {
|
|
81
|
+
/**
|
|
82
|
+
* Parse a complete message from a buffer
|
|
83
|
+
* Returns the parsed command and the number of bytes consumed
|
|
84
|
+
*/
|
|
85
|
+
static parseMessage(buffer: Buffer): {
|
|
86
|
+
command: IParsedCommand;
|
|
87
|
+
bytesConsumed: number;
|
|
88
|
+
} | null;
|
|
89
|
+
/**
|
|
90
|
+
* Parse message header (16 bytes)
|
|
91
|
+
*/
|
|
92
|
+
private static parseHeader;
|
|
93
|
+
/**
|
|
94
|
+
* Parse OP_MSG message
|
|
95
|
+
*/
|
|
96
|
+
private static parseOpMsg;
|
|
97
|
+
/**
|
|
98
|
+
* Parse OP_QUERY message (legacy, used for initial handshake)
|
|
99
|
+
*/
|
|
100
|
+
private static parseOpQuery;
|
|
101
|
+
/**
|
|
102
|
+
* Encode a response as OP_MSG
|
|
103
|
+
*/
|
|
104
|
+
static encodeOpMsgResponse(responseTo: number, response: plugins.bson.Document, requestID?: number): Buffer;
|
|
105
|
+
/**
|
|
106
|
+
* Encode a response as OP_REPLY (legacy, for OP_QUERY responses)
|
|
107
|
+
*/
|
|
108
|
+
static encodeOpReplyResponse(responseTo: number, documents: plugins.bson.Document[], requestID?: number, cursorId?: bigint): Buffer;
|
|
109
|
+
/**
|
|
110
|
+
* Encode an error response
|
|
111
|
+
*/
|
|
112
|
+
static encodeErrorResponse(responseTo: number, errorCode: number, errorMessage: string, commandName?: string): Buffer;
|
|
113
|
+
/**
|
|
114
|
+
* Get error code name from error code
|
|
115
|
+
*/
|
|
116
|
+
private static getErrorCodeName;
|
|
117
|
+
}
|