@push.rocks/smartdb 1.0.1 → 2.1.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.
Files changed (126) hide show
  1. package/.smartconfig.json +18 -4
  2. package/dist_rust/rustdb_linux_amd64 +0 -0
  3. package/dist_rust/rustdb_linux_arm64 +0 -0
  4. package/dist_ts/00_commitinfo_data.js +3 -3
  5. package/dist_ts/index.d.ts +1 -0
  6. package/dist_ts/ts_local/classes.localsmartdb.d.ts +5 -5
  7. package/dist_ts/ts_local/classes.localsmartdb.js +7 -9
  8. package/dist_ts/ts_local/plugins.d.ts +1 -2
  9. package/dist_ts/ts_local/plugins.js +3 -3
  10. package/dist_ts/ts_smartdb/index.d.ts +2 -24
  11. package/dist_ts/ts_smartdb/index.js +4 -29
  12. package/dist_ts/ts_smartdb/plugins.d.ts +2 -10
  13. package/dist_ts/ts_smartdb/plugins.js +3 -13
  14. package/dist_ts/ts_smartdb/rust-db-bridge.d.ts +122 -0
  15. package/dist_ts/ts_smartdb/rust-db-bridge.js +113 -0
  16. package/dist_ts/ts_smartdb/server/SmartdbServer.d.ts +39 -37
  17. package/dist_ts/ts_smartdb/server/SmartdbServer.js +87 -206
  18. package/dist_ts/ts_smartdb/server/index.d.ts +0 -4
  19. package/dist_ts/ts_smartdb/server/index.js +1 -5
  20. package/dist_ts_debugserver/bundled.d.ts +4 -0
  21. package/dist_ts_debugserver/bundled.js +12 -0
  22. package/dist_ts_debugserver/classes.debugserver.d.ts +36 -0
  23. package/dist_ts_debugserver/classes.debugserver.js +95 -0
  24. package/dist_ts_debugserver/index.d.ts +2 -0
  25. package/dist_ts_debugserver/index.js +2 -0
  26. package/dist_ts_debugserver/plugins.d.ts +2 -0
  27. package/dist_ts_debugserver/plugins.js +3 -0
  28. package/dist_ts_debugui/index.d.ts +2 -0
  29. package/dist_ts_debugui/index.js +2 -0
  30. package/dist_ts_debugui/plugins.d.ts +1 -0
  31. package/dist_ts_debugui/plugins.js +2 -0
  32. package/dist_ts_debugui/smartdb-debugui.d.ts +62 -0
  33. package/dist_ts_debugui/smartdb-debugui.js +1132 -0
  34. package/license +3 -1
  35. package/package.json +14 -13
  36. package/readme.md +209 -177
  37. package/ts/00_commitinfo_data.ts +2 -2
  38. package/ts/index.ts +11 -0
  39. package/ts/ts_local/classes.localsmartdb.ts +5 -6
  40. package/ts/ts_local/plugins.ts +1 -3
  41. package/ts/ts_smartdb/index.ts +14 -41
  42. package/ts/ts_smartdb/plugins.ts +2 -15
  43. package/ts/ts_smartdb/rust-db-bridge.ts +262 -0
  44. package/ts/ts_smartdb/server/SmartdbServer.ts +115 -246
  45. package/ts/ts_smartdb/server/index.ts +0 -7
  46. package/dist_ts/ts_smartdb/engine/AggregationEngine.d.ts +0 -66
  47. package/dist_ts/ts_smartdb/engine/AggregationEngine.js +0 -189
  48. package/dist_ts/ts_smartdb/engine/IndexEngine.d.ts +0 -97
  49. package/dist_ts/ts_smartdb/engine/IndexEngine.js +0 -678
  50. package/dist_ts/ts_smartdb/engine/QueryEngine.d.ts +0 -54
  51. package/dist_ts/ts_smartdb/engine/QueryEngine.js +0 -271
  52. package/dist_ts/ts_smartdb/engine/QueryPlanner.d.ts +0 -64
  53. package/dist_ts/ts_smartdb/engine/QueryPlanner.js +0 -308
  54. package/dist_ts/ts_smartdb/engine/SessionEngine.d.ts +0 -117
  55. package/dist_ts/ts_smartdb/engine/SessionEngine.js +0 -232
  56. package/dist_ts/ts_smartdb/engine/TransactionEngine.d.ts +0 -85
  57. package/dist_ts/ts_smartdb/engine/TransactionEngine.js +0 -287
  58. package/dist_ts/ts_smartdb/engine/UpdateEngine.d.ts +0 -47
  59. package/dist_ts/ts_smartdb/engine/UpdateEngine.js +0 -461
  60. package/dist_ts/ts_smartdb/errors/SmartdbErrors.d.ts +0 -100
  61. package/dist_ts/ts_smartdb/errors/SmartdbErrors.js +0 -155
  62. package/dist_ts/ts_smartdb/server/CommandRouter.d.ts +0 -87
  63. package/dist_ts/ts_smartdb/server/CommandRouter.js +0 -222
  64. package/dist_ts/ts_smartdb/server/WireProtocol.d.ts +0 -117
  65. package/dist_ts/ts_smartdb/server/WireProtocol.js +0 -298
  66. package/dist_ts/ts_smartdb/server/handlers/AdminHandler.d.ts +0 -100
  67. package/dist_ts/ts_smartdb/server/handlers/AdminHandler.js +0 -668
  68. package/dist_ts/ts_smartdb/server/handlers/AggregateHandler.d.ts +0 -31
  69. package/dist_ts/ts_smartdb/server/handlers/AggregateHandler.js +0 -277
  70. package/dist_ts/ts_smartdb/server/handlers/DeleteHandler.d.ts +0 -8
  71. package/dist_ts/ts_smartdb/server/handlers/DeleteHandler.js +0 -95
  72. package/dist_ts/ts_smartdb/server/handlers/FindHandler.d.ts +0 -31
  73. package/dist_ts/ts_smartdb/server/handlers/FindHandler.js +0 -291
  74. package/dist_ts/ts_smartdb/server/handlers/HelloHandler.d.ts +0 -11
  75. package/dist_ts/ts_smartdb/server/handlers/HelloHandler.js +0 -62
  76. package/dist_ts/ts_smartdb/server/handlers/IndexHandler.d.ts +0 -20
  77. package/dist_ts/ts_smartdb/server/handlers/IndexHandler.js +0 -183
  78. package/dist_ts/ts_smartdb/server/handlers/InsertHandler.d.ts +0 -8
  79. package/dist_ts/ts_smartdb/server/handlers/InsertHandler.js +0 -79
  80. package/dist_ts/ts_smartdb/server/handlers/UpdateHandler.d.ts +0 -24
  81. package/dist_ts/ts_smartdb/server/handlers/UpdateHandler.js +0 -296
  82. package/dist_ts/ts_smartdb/server/handlers/index.d.ts +0 -8
  83. package/dist_ts/ts_smartdb/server/handlers/index.js +0 -10
  84. package/dist_ts/ts_smartdb/storage/FileStorageAdapter.d.ts +0 -85
  85. package/dist_ts/ts_smartdb/storage/FileStorageAdapter.js +0 -465
  86. package/dist_ts/ts_smartdb/storage/IStorageAdapter.d.ts +0 -145
  87. package/dist_ts/ts_smartdb/storage/IStorageAdapter.js +0 -2
  88. package/dist_ts/ts_smartdb/storage/MemoryStorageAdapter.d.ts +0 -67
  89. package/dist_ts/ts_smartdb/storage/MemoryStorageAdapter.js +0 -378
  90. package/dist_ts/ts_smartdb/storage/OpLog.d.ts +0 -93
  91. package/dist_ts/ts_smartdb/storage/OpLog.js +0 -221
  92. package/dist_ts/ts_smartdb/storage/WAL.d.ts +0 -117
  93. package/dist_ts/ts_smartdb/storage/WAL.js +0 -286
  94. package/dist_ts/ts_smartdb/types/interfaces.d.ts +0 -363
  95. package/dist_ts/ts_smartdb/types/interfaces.js +0 -2
  96. package/dist_ts/ts_smartdb/utils/checksum.d.ts +0 -30
  97. package/dist_ts/ts_smartdb/utils/checksum.js +0 -77
  98. package/dist_ts/ts_smartdb/utils/index.d.ts +0 -1
  99. package/dist_ts/ts_smartdb/utils/index.js +0 -2
  100. package/ts/ts_smartdb/engine/AggregationEngine.ts +0 -283
  101. package/ts/ts_smartdb/engine/IndexEngine.ts +0 -798
  102. package/ts/ts_smartdb/engine/QueryEngine.ts +0 -301
  103. package/ts/ts_smartdb/engine/QueryPlanner.ts +0 -393
  104. package/ts/ts_smartdb/engine/SessionEngine.ts +0 -292
  105. package/ts/ts_smartdb/engine/TransactionEngine.ts +0 -351
  106. package/ts/ts_smartdb/engine/UpdateEngine.ts +0 -506
  107. package/ts/ts_smartdb/errors/SmartdbErrors.ts +0 -181
  108. package/ts/ts_smartdb/server/CommandRouter.ts +0 -289
  109. package/ts/ts_smartdb/server/WireProtocol.ts +0 -416
  110. package/ts/ts_smartdb/server/handlers/AdminHandler.ts +0 -719
  111. package/ts/ts_smartdb/server/handlers/AggregateHandler.ts +0 -342
  112. package/ts/ts_smartdb/server/handlers/DeleteHandler.ts +0 -115
  113. package/ts/ts_smartdb/server/handlers/FindHandler.ts +0 -330
  114. package/ts/ts_smartdb/server/handlers/HelloHandler.ts +0 -78
  115. package/ts/ts_smartdb/server/handlers/IndexHandler.ts +0 -207
  116. package/ts/ts_smartdb/server/handlers/InsertHandler.ts +0 -97
  117. package/ts/ts_smartdb/server/handlers/UpdateHandler.ts +0 -344
  118. package/ts/ts_smartdb/server/handlers/index.ts +0 -10
  119. package/ts/ts_smartdb/storage/FileStorageAdapter.ts +0 -562
  120. package/ts/ts_smartdb/storage/IStorageAdapter.ts +0 -208
  121. package/ts/ts_smartdb/storage/MemoryStorageAdapter.ts +0 -455
  122. package/ts/ts_smartdb/storage/OpLog.ts +0 -282
  123. package/ts/ts_smartdb/storage/WAL.ts +0 -375
  124. package/ts/ts_smartdb/types/interfaces.ts +0 -433
  125. package/ts/ts_smartdb/utils/checksum.ts +0 -88
  126. package/ts/ts_smartdb/utils/index.ts +0 -1
