@push.rocks/smartmongo 2.0.14 → 2.2.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.
Files changed (87) hide show
  1. package/dist_ts/00_commitinfo_data.js +2 -2
  2. package/dist_ts/congodb/congodb.plugins.d.ts +10 -0
  3. package/dist_ts/congodb/congodb.plugins.js +14 -0
  4. package/dist_ts/congodb/engine/AggregationEngine.d.ts +66 -0
  5. package/dist_ts/congodb/engine/AggregationEngine.js +189 -0
  6. package/dist_ts/congodb/engine/IndexEngine.d.ts +77 -0
  7. package/dist_ts/congodb/engine/IndexEngine.js +376 -0
  8. package/dist_ts/congodb/engine/QueryEngine.d.ts +54 -0
  9. package/dist_ts/congodb/engine/QueryEngine.js +271 -0
  10. package/dist_ts/congodb/engine/TransactionEngine.d.ts +85 -0
  11. package/dist_ts/congodb/engine/TransactionEngine.js +287 -0
  12. package/dist_ts/congodb/engine/UpdateEngine.d.ts +47 -0
  13. package/dist_ts/congodb/engine/UpdateEngine.js +461 -0
  14. package/dist_ts/congodb/errors/CongoErrors.d.ts +100 -0
  15. package/dist_ts/congodb/errors/CongoErrors.js +155 -0
  16. package/dist_ts/congodb/index.d.ts +19 -0
  17. package/dist_ts/congodb/index.js +26 -0
  18. package/dist_ts/congodb/server/CommandRouter.d.ts +51 -0
  19. package/dist_ts/congodb/server/CommandRouter.js +132 -0
  20. package/dist_ts/congodb/server/CongoServer.d.ts +95 -0
  21. package/dist_ts/congodb/server/CongoServer.js +227 -0
  22. package/dist_ts/congodb/server/WireProtocol.d.ts +117 -0
  23. package/dist_ts/congodb/server/WireProtocol.js +298 -0
  24. package/dist_ts/congodb/server/handlers/AdminHandler.d.ts +100 -0
  25. package/dist_ts/congodb/server/handlers/AdminHandler.js +568 -0
  26. package/dist_ts/congodb/server/handlers/AggregateHandler.d.ts +31 -0
  27. package/dist_ts/congodb/server/handlers/AggregateHandler.js +277 -0
  28. package/dist_ts/congodb/server/handlers/DeleteHandler.d.ts +8 -0
  29. package/dist_ts/congodb/server/handlers/DeleteHandler.js +83 -0
  30. package/dist_ts/congodb/server/handlers/FindHandler.d.ts +31 -0
  31. package/dist_ts/congodb/server/handlers/FindHandler.js +261 -0
  32. package/dist_ts/congodb/server/handlers/HelloHandler.d.ts +11 -0
  33. package/dist_ts/congodb/server/handlers/HelloHandler.js +62 -0
  34. package/dist_ts/congodb/server/handlers/IndexHandler.d.ts +20 -0
  35. package/dist_ts/congodb/server/handlers/IndexHandler.js +183 -0
  36. package/dist_ts/congodb/server/handlers/InsertHandler.d.ts +8 -0
  37. package/dist_ts/congodb/server/handlers/InsertHandler.js +76 -0
  38. package/dist_ts/congodb/server/handlers/UpdateHandler.d.ts +24 -0
  39. package/dist_ts/congodb/server/handlers/UpdateHandler.js +270 -0
  40. package/dist_ts/congodb/server/handlers/index.d.ts +8 -0
  41. package/dist_ts/congodb/server/handlers/index.js +10 -0
  42. package/dist_ts/congodb/server/index.d.ts +6 -0
  43. package/dist_ts/congodb/server/index.js +7 -0
  44. package/dist_ts/congodb/storage/FileStorageAdapter.d.ts +61 -0
  45. package/dist_ts/congodb/storage/FileStorageAdapter.js +396 -0
  46. package/dist_ts/congodb/storage/IStorageAdapter.d.ts +140 -0
  47. package/dist_ts/congodb/storage/IStorageAdapter.js +2 -0
  48. package/dist_ts/congodb/storage/MemoryStorageAdapter.d.ts +66 -0
  49. package/dist_ts/congodb/storage/MemoryStorageAdapter.js +367 -0
  50. package/dist_ts/congodb/storage/OpLog.d.ts +93 -0
  51. package/dist_ts/congodb/storage/OpLog.js +221 -0
  52. package/dist_ts/congodb/types/interfaces.d.ts +363 -0
  53. package/dist_ts/congodb/types/interfaces.js +2 -0
  54. package/dist_ts/index.d.ts +1 -0
  55. package/dist_ts/index.js +8 -6
  56. package/npmextra.json +17 -7
  57. package/package.json +20 -12
  58. package/readme.hints.md +79 -0
  59. package/readme.md +398 -44
  60. package/ts/00_commitinfo_data.ts +1 -1
  61. package/ts/congodb/congodb.plugins.ts +17 -0
  62. package/ts/congodb/engine/AggregationEngine.ts +283 -0
  63. package/ts/congodb/engine/IndexEngine.ts +479 -0
  64. package/ts/congodb/engine/QueryEngine.ts +301 -0
  65. package/ts/congodb/engine/TransactionEngine.ts +351 -0
  66. package/ts/congodb/engine/UpdateEngine.ts +506 -0
  67. package/ts/congodb/errors/CongoErrors.ts +181 -0
  68. package/ts/congodb/index.ts +37 -0
  69. package/ts/congodb/server/CommandRouter.ts +180 -0
  70. package/ts/congodb/server/CongoServer.ts +298 -0
  71. package/ts/congodb/server/WireProtocol.ts +416 -0
  72. package/ts/congodb/server/handlers/AdminHandler.ts +614 -0
  73. package/ts/congodb/server/handlers/AggregateHandler.ts +342 -0
  74. package/ts/congodb/server/handlers/DeleteHandler.ts +100 -0
  75. package/ts/congodb/server/handlers/FindHandler.ts +301 -0
  76. package/ts/congodb/server/handlers/HelloHandler.ts +78 -0
  77. package/ts/congodb/server/handlers/IndexHandler.ts +207 -0
  78. package/ts/congodb/server/handlers/InsertHandler.ts +91 -0
  79. package/ts/congodb/server/handlers/UpdateHandler.ts +315 -0
  80. package/ts/congodb/server/handlers/index.ts +10 -0
  81. package/ts/congodb/server/index.ts +10 -0
  82. package/ts/congodb/storage/FileStorageAdapter.ts +479 -0
  83. package/ts/congodb/storage/IStorageAdapter.ts +202 -0
  84. package/ts/congodb/storage/MemoryStorageAdapter.ts +443 -0
  85. package/ts/congodb/storage/OpLog.ts +282 -0
  86. package/ts/congodb/types/interfaces.ts +433 -0
  87. package/ts/index.ts +3 -0