@@ -1,719 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import type { ICommandHandler, IHandlerContext } from '../CommandRouter.js';
3
- import { SessionEngine } from '../../engine/SessionEngine.js';
4
-
5
- /**
6
- * AdminHandler - Handles administrative commands
7
- */
8
- export class AdminHandler implements ICommandHandler {
9
- async handle(context: IHandlerContext): Promise<plugins.bson.Document> {
10
- const { command } = context;
11
-
12
- // Determine which command to handle
13
- if (command.ping !== undefined) {
14
- return this.handlePing(context);
15
- } else if (command.listDatabases !== undefined) {
16
- return this.handleListDatabases(context);
17
- } else if (command.listCollections !== undefined) {
18
- return this.handleListCollections(context);
19
- } else if (command.drop !== undefined) {
20
- return this.handleDrop(context);
21
- } else if (command.dropDatabase !== undefined) {
22
- return this.handleDropDatabase(context);
23
- } else if (command.create !== undefined) {
24
- return this.handleCreate(context);
25
- } else if (command.serverStatus !== undefined) {
26
- return this.handleServerStatus(context);
27
- } else if (command.buildInfo !== undefined) {
28
- return this.handleBuildInfo(context);
29
- } else if (command.whatsmyuri !== undefined) {
30
- return this.handleWhatsMyUri(context);
31
- } else if (command.getLog !== undefined) {
32
- return this.handleGetLog(context);
33
- } else if (command.hostInfo !== undefined) {
34
- return this.handleHostInfo(context);
35
- } else if (command.replSetGetStatus !== undefined) {
36
- return this.handleReplSetGetStatus(context);
37
- } else if (command.saslStart !== undefined) {
38
- return this.handleSaslStart(context);
39
- } else if (command.saslContinue !== undefined) {
40
- return this.handleSaslContinue(context);
41
- } else if (command.endSessions !== undefined) {
42
- return this.handleEndSessions(context);
43
- } else if (command.abortTransaction !== undefined) {
44
- return this.handleAbortTransaction(context);
45
- } else if (command.commitTransaction !== undefined) {
46
- return this.handleCommitTransaction(context);
47
- } else if (command.collStats !== undefined) {
48
- return this.handleCollStats(context);
49
- } else if (command.dbStats !== undefined) {
50
- return this.handleDbStats(context);
51
- } else if (command.connectionStatus !== undefined) {
52
- return this.handleConnectionStatus(context);
53
- } else if (command.currentOp !== undefined) {
54
- return this.handleCurrentOp(context);
55
- } else if (command.collMod !== undefined) {
56
- return this.handleCollMod(context);
57
- } else if (command.renameCollection !== undefined) {
58
- return this.handleRenameCollection(context);
59
- }
60
-
61
- return {
62
- ok: 0,
63
- errmsg: 'Unknown admin command',
64
- code: 59,
65
- codeName: 'CommandNotFound',
66
- };
67
- }
68
-
69
- /**
70
- * Handle ping command
71
- */
72
- private async handlePing(context: IHandlerContext): Promise<plugins.bson.Document> {
73
- return { ok: 1 };
74
- }
75
-
76
- /**
77
- * Handle listDatabases command
78
- */
79
- private async handleListDatabases(context: IHandlerContext): Promise<plugins.bson.Document> {
80
- const { storage, command } = context;
81
-
82
- const dbNames = await storage.listDatabases();
83
- const nameOnly = command.nameOnly || false;
84
-
85
- if (nameOnly) {
86
- return {
87
- ok: 1,
88
- databases: dbNames.map(name => ({ name })),
89
- };
90
- }
91
-
92
- // Build database list with sizes
93
- const databases: plugins.bson.Document[] = [];
94
- let totalSize = 0;
95
-
96
- for (const name of dbNames) {
97
- const collections = await storage.listCollections(name);
98
- let dbSize = 0;
99
-
100
- for (const collName of collections) {
101
- const docs = await storage.findAll(name, collName);
102
- // Estimate size (rough approximation)
103
- dbSize += docs.reduce((sum, doc) => sum + JSON.stringify(doc).length, 0);
104
- }
105
-
106
- totalSize += dbSize;
107
-
108
- databases.push({
109
- name,
110
- sizeOnDisk: dbSize,
111
- empty: dbSize === 0,
112
- });
113
- }
114
-
115
- return {
116
- ok: 1,
117
- databases,
118
- totalSize,
119
- totalSizeMb: totalSize / (1024 * 1024),
120
- };
121
- }
122
-
123
- /**
124
- * Handle listCollections command
125
- */
126
- private async handleListCollections(context: IHandlerContext): Promise<plugins.bson.Document> {
127
- const { storage, database, command } = context;
128
-
129
- const filter = command.filter || {};
130
- const nameOnly = command.nameOnly || false;
131
- const cursor = command.cursor || {};
132
- const batchSize = cursor.batchSize || 101;
133
-
134
- const collNames = await storage.listCollections(database);
135
-
136
- let collections: plugins.bson.Document[] = [];
137
-
138
- for (const name of collNames) {
139
- // Apply name filter
140
- if (filter.name && filter.name !== name) {
141
- // Check regex
142
- if (filter.name.$regex) {
143
- const regex = new RegExp(filter.name.$regex, filter.name.$options);
144
- if (!regex.test(name)) continue;
145
- } else {
146
- continue;
147
- }
148
- }
149
-
150
- if (nameOnly) {
151
- collections.push({ name });
152
- } else {
153
- collections.push({
154
- name,
155
- type: 'collection',
156
- options: {},
157
- info: {
158
- readOnly: false,
159
- uuid: new plugins.bson.UUID(),
160
- },
161
- idIndex: {
162
- v: 2,
163
- key: { _id: 1 },
164
- name: '_id_',
165
- },
166
- });
167
- }
168
- }
169
-
170
- return {
171
- ok: 1,
172
- cursor: {
173
- id: plugins.bson.Long.fromNumber(0),
174
- ns: `${database}.$cmd.listCollections`,
175
- firstBatch: collections,
176
- },
177
- };
178
- }
179
-
180
- /**
181
- * Handle drop command (drop collection)
182
- */
183
- private async handleDrop(context: IHandlerContext): Promise<plugins.bson.Document> {
184
- const { storage, database, command } = context;
185
-
186
- const collection = command.drop;
187
-
188
- const existed = await storage.dropCollection(database, collection);
189
-
190
- if (!existed) {
191
- return {
192
- ok: 0,
193
- errmsg: `ns not found ${database}.${collection}`,
194
- code: 26,
195
- codeName: 'NamespaceNotFound',
196
- };
197
- }
198
-
199
- return { ok: 1, ns: `${database}.${collection}` };
200
- }
201
-
202
- /**
203
- * Handle dropDatabase command
204
- */
205
- private async handleDropDatabase(context: IHandlerContext): Promise<plugins.bson.Document> {
206
- const { storage, database } = context;
207
-
208
- await storage.dropDatabase(database);
209
-
210
- return { ok: 1, dropped: database };
211
- }
212
-
213
- /**
214
- * Handle create command (create collection)
215
- */
216
- private async handleCreate(context: IHandlerContext): Promise<plugins.bson.Document> {
217
- const { storage, database, command } = context;
218
-
219
- const collection = command.create;
220
-
221
- // Check if already exists
222
- const exists = await storage.collectionExists(database, collection);
223
- if (exists) {
224
- return {
225
- ok: 0,
226
- errmsg: `Collection ${database}.${collection} already exists.`,
227
- code: 48,
228
- codeName: 'NamespaceExists',
229
- };
230
- }
231
-
232
- await storage.createCollection(database, collection);
233
-
234
- return { ok: 1 };
235
- }
236
-
237
- /**
238
- * Handle serverStatus command
239
- */
240
- private async handleServerStatus(context: IHandlerContext): Promise<plugins.bson.Document> {
241
- const { server, sessionEngine } = context;
242
-
243
- const uptime = server.getUptime();
244
- const connections = server.getConnectionCount();
245
- const sessions = sessionEngine.listSessions();
246
- const sessionsWithTxn = sessionEngine.getSessionsWithTransactions();
247
-
248
- return {
249
- ok: 1,
250
- host: `${server.host}:${server.port}`,
251
- version: '7.0.0',
252
- process: 'smartdb',
253
- pid: process.pid,
254
- uptime,
255
- uptimeMillis: uptime * 1000,
256
- uptimeEstimate: uptime,
257
- localTime: new Date(),
258
- mem: {
259
- resident: Math.floor(process.memoryUsage().rss / (1024 * 1024)),
260
- virtual: Math.floor(process.memoryUsage().heapTotal / (1024 * 1024)),
261
- supported: true,
262
- },
263
- connections: {
264
- current: connections,
265
- available: 1000 - connections,
266
- totalCreated: connections,
267
- active: connections,
268
- },
269
- logicalSessionRecordCache: {
270
- activeSessionsCount: sessions.length,
271
- sessionsCollectionJobCount: 0,
272
- lastSessionsCollectionJobDurationMillis: 0,
273
- lastSessionsCollectionJobTimestamp: new Date(),
274
- transactionReaperJobCount: 0,
275
- lastTransactionReaperJobDurationMillis: 0,
276
- lastTransactionReaperJobTimestamp: new Date(),
277
- },
278
- transactions: {
279
- retriedCommandsCount: 0,
280
- retriedStatementsCount: 0,
281
- transactionsCollectionWriteCount: 0,
282
- currentActive: sessionsWithTxn.length,
283
- currentInactive: 0,
284
- currentOpen: sessionsWithTxn.length,
285
- totalStarted: sessionsWithTxn.length,
286
- totalCommitted: 0,
287
- totalAborted: 0,
288
- },
289
- network: {
290
- bytesIn: 0,
291
- bytesOut: 0,
292
- numRequests: 0,
293
- },
294
- storageEngine: {
295
- name: 'smartdb',
296
- supportsCommittedReads: true,
297
- persistent: false,
298
- },
299
- };
300
- }
301
-
302
- /**
303
- * Handle buildInfo command
304
- */
305
- private async handleBuildInfo(context: IHandlerContext): Promise<plugins.bson.Document> {
306
- return {
307
- ok: 1,
308
- version: '7.0.0',
309
- gitVersion: 'smartdb',
310
- modules: [],
311
- allocator: 'system',
312
- javascriptEngine: 'none',
313
- sysInfo: 'deprecated',
314
- versionArray: [7, 0, 0, 0],
315
- openssl: {
316
- running: 'disabled',
317
- compiled: 'disabled',
318
- },
319
- buildEnvironment: {
320
- distmod: 'smartdb',
321
- distarch: process.arch,
322
- cc: '',
323
- ccflags: '',
324
- cxx: '',
325
- cxxflags: '',
326
- linkflags: '',
327
- target_arch: process.arch,
328
- target_os: process.platform,
329
- },
330
- bits: 64,
331
- debug: false,
332
- maxBsonObjectSize: 16777216,
333
- storageEngines: ['smartdb'],
334
- };
335
- }
336
-
337
- /**
338
- * Handle whatsmyuri command
339
- */
340
- private async handleWhatsMyUri(context: IHandlerContext): Promise<plugins.bson.Document> {
341
- const { server } = context;
342
- return {
343
- ok: 1,
344
- you: `127.0.0.1:${server.port}`,
345
- };
346
- }
347
-
348
- /**
349
- * Handle getLog command
350
- */
351
- private async handleGetLog(context: IHandlerContext): Promise<plugins.bson.Document> {
352
- const { command } = context;
353
-
354
- if (command.getLog === '*') {
355
- return {
356
- ok: 1,
357
- names: ['global', 'startupWarnings'],
358
- };
359
- }
360
-
361
- return {
362
- ok: 1,
363
- totalLinesWritten: 0,
364
- log: [],
365
- };
366
- }
367
-
368
- /**
369
- * Handle hostInfo command
370
- */
371
- private async handleHostInfo(context: IHandlerContext): Promise<plugins.bson.Document> {
372
- return {
373
- ok: 1,
374
- system: {
375
- currentTime: new Date(),
376
- hostname: 'localhost',
377
- cpuAddrSize: 64,
378
- memSizeMB: Math.floor(process.memoryUsage().heapTotal / (1024 * 1024)),
379
- numCores: 1,
380
- cpuArch: process.arch,
381
- numaEnabled: false,
382
- },
383
- os: {
384
- type: process.platform,
385
- name: process.platform,
386
- version: process.version,
387
- },
388
- extra: {},
389
- };
390
- }
391
-
392
- /**
393
- * Handle replSetGetStatus command
394
- */
395
- private async handleReplSetGetStatus(context: IHandlerContext): Promise<plugins.bson.Document> {
396
- // We're standalone, not a replica set
397
- return {
398
- ok: 0,
399
- errmsg: 'not running with --replSet',
400
- code: 76,
401
- codeName: 'NoReplicationEnabled',
402
- };
403
- }
404
-
405
- /**
406
- * Handle saslStart command (authentication)
407
- */
408
- private async handleSaslStart(context: IHandlerContext): Promise<plugins.bson.Document> {
409
- // We don't require authentication, but we need to respond properly
410
- // to let drivers know auth is "successful"
411
- return {
412
- ok: 1,
413
- conversationId: 1,
414
- done: true,
415
- payload: Buffer.from([]),
416
- };
417
- }
418
-
419
- /**
420
- * Handle saslContinue command
421
- */
422
- private async handleSaslContinue(context: IHandlerContext): Promise<plugins.bson.Document> {
423
- return {
424
- ok: 1,
425
- conversationId: 1,
426
- done: true,
427
- payload: Buffer.from([]),
428
- };
429
- }
430
-
431
- /**
432
- * Handle endSessions command
433
- */
434
- private async handleEndSessions(context: IHandlerContext): Promise<plugins.bson.Document> {
435
- const { command, sessionEngine } = context;
436
-
437
- // End each session in the array
438
- const sessions = command.endSessions || [];
439
- for (const sessionSpec of sessions) {
440
- const sessionId = SessionEngine.extractSessionId(sessionSpec);
441
- if (sessionId) {
442
- await sessionEngine.endSession(sessionId);
443
- }
444
- }
445
-
446
- return { ok: 1 };
447
- }
448
-
449
- /**
450
- * Handle abortTransaction command
451
- */
452
- private async handleAbortTransaction(context: IHandlerContext): Promise<plugins.bson.Document> {
453
- const { transactionEngine, sessionEngine, txnId, sessionId } = context;
454
-
455
- if (!txnId) {
456
- return {
457
- ok: 0,
458
- errmsg: 'No transaction started',
459
- code: 251,
460
- codeName: 'NoSuchTransaction',
461
- };
462
- }
463
-
464
- try {
465
- await transactionEngine.abortTransaction(txnId);
466
- transactionEngine.endTransaction(txnId);
467
- // Update session state
468
- if (sessionId) {
469
- sessionEngine.endTransaction(sessionId);
470
- }
471
- return { ok: 1 };
472
- } catch (error: any) {
473
- return {
474
- ok: 0,
475
- errmsg: error.message || 'Abort transaction failed',
476
- code: error.code || 1,
477
- codeName: error.codeName || 'UnknownError',
478
- };
479
- }
480
- }
481
-
482
- /**
483
- * Handle commitTransaction command
484
- */
485
- private async handleCommitTransaction(context: IHandlerContext): Promise<plugins.bson.Document> {
486
- const { transactionEngine, sessionEngine, txnId, sessionId } = context;
487
-
488
- if (!txnId) {
489
- return {
490
- ok: 0,
491
- errmsg: 'No transaction started',
492
- code: 251,
493
- codeName: 'NoSuchTransaction',
494
- };
495
- }
496
-
497
- try {
498
- await transactionEngine.commitTransaction(txnId);
499
- transactionEngine.endTransaction(txnId);
500
- // Update session state
501
- if (sessionId) {
502
- sessionEngine.endTransaction(sessionId);
503
- }
504
- return { ok: 1 };
505
- } catch (error: any) {
506
- // If commit fails, transaction should be aborted
507
- try {
508
- await transactionEngine.abortTransaction(txnId);
509
- transactionEngine.endTransaction(txnId);
510
- if (sessionId) {
511
- sessionEngine.endTransaction(sessionId);
512
- }
513
- } catch {
514
- // Ignore abort errors
515
- }
516
-
517
- if (error.code === 112) {
518
- // Write conflict
519
- return {
520
- ok: 0,
521
- errmsg: error.message || 'Write conflict during commit',
522
- code: 112,
523
- codeName: 'WriteConflict',
524
- };
525
- }
526
-
527
- return {
528
- ok: 0,
529
- errmsg: error.message || 'Commit transaction failed',
530
- code: error.code || 1,
531
- codeName: error.codeName || 'UnknownError',
532
- };
533
- }
534
- }
535
-
536
- /**
537
- * Handle collStats command
538
- */
539
- private async handleCollStats(context: IHandlerContext): Promise<plugins.bson.Document> {
540
- const { storage, database, command } = context;
541
-
542
- const collection = command.collStats;
543
-
544
- const exists = await storage.collectionExists(database, collection);
545
- if (!exists) {
546
- return {
547
- ok: 0,
548
- errmsg: `ns not found ${database}.${collection}`,
549
- code: 26,
550
- codeName: 'NamespaceNotFound',
551
- };
552
- }
553
-
554
- const docs = await storage.findAll(database, collection);
555
- const size = docs.reduce((sum, doc) => sum + JSON.stringify(doc).length, 0);
556
- const count = docs.length;
557
- const avgObjSize = count > 0 ? size / count : 0;
558
-
559
- const indexes = await storage.getIndexes(database, collection);
560
-
561
- return {
562
- ok: 1,
563
- ns: `${database}.${collection}`,
564
- count,
565
- size,
566
- avgObjSize,
567
- storageSize: size,
568
- totalIndexSize: 0,
569
- indexSizes: indexes.reduce((acc: any, idx: any) => {
570
- acc[idx.name] = 0;
571
- return acc;
572
- }, {}),
573
- nindexes: indexes.length,
574
- };
575
- }
576
-
577
- /**
578
- * Handle dbStats command
579
- */
580
- private async handleDbStats(context: IHandlerContext): Promise<plugins.bson.Document> {
581
- const { storage, database } = context;
582
-
583
- const collections = await storage.listCollections(database);
584
- let totalSize = 0;
585
- let totalObjects = 0;
586
-
587
- for (const collName of collections) {
588
- const docs = await storage.findAll(database, collName);
589
- totalObjects += docs.length;
590
- totalSize += docs.reduce((sum, doc) => sum + JSON.stringify(doc).length, 0);
591
- }
592
-
593
- return {
594
- ok: 1,
595
- db: database,
596
- collections: collections.length,
597
- views: 0,
598
- objects: totalObjects,
599
- avgObjSize: totalObjects > 0 ? totalSize / totalObjects : 0,
600
- dataSize: totalSize,
601
- storageSize: totalSize,
602
- indexes: collections.length, // At least _id index per collection
603
- indexSize: 0,
604
- totalSize,
605
- };
606
- }
607
-
608
- /**
609
- * Handle connectionStatus command
610
- */
611
- private async handleConnectionStatus(context: IHandlerContext): Promise<plugins.bson.Document> {
612
- return {
613
- ok: 1,
614
- authInfo: {
615
- authenticatedUsers: [],
616
- authenticatedUserRoles: [],
617
- },
618
- };
619
- }
620
-
621
- /**
622
- * Handle currentOp command
623
- */
624
- private async handleCurrentOp(context: IHandlerContext): Promise<plugins.bson.Document> {
625
- return {
626
- ok: 1,
627
- inprog: [],
628
- };
629
- }
630
-
631
- /**
632
- * Handle collMod command
633
- */
634
- private async handleCollMod(context: IHandlerContext): Promise<plugins.bson.Document> {
635
- // We don't support modifying collection options, but acknowledge the command
636
- return { ok: 1 };
637
- }
638
-
639
- /**
640
- * Handle renameCollection command
641
- */
642
- private async handleRenameCollection(context: IHandlerContext): Promise<plugins.bson.Document> {
643
- const { storage, command } = context;
644
-
645
- const from = command.renameCollection;
646
- const to = command.to;
647
- const dropTarget = command.dropTarget || false;
648
-
649
- if (!from || !to) {
650
- return {
651
- ok: 0,
652
- errmsg: 'renameCollection requires both source and target',
653
- code: 2,
654
- codeName: 'BadValue',
655
- };
656
- }
657
-
658
- // Parse namespace (format: "db.collection")
659
- const fromParts = from.split('.');
660
- const toParts = to.split('.');
661
-
662
- if (fromParts.length < 2 || toParts.length < 2) {
663
- return {
664
- ok: 0,
665
- errmsg: 'Invalid namespace format',
666
- code: 73,
667
- codeName: 'InvalidNamespace',
668
- };
669
- }
670
-
671
- const fromDb = fromParts[0];
672
- const fromColl = fromParts.slice(1).join('.');
673
- const toDb = toParts[0];
674
- const toColl = toParts.slice(1).join('.');
675
-
676
- // Check if source exists
677
- const sourceExists = await storage.collectionExists(fromDb, fromColl);
678
- if (!sourceExists) {
679
- return {
680
- ok: 0,
681
- errmsg: `source namespace ${from} does not exist`,
682
- code: 26,
683
- codeName: 'NamespaceNotFound',
684
- };
685
- }
686
-
687
- // Check if target exists
688
- const targetExists = await storage.collectionExists(toDb, toColl);
689
- if (targetExists) {
690
- if (dropTarget) {
691
- await storage.dropCollection(toDb, toColl);
692
- } else {
693
- return {
694
- ok: 0,
695
- errmsg: `target namespace ${to} already exists`,
696
- code: 48,
697
- codeName: 'NamespaceExists',
698
- };
699
- }
700
- }
701
-
702
- // Same database rename
703
- if (fromDb === toDb) {
704
- await storage.renameCollection(fromDb, fromColl, toColl);
705
- } else {
706
- // Cross-database rename: copy documents then drop source
707
- await storage.createCollection(toDb, toColl);
708
- const docs = await storage.findAll(fromDb, fromColl);
709
-
710
- for (const doc of docs) {
711
- await storage.insertOne(toDb, toColl, doc);
712
- }
713
-
714
- await storage.dropCollection(fromDb, fromColl);
715
- }
716
-
717
- return { ok: 1 };
718
- }
719
- }