@@ -0,0 +1,100 @@
1
+ import * as plugins from '../../congodb.plugins.js';
2
+ import type { ICommandHandler, IHandlerContext } from '../CommandRouter.js';
3
+ /**
4
+ * AdminHandler - Handles administrative commands
5
+ */
6
+ export declare class AdminHandler implements ICommandHandler {
7
+ handle(context: IHandlerContext): Promise<plugins.bson.Document>;
8
+ /**
9
+ * Handle ping command
10
+ */
11
+ private handlePing;
12
+ /**
13
+ * Handle listDatabases command
14
+ */
15
+ private handleListDatabases;
16
+ /**
17
+ * Handle listCollections command
18
+ */
19
+ private handleListCollections;
20
+ /**
21
+ * Handle drop command (drop collection)
22
+ */
23
+ private handleDrop;
24
+ /**
25
+ * Handle dropDatabase command
26
+ */
27
+ private handleDropDatabase;
28
+ /**
29
+ * Handle create command (create collection)
30
+ */
31
+ private handleCreate;
32
+ /**
33
+ * Handle serverStatus command
34
+ */
35
+ private handleServerStatus;
36
+ /**
37
+ * Handle buildInfo command
38
+ */
39
+ private handleBuildInfo;
40
+ /**
41
+ * Handle whatsmyuri command
42
+ */
43
+ private handleWhatsMyUri;
44
+ /**
45
+ * Handle getLog command
46
+ */
47
+ private handleGetLog;
48
+ /**
49
+ * Handle hostInfo command
50
+ */
51
+ private handleHostInfo;
52
+ /**
53
+ * Handle replSetGetStatus command
54
+ */
55
+ private handleReplSetGetStatus;
56
+ /**
57
+ * Handle saslStart command (authentication)
58
+ */
59
+ private handleSaslStart;
60
+ /**
61
+ * Handle saslContinue command
62
+ */
63
+ private handleSaslContinue;
64
+ /**
65
+ * Handle endSessions command
66
+ */
67
+ private handleEndSessions;
68
+ /**
69
+ * Handle abortTransaction command
70
+ */
71
+ private handleAbortTransaction;
72
+ /**
73
+ * Handle commitTransaction command
74
+ */
75
+ private handleCommitTransaction;
76
+ /**
77
+ * Handle collStats command
78
+ */
79
+ private handleCollStats;
80
+ /**
81
+ * Handle dbStats command
82
+ */
83
+ private handleDbStats;
84
+ /**
85
+ * Handle connectionStatus command
86
+ */
87
+ private handleConnectionStatus;
88
+ /**
89
+ * Handle currentOp command
90
+ */
91
+ private handleCurrentOp;
92
+ /**
93
+ * Handle collMod command
94
+ */
95
+ private handleCollMod;
96
+ /**
97
+ * Handle renameCollection command
98
+ */
99
+ private handleRenameCollection;
100
+ }
@@ -0,0 +1,568 @@
1
+ import * as plugins from '../../congodb.plugins.js';
2
+ /**
3
+ * AdminHandler - Handles administrative commands
4
+ */
5
+ export class AdminHandler {
6
+ async handle(context) {
7
+ const { command } = context;
8
+ // Determine which command to handle
9
+ if (command.ping !== undefined) {
10
+ return this.handlePing(context);
11
+ }
12
+ else if (command.listDatabases !== undefined) {
13
+ return this.handleListDatabases(context);
14
+ }
15
+ else if (command.listCollections !== undefined) {
16
+ return this.handleListCollections(context);
17
+ }
18
+ else if (command.drop !== undefined) {
19
+ return this.handleDrop(context);
20
+ }
21
+ else if (command.dropDatabase !== undefined) {
22
+ return this.handleDropDatabase(context);
23
+ }
24
+ else if (command.create !== undefined) {
25
+ return this.handleCreate(context);
26
+ }
27
+ else if (command.serverStatus !== undefined) {
28
+ return this.handleServerStatus(context);
29
+ }
30
+ else if (command.buildInfo !== undefined) {
31
+ return this.handleBuildInfo(context);
32
+ }
33
+ else if (command.whatsmyuri !== undefined) {
34
+ return this.handleWhatsMyUri(context);
35
+ }
36
+ else if (command.getLog !== undefined) {
37
+ return this.handleGetLog(context);
38
+ }
39
+ else if (command.hostInfo !== undefined) {
40
+ return this.handleHostInfo(context);
41
+ }
42
+ else if (command.replSetGetStatus !== undefined) {
43
+ return this.handleReplSetGetStatus(context);
44
+ }
45
+ else if (command.saslStart !== undefined) {
46
+ return this.handleSaslStart(context);
47
+ }
48
+ else if (command.saslContinue !== undefined) {
49
+ return this.handleSaslContinue(context);
50
+ }
51
+ else if (command.endSessions !== undefined) {
52
+ return this.handleEndSessions(context);
53
+ }
54
+ else if (command.abortTransaction !== undefined) {
55
+ return this.handleAbortTransaction(context);
56
+ }
57
+ else if (command.commitTransaction !== undefined) {
58
+ return this.handleCommitTransaction(context);
59
+ }
60
+ else if (command.collStats !== undefined) {
61
+ return this.handleCollStats(context);
62
+ }
63
+ else if (command.dbStats !== undefined) {
64
+ return this.handleDbStats(context);
65
+ }
66
+ else if (command.connectionStatus !== undefined) {
67
+ return this.handleConnectionStatus(context);
68
+ }
69
+ else if (command.currentOp !== undefined) {
70
+ return this.handleCurrentOp(context);
71
+ }
72
+ else if (command.collMod !== undefined) {
73
+ return this.handleCollMod(context);
74
+ }
75
+ else if (command.renameCollection !== undefined) {
76
+ return this.handleRenameCollection(context);
77
+ }
78
+ return {
79
+ ok: 0,
80
+ errmsg: 'Unknown admin command',
81
+ code: 59,
82
+ codeName: 'CommandNotFound',
83
+ };
84
+ }
85
+ /**
86
+ * Handle ping command
87
+ */
88
+ async handlePing(context) {
89
+ return { ok: 1 };
90
+ }
91
+ /**
92
+ * Handle listDatabases command
93
+ */
94
+ async handleListDatabases(context) {
95
+ const { storage, command } = context;
96
+ const dbNames = await storage.listDatabases();
97
+ const nameOnly = command.nameOnly || false;
98
+ if (nameOnly) {
99
+ return {
100
+ ok: 1,
101
+ databases: dbNames.map(name => ({ name })),
102
+ };
103
+ }
104
+ // Build database list with sizes
105
+ const databases = [];
106
+ let totalSize = 0;
107
+ for (const name of dbNames) {
108
+ const collections = await storage.listCollections(name);
109
+ let dbSize = 0;
110
+ for (const collName of collections) {
111
+ const docs = await storage.findAll(name, collName);
112
+ // Estimate size (rough approximation)
113
+ dbSize += docs.reduce((sum, doc) => sum + JSON.stringify(doc).length, 0);
114
+ }
115
+ totalSize += dbSize;
116
+ databases.push({
117
+ name,
118
+ sizeOnDisk: dbSize,
119
+ empty: dbSize === 0,
120
+ });
121
+ }
122
+ return {
123
+ ok: 1,
124
+ databases,
125
+ totalSize,
126
+ totalSizeMb: totalSize / (1024 * 1024),
127
+ };
128
+ }
129
+ /**
130
+ * Handle listCollections command
131
+ */
132
+ async handleListCollections(context) {
133
+ const { storage, database, command } = context;
134
+ const filter = command.filter || {};
135
+ const nameOnly = command.nameOnly || false;
136
+ const cursor = command.cursor || {};
137
+ const batchSize = cursor.batchSize || 101;
138
+ const collNames = await storage.listCollections(database);
139
+ let collections = [];
140
+ for (const name of collNames) {
141
+ // Apply name filter
142
+ if (filter.name && filter.name !== name) {
143
+ // Check regex
144
+ if (filter.name.$regex) {
145
+ const regex = new RegExp(filter.name.$regex, filter.name.$options);
146
+ if (!regex.test(name))
147
+ continue;
148
+ }
149
+ else {
150
+ continue;
151
+ }
152
+ }
153
+ if (nameOnly) {
154
+ collections.push({ name });
155
+ }
156
+ else {
157
+ collections.push({
158
+ name,
159
+ type: 'collection',
160
+ options: {},
161
+ info: {
162
+ readOnly: false,
163
+ uuid: new plugins.bson.UUID(),
164
+ },
165
+ idIndex: {
166
+ v: 2,
167
+ key: { _id: 1 },
168
+ name: '_id_',
169
+ },
170
+ });
171
+ }
172
+ }
173
+ return {
174
+ ok: 1,
175
+ cursor: {
176
+ id: plugins.bson.Long.fromNumber(0),
177
+ ns: `${database}.$cmd.listCollections`,
178
+ firstBatch: collections,
179
+ },
180
+ };
181
+ }
182
+ /**
183
+ * Handle drop command (drop collection)
184
+ */
185
+ async handleDrop(context) {
186
+ const { storage, database, command } = context;
187
+ const collection = command.drop;
188
+ const existed = await storage.dropCollection(database, collection);
189
+ if (!existed) {
190
+ return {
191
+ ok: 0,
192
+ errmsg: `ns not found ${database}.${collection}`,
193
+ code: 26,
194
+ codeName: 'NamespaceNotFound',
195
+ };
196
+ }
197
+ return { ok: 1, ns: `${database}.${collection}` };
198
+ }
199
+ /**
200
+ * Handle dropDatabase command
201
+ */
202
+ async handleDropDatabase(context) {
203
+ const { storage, database } = context;
204
+ await storage.dropDatabase(database);
205
+ return { ok: 1, dropped: database };
206
+ }
207
+ /**
208
+ * Handle create command (create collection)
209
+ */
210
+ async handleCreate(context) {
211
+ const { storage, database, command } = context;
212
+ const collection = command.create;
213
+ // Check if already exists
214
+ const exists = await storage.collectionExists(database, collection);
215
+ if (exists) {
216
+ return {
217
+ ok: 0,
218
+ errmsg: `Collection ${database}.${collection} already exists.`,
219
+ code: 48,
220
+ codeName: 'NamespaceExists',
221
+ };
222
+ }
223
+ await storage.createCollection(database, collection);
224
+ return { ok: 1 };
225
+ }
226
+ /**
227
+ * Handle serverStatus command
228
+ */
229
+ async handleServerStatus(context) {
230
+ const { server } = context;
231
+ const uptime = server.getUptime();
232
+ const connections = server.getConnectionCount();
233
+ return {
234
+ ok: 1,
235
+ host: `${server.host}:${server.port}`,
236
+ version: '7.0.0',
237
+ process: 'congodb',
238
+ pid: process.pid,
239
+ uptime,
240
+ uptimeMillis: uptime * 1000,
241
+ uptimeEstimate: uptime,
242
+ localTime: new Date(),
243
+ mem: {
244
+ resident: Math.floor(process.memoryUsage().rss / (1024 * 1024)),
245
+ virtual: Math.floor(process.memoryUsage().heapTotal / (1024 * 1024)),
246
+ supported: true,
247
+ },
248
+ connections: {
249
+ current: connections,
250
+ available: 1000 - connections,
251
+ totalCreated: connections,
252
+ active: connections,
253
+ },
254
+ network: {
255
+ bytesIn: 0,
256
+ bytesOut: 0,
257
+ numRequests: 0,
258
+ },
259
+ storageEngine: {
260
+ name: 'congodb',
261
+ supportsCommittedReads: true,
262
+ persistent: false,
263
+ },
264
+ };
265
+ }
266
+ /**
267
+ * Handle buildInfo command
268
+ */
269
+ async handleBuildInfo(context) {
270
+ return {
271
+ ok: 1,
272
+ version: '7.0.0',
273
+ gitVersion: 'congodb',
274
+ modules: [],
275
+ allocator: 'system',
276
+ javascriptEngine: 'none',
277
+ sysInfo: 'deprecated',
278
+ versionArray: [7, 0, 0, 0],
279
+ openssl: {
280
+ running: 'disabled',
281
+ compiled: 'disabled',
282
+ },
283
+ buildEnvironment: {
284
+ distmod: 'congodb',
285
+ distarch: process.arch,
286
+ cc: '',
287
+ ccflags: '',
288
+ cxx: '',
289
+ cxxflags: '',
290
+ linkflags: '',
291
+ target_arch: process.arch,
292
+ target_os: process.platform,
293
+ },
294
+ bits: 64,
295
+ debug: false,
296
+ maxBsonObjectSize: 16777216,
297
+ storageEngines: ['congodb'],
298
+ };
299
+ }
300
+ /**
301
+ * Handle whatsmyuri command
302
+ */
303
+ async handleWhatsMyUri(context) {
304
+ const { server } = context;
305
+ return {
306
+ ok: 1,
307
+ you: `127.0.0.1:${server.port}`,
308
+ };
309
+ }
310
+ /**
311
+ * Handle getLog command
312
+ */
313
+ async handleGetLog(context) {
314
+ const { command } = context;
315
+ if (command.getLog === '*') {
316
+ return {
317
+ ok: 1,
318
+ names: ['global', 'startupWarnings'],
319
+ };
320
+ }
321
+ return {
322
+ ok: 1,
323
+ totalLinesWritten: 0,
324
+ log: [],
325
+ };
326
+ }
327
+ /**
328
+ * Handle hostInfo command
329
+ */
330
+ async handleHostInfo(context) {
331
+ return {
332
+ ok: 1,
333
+ system: {
334
+ currentTime: new Date(),
335
+ hostname: 'localhost',
336
+ cpuAddrSize: 64,
337
+ memSizeMB: Math.floor(process.memoryUsage().heapTotal / (1024 * 1024)),
338
+ numCores: 1,
339
+ cpuArch: process.arch,
340
+ numaEnabled: false,
341
+ },
342
+ os: {
343
+ type: process.platform,
344
+ name: process.platform,
345
+ version: process.version,
346
+ },
347
+ extra: {},
348
+ };
349
+ }
350
+ /**
351
+ * Handle replSetGetStatus command
352
+ */
353
+ async handleReplSetGetStatus(context) {
354
+ // We're standalone, not a replica set
355
+ return {
356
+ ok: 0,
357
+ errmsg: 'not running with --replSet',
358
+ code: 76,
359
+ codeName: 'NoReplicationEnabled',
360
+ };
361
+ }
362
+ /**
363
+ * Handle saslStart command (authentication)
364
+ */
365
+ async handleSaslStart(context) {
366
+ // We don't require authentication, but we need to respond properly
367
+ // to let drivers know auth is "successful"
368
+ return {
369
+ ok: 1,
370
+ conversationId: 1,
371
+ done: true,
372
+ payload: Buffer.from([]),
373
+ };
374
+ }
375
+ /**
376
+ * Handle saslContinue command
377
+ */
378
+ async handleSaslContinue(context) {
379
+ return {
380
+ ok: 1,
381
+ conversationId: 1,
382
+ done: true,
383
+ payload: Buffer.from([]),
384
+ };
385
+ }
386
+ /**
387
+ * Handle endSessions command
388
+ */
389
+ async handleEndSessions(context) {
390
+ return { ok: 1 };
391
+ }
392
+ /**
393
+ * Handle abortTransaction command
394
+ */
395
+ async handleAbortTransaction(context) {
396
+ // Transactions are not fully supported, but acknowledge the command
397
+ return { ok: 1 };
398
+ }
399
+ /**
400
+ * Handle commitTransaction command
401
+ */
402
+ async handleCommitTransaction(context) {
403
+ // Transactions are not fully supported, but acknowledge the command
404
+ return { ok: 1 };
405
+ }
406
+ /**
407
+ * Handle collStats command
408
+ */
409
+ async handleCollStats(context) {
410
+ const { storage, database, command } = context;
411
+ const collection = command.collStats;
412
+ const exists = await storage.collectionExists(database, collection);
413
+ if (!exists) {
414
+ return {
415
+ ok: 0,
416
+ errmsg: `ns not found ${database}.${collection}`,
417
+ code: 26,
418
+ codeName: 'NamespaceNotFound',
419
+ };
420
+ }
421
+ const docs = await storage.findAll(database, collection);
422
+ const size = docs.reduce((sum, doc) => sum + JSON.stringify(doc).length, 0);
423
+ const count = docs.length;
424
+ const avgObjSize = count > 0 ? size / count : 0;
425
+ const indexes = await storage.getIndexes(database, collection);
426
+ return {
427
+ ok: 1,
428
+ ns: `${database}.${collection}`,
429
+ count,
430
+ size,
431
+ avgObjSize,
432
+ storageSize: size,
433
+ totalIndexSize: 0,
434
+ indexSizes: indexes.reduce((acc, idx) => {
435
+ acc[idx.name] = 0;
436
+ return acc;
437
+ }, {}),
438
+ nindexes: indexes.length,
439
+ };
440
+ }
441
+ /**
442
+ * Handle dbStats command
443
+ */
444
+ async handleDbStats(context) {
445
+ const { storage, database } = context;
446
+ const collections = await storage.listCollections(database);
447
+ let totalSize = 0;
448
+ let totalObjects = 0;
449
+ for (const collName of collections) {
450
+ const docs = await storage.findAll(database, collName);
451
+ totalObjects += docs.length;
452
+ totalSize += docs.reduce((sum, doc) => sum + JSON.stringify(doc).length, 0);
453
+ }
454
+ return {
455
+ ok: 1,
456
+ db: database,
457
+ collections: collections.length,
458
+ views: 0,
459
+ objects: totalObjects,
460
+ avgObjSize: totalObjects > 0 ? totalSize / totalObjects : 0,
461
+ dataSize: totalSize,
462
+ storageSize: totalSize,
463
+ indexes: collections.length, // At least _id index per collection
464
+ indexSize: 0,
465
+ totalSize,
466
+ };
467
+ }
468
+ /**
469
+ * Handle connectionStatus command
470
+ */
471
+ async handleConnectionStatus(context) {
472
+ return {
473
+ ok: 1,
474
+ authInfo: {
475
+ authenticatedUsers: [],
476
+ authenticatedUserRoles: [],
477
+ },
478
+ };
479
+ }
480
+ /**
481
+ * Handle currentOp command
482
+ */
483
+ async handleCurrentOp(context) {
484
+ return {
485
+ ok: 1,
486
+ inprog: [],
487
+ };
488
+ }
489
+ /**
490
+ * Handle collMod command
491
+ */
492
+ async handleCollMod(context) {
493
+ // We don't support modifying collection options, but acknowledge the command
494
+ return { ok: 1 };
495
+ }
496
+ /**
497
+ * Handle renameCollection command
498
+ */
499
+ async handleRenameCollection(context) {
500
+ const { storage, command } = context;
501
+ const from = command.renameCollection;
502
+ const to = command.to;
503
+ const dropTarget = command.dropTarget || false;
504
+ if (!from || !to) {
505
+ return {
506
+ ok: 0,
507
+ errmsg: 'renameCollection requires both source and target',
508
+ code: 2,
509
+ codeName: 'BadValue',
510
+ };
511
+ }
512
+ // Parse namespace (format: "db.collection")
513
+ const fromParts = from.split('.');
514
+ const toParts = to.split('.');
515
+ if (fromParts.length < 2 || toParts.length < 2) {
516
+ return {
517
+ ok: 0,
518
+ errmsg: 'Invalid namespace format',
519
+ code: 73,
520
+ codeName: 'InvalidNamespace',
521
+ };
522
+ }
523
+ const fromDb = fromParts[0];
524
+ const fromColl = fromParts.slice(1).join('.');
525
+ const toDb = toParts[0];
526
+ const toColl = toParts.slice(1).join('.');
527
+ // Check if source exists
528
+ const sourceExists = await storage.collectionExists(fromDb, fromColl);
529
+ if (!sourceExists) {
530
+ return {
531
+ ok: 0,
532
+ errmsg: `source namespace ${from} does not exist`,
533
+ code: 26,
534
+ codeName: 'NamespaceNotFound',
535
+ };
536
+ }
537
+ // Check if target exists
538
+ const targetExists = await storage.collectionExists(toDb, toColl);
539
+ if (targetExists) {
540
+ if (dropTarget) {
541
+ await storage.dropCollection(toDb, toColl);
542
+ }
543
+ else {
544
+ return {
545
+ ok: 0,
546
+ errmsg: `target namespace ${to} already exists`,
547
+ code: 48,
548
+ codeName: 'NamespaceExists',
549
+ };
550
+ }
551
+ }
552
+ // Same database rename
553
+ if (fromDb === toDb) {
554
+ await storage.renameCollection(fromDb, fromColl, toColl);
555
+ }
556
+ else {
557
+ // Cross-database rename: copy documents then drop source
558
+ await storage.createCollection(toDb, toColl);
559
+ const docs = await storage.findAll(fromDb, fromColl);
560
+ for (const doc of docs) {
561
+ await storage.insertOne(toDb, toColl, doc);
562
+ }
563
+ await storage.dropCollection(fromDb, fromColl);
564
+ }
565
+ return { ok: 1 };
566
+ }
567
+ }
568
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQWRtaW5IYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdHMvY29uZ29kYi9zZXJ2ZXIvaGFuZGxlcnMvQWRtaW5IYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sMEJBQTBCLENBQUM7QUFHcEQ7O0dBRUc7QUFDSCxNQUFNLE9BQU8sWUFBWTtJQUN2QixLQUFLLENBQUMsTUFBTSxDQUFDLE9BQXdCO1FBQ25DLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFFNUIsb0NBQW9DO1FBQ3BDLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMvQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDbEMsQ0FBQzthQUFNLElBQUksT0FBTyxDQUFDLGFBQWEsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUMvQyxPQUFPLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMzQyxDQUFDO2FBQU0sSUFBSSxPQUFPLENBQUMsZUFBZSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ2pELE9BQU8sSUFBSSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzdDLENBQUM7YUFBTSxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDdEMsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2xDLENBQUM7YUFBTSxJQUFJLE9BQU8sQ0FBQyxZQUFZLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDOUMsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDMUMsQ0FBQzthQUFNLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN4QyxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxD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