@intranefr/superbackend 1.7.7 → 1.7.9

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 (119) hide show
  1. package/.beads/.br_history/issues.20260314_212352_900045509.jsonl +0 -0
  2. package/.beads/.br_history/issues.20260314_212352_900045509.jsonl.meta.json +1 -0
  3. package/.beads/.br_history/issues.20260314_212353_087140743.jsonl +1 -0
  4. package/.beads/.br_history/issues.20260314_212353_087140743.jsonl.meta.json +1 -0
  5. package/.beads/.br_history/issues.20260314_212353_285881504.jsonl +2 -0
  6. package/.beads/.br_history/issues.20260314_212353_285881504.jsonl.meta.json +1 -0
  7. package/.beads/.br_history/issues.20260314_212353_473915419.jsonl +3 -0
  8. package/.beads/.br_history/issues.20260314_212353_473915419.jsonl.meta.json +1 -0
  9. package/.beads/.br_history/issues.20260314_212353_659476307.jsonl +4 -0
  10. package/.beads/.br_history/issues.20260314_212353_659476307.jsonl.meta.json +1 -0
  11. package/.beads/.br_history/issues.20260314_212353_869998925.jsonl +5 -0
  12. package/.beads/.br_history/issues.20260314_212353_869998925.jsonl.meta.json +1 -0
  13. package/.beads/.br_history/issues.20260314_212354_054785029.jsonl +6 -0
  14. package/.beads/.br_history/issues.20260314_212354_054785029.jsonl.meta.json +1 -0
  15. package/.beads/.br_history/issues.20260314_213336_175893691.jsonl +7 -0
  16. package/.beads/.br_history/issues.20260314_213336_175893691.jsonl.meta.json +1 -0
  17. package/.beads/.br_history/issues.20260314_213336_338509797.jsonl +7 -0
  18. package/.beads/.br_history/issues.20260314_213336_338509797.jsonl.meta.json +1 -0
  19. package/.beads/.br_history/issues.20260314_213336_515443192.jsonl +7 -0
  20. package/.beads/.br_history/issues.20260314_213336_515443192.jsonl.meta.json +1 -0
  21. package/.beads/.br_history/issues.20260314_213336_676417592.jsonl +7 -0
  22. package/.beads/.br_history/issues.20260314_213336_676417592.jsonl.meta.json +1 -0
  23. package/.beads/.br_history/issues.20260314_213336_839182422.jsonl +7 -0
  24. package/.beads/.br_history/issues.20260314_213336_839182422.jsonl.meta.json +1 -0
  25. package/.beads/.br_history/issues.20260314_213337_004349113.jsonl +7 -0
  26. package/.beads/.br_history/issues.20260314_213337_004349113.jsonl.meta.json +1 -0
  27. package/.beads/.br_history/issues.20260314_213337_179824080.jsonl +7 -0
  28. package/.beads/.br_history/issues.20260314_213337_179824080.jsonl.meta.json +1 -0
  29. package/.beads/.br_history/issues.20260314_213701_705075332.jsonl +7 -0
  30. package/.beads/.br_history/issues.20260314_213701_705075332.jsonl.meta.json +1 -0
  31. package/.beads/.br_history/issues.20260314_213706_783128702.jsonl +8 -0
  32. package/.beads/.br_history/issues.20260314_213706_783128702.jsonl.meta.json +1 -0
  33. package/.beads/config.yaml +4 -0
  34. package/.beads/issues.jsonl +8 -0
  35. package/.beads/metadata.json +4 -0
  36. package/.env.example +8 -0
  37. package/autochangelog/.env.example +36 -0
  38. package/autochangelog/README.md +412 -0
  39. package/autochangelog/config/database.js +27 -0
  40. package/autochangelog/package.json +47 -0
  41. package/autochangelog/public/landing.html +581 -0
  42. package/autochangelog/server.js +104 -0
  43. package/autochangelog/src/app.js +181 -0
  44. package/autochangelog/src/config/database.js +26 -0
  45. package/autochangelog/src/controllers/auth.js +488 -0
  46. package/autochangelog/src/controllers/changelog.js +682 -0
  47. package/autochangelog/src/controllers/project.js +580 -0
  48. package/autochangelog/src/controllers/repository.js +780 -0
  49. package/autochangelog/src/middleware/auth.js +386 -0
  50. package/autochangelog/src/models/Changelog.js +443 -0
  51. package/autochangelog/src/models/Project.js +226 -0
  52. package/autochangelog/src/models/Repository.js +366 -0
  53. package/autochangelog/src/models/User.js +223 -0
  54. package/autochangelog/src/routes/auth.routes.js +32 -0
  55. package/autochangelog/src/routes/changelog.routes.js +42 -0
  56. package/autochangelog/src/routes/github-auth.routes.js +102 -0
  57. package/autochangelog/src/routes/project.routes.js +50 -0
  58. package/autochangelog/src/routes/repository.routes.js +54 -0
  59. package/autochangelog/src/services/changelog.js +722 -0
  60. package/autochangelog/src/services/github.js +243 -0
  61. package/autochangelog/utils/logger.js +77 -0
  62. package/autochangelog/views/404.ejs +18 -0
  63. package/autochangelog/views/dashboard.ejs +596 -0
  64. package/autochangelog/views/index.ejs +231 -0
  65. package/autochangelog/views/layouts/main.ejs +44 -0
  66. package/autochangelog/views/login.ejs +104 -0
  67. package/autochangelog/views/partials/footer.ejs +20 -0
  68. package/autochangelog/views/partials/navbar.ejs +51 -0
  69. package/autochangelog/views/register.ejs +109 -0
  70. package/autochangelog-cli/README.md +266 -0
  71. package/autochangelog-cli/bin/autochangelog +120 -0
  72. package/autochangelog-cli/package.json +46 -0
  73. package/autochangelog-cli/src/cli/commands/auth.js +291 -0
  74. package/autochangelog-cli/src/cli/commands/changelog.js +619 -0
  75. package/autochangelog-cli/src/cli/commands/project.js +427 -0
  76. package/autochangelog-cli/src/cli/commands/repo.js +557 -0
  77. package/autochangelog-cli/src/cli/commands/stats.js +706 -0
  78. package/autochangelog-cli/src/cli/utils/config.js +277 -0
  79. package/autochangelog-cli/src/cli/utils/errors.js +307 -0
  80. package/autochangelog-cli/src/cli/utils/logger.js +75 -0
  81. package/autochangelog-cli/src/cli/utils/output.js +357 -0
  82. package/package.json +8 -3
  83. package/plugins/supercli/README.md +108 -0
  84. package/plugins/supercli/plugin.json +123 -0
  85. package/server.js +1 -1
  86. package/src/cli/api.js +380 -0
  87. package/src/cli/direct/agent-utils.js +61 -0
  88. package/src/cli/direct/cli-utils.js +112 -0
  89. package/src/cli/direct/data-seeding.js +307 -0
  90. package/src/cli/direct/db-admin.js +84 -0
  91. package/src/cli/direct/db-advanced.js +372 -0
  92. package/src/cli/direct/db-utils.js +558 -0
  93. package/src/cli/direct/help.js +195 -0
  94. package/src/cli/direct/migration.js +107 -0
  95. package/src/cli/direct/rbac-advanced.js +132 -0
  96. package/src/cli/direct/resources-additional.js +400 -0
  97. package/src/cli/direct/resources-cms-advanced.js +173 -0
  98. package/src/cli/direct/resources-cms.js +247 -0
  99. package/src/cli/direct/resources-core.js +253 -0
  100. package/src/cli/direct/resources-execution.js +367 -0
  101. package/src/cli/direct/resources-health.js +152 -0
  102. package/src/cli/direct/resources-integrations.js +182 -0
  103. package/src/cli/direct/resources-logs.js +204 -0
  104. package/src/cli/direct/resources-org-rbac.js +187 -0
  105. package/src/cli/direct/resources-system.js +236 -0
  106. package/src/cli/direct.js +556 -0
  107. package/src/controllers/admin.controller.js +4 -0
  108. package/src/controllers/auth.controller.js +148 -1
  109. package/src/controllers/waitingList.controller.js +130 -1
  110. package/src/models/RbacRole.js +1 -1
  111. package/src/models/User.js +39 -5
  112. package/src/routes/auth.routes.js +6 -0
  113. package/src/routes/waitingList.routes.js +12 -2
  114. package/src/routes/waitingListAdmin.routes.js +3 -0
  115. package/src/services/email.service.js +1 -0
  116. package/src/services/github.service.js +255 -0
  117. package/src/services/rateLimiter.service.js +29 -1
  118. package/src/services/waitingListJson.service.js +32 -3
  119. package/views/admin-waiting-list.ejs +386 -3
@@ -0,0 +1,558 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Database utilities: db-stats, db-indexes, db-cleanup, and collection operations
5
+ */
6
+
7
+ const mongoose = require("mongoose");
8
+
9
+ const dbStats = {
10
+ async execute(options, context) {
11
+ const db = context.db;
12
+ const collections = await db.listCollections().toArray();
13
+ const stats = {};
14
+ let totalDocs = 0,
15
+ totalSize = 0;
16
+
17
+ for (const coll of collections) {
18
+ const count = await db.collection(coll.name).countDocuments();
19
+ stats[coll.name] = { count };
20
+ totalDocs += count;
21
+ }
22
+
23
+ return {
24
+ collections: collections.length,
25
+ totalDocuments: totalDocs,
26
+ byCollection: stats,
27
+ };
28
+ },
29
+ };
30
+
31
+ const dbIndexes = {
32
+ async execute(options, context) {
33
+ const db = context.db;
34
+ const collectionName = options.key;
35
+
36
+ if (options.command === "execute" || !collectionName) {
37
+ const collections = await db.listCollections().toArray();
38
+ const result = [];
39
+ for (const coll of collections) {
40
+ const indexes = await db.collection(coll.name).indexes();
41
+ result.push({
42
+ collection: coll.name,
43
+ indexCount: indexes.length,
44
+ indexes: indexes.map((idx) => ({
45
+ name: idx.name,
46
+ key: idx.key,
47
+ unique: idx.unique || false,
48
+ })),
49
+ });
50
+ }
51
+ return result;
52
+ }
53
+
54
+ const indexes = await db.collection(collectionName).indexes();
55
+ return {
56
+ collection: collectionName,
57
+ indexCount: indexes.length,
58
+ indexes: indexes.map((idx) => ({
59
+ name: idx.name,
60
+ key: idx.key,
61
+ unique: idx.unique || false,
62
+ })),
63
+ };
64
+ },
65
+ };
66
+
67
+ const dbCleanup = {
68
+ async execute(options, context) {
69
+ const db = context.db;
70
+ const collectionName = options.key;
71
+ const days = parseInt(options.value) || 30;
72
+ const cutoffDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
73
+
74
+ if (!collectionName) throw new Error("--key (collection name) is required");
75
+
76
+ const collection = db.collection(collectionName);
77
+ const result = await collection.deleteMany({
78
+ createdAt: { $lt: cutoffDate },
79
+ });
80
+
81
+ return {
82
+ collection: collectionName,
83
+ deletedCount: result.deletedCount,
84
+ olderThan: cutoffDate.toISOString(),
85
+ };
86
+ },
87
+ };
88
+
89
+ const batchDelete = {
90
+ async execute(options, context) {
91
+ const db = context.db;
92
+ const collectionName = options.key;
93
+ const filterKey = options.description || "_id";
94
+ const idsArg = options.value;
95
+
96
+ if (!collectionName) throw new Error("--key (collection name) is required");
97
+ if (!idsArg) throw new Error("--value (comma-separated IDs) is required");
98
+
99
+ const ids = idsArg.split(",").map((id) => id.trim());
100
+ const filter = { [filterKey]: { $in: ids } };
101
+ const result = await db.collection(collectionName).deleteMany(filter);
102
+
103
+ return {
104
+ collection: collectionName,
105
+ deletedCount: result.deletedCount,
106
+ requestedCount: ids.length,
107
+ filter,
108
+ };
109
+ },
110
+ };
111
+
112
+ const batchUpdate = {
113
+ async execute(options, context) {
114
+ const db = context.db;
115
+ const collectionName = options.key;
116
+ const updateJson = options.value;
117
+
118
+ if (!collectionName) throw new Error("--key (collection name) is required");
119
+ if (!updateJson) throw new Error("--value (update JSON) is required");
120
+
121
+ let update;
122
+ try {
123
+ update = JSON.parse(updateJson);
124
+ } catch (e) {
125
+ throw new Error("--value must be valid JSON");
126
+ }
127
+
128
+ const result = await db.collection(collectionName).updateMany({}, update);
129
+ return {
130
+ collection: collectionName,
131
+ matchedCount: result.matchedCount,
132
+ modifiedCount: result.modifiedCount,
133
+ update,
134
+ };
135
+ },
136
+ };
137
+
138
+ const collectionCount = {
139
+ async execute(options, context) {
140
+ const db = context.db;
141
+ const collectionName = options.key;
142
+
143
+ if (!collectionName) {
144
+ const collections = await db.listCollections().toArray();
145
+ const counts = {};
146
+ let total = 0;
147
+ for (const coll of collections) {
148
+ const count = await db.collection(coll.name).countDocuments();
149
+ counts[coll.name] = count;
150
+ total += count;
151
+ }
152
+ return {
153
+ totalDocuments: total,
154
+ collectionCount: collections.length,
155
+ byCollection: counts,
156
+ };
157
+ }
158
+
159
+ const count = await db.collection(collectionName).countDocuments();
160
+ return { collection: collectionName, count };
161
+ },
162
+ };
163
+
164
+ const collectionSchema = {
165
+ async execute(options, context) {
166
+ const db = context.db;
167
+ const collectionName = options.key;
168
+
169
+ if (!collectionName) throw new Error("--key (collection name) is required");
170
+
171
+ const collection = db.collection(collectionName);
172
+ const sample = await collection.findOne();
173
+ const indexes = await collection.indexes();
174
+
175
+ if (!sample) {
176
+ return {
177
+ collection: collectionName,
178
+ message: "Collection is empty",
179
+ indexes: indexes.map((idx) => ({ name: idx.name, key: idx.key })),
180
+ };
181
+ }
182
+
183
+ const schema = {};
184
+ for (const [key, value] of Object.entries(sample)) {
185
+ schema[key] = {
186
+ type:
187
+ value === null
188
+ ? "null"
189
+ : Array.isArray(value)
190
+ ? "array"
191
+ : typeof value,
192
+ example:
193
+ value === null
194
+ ? null
195
+ : typeof value === "string" && value.length > 50
196
+ ? value.slice(0, 50) + "..."
197
+ : value,
198
+ };
199
+ }
200
+
201
+ return {
202
+ collection: collectionName,
203
+ sampleSize: 1,
204
+ schema,
205
+ indexes: indexes.map((idx) => ({
206
+ name: idx.name,
207
+ key: idx.key,
208
+ unique: idx.unique || false,
209
+ })),
210
+ };
211
+ },
212
+ };
213
+
214
+ const exportCollection = {
215
+ async execute(options, context) {
216
+ const db = context.db;
217
+ const collectionName = options.key;
218
+ const limit = parseInt(options.value) || 1000;
219
+ const outputFile = options.description || `${collectionName}-export.json`;
220
+
221
+ if (!collectionName) throw new Error("--key (collection name) is required");
222
+
223
+ const fs = require("fs");
224
+ const collection = db.collection(collectionName);
225
+ const documents = await collection.find({}).limit(limit).toArray();
226
+ fs.writeFileSync(outputFile, JSON.stringify(documents, null, 2));
227
+
228
+ return {
229
+ collection: collectionName,
230
+ exportedCount: documents.length,
231
+ outputFile,
232
+ limit,
233
+ };
234
+ },
235
+ };
236
+
237
+ const findDuplicates = {
238
+ async execute(options, context) {
239
+ const db = context.db;
240
+ const collectionName = options.key;
241
+ const field = options.description || "email";
242
+
243
+ if (!collectionName) throw new Error("--key (collection name) is required");
244
+
245
+ const collection = db.collection(collectionName);
246
+ const duplicates = await collection
247
+ .aggregate([
248
+ {
249
+ $group: {
250
+ _id: `$${field}`,
251
+ count: { $sum: 1 },
252
+ ids: { $push: "$_id" },
253
+ },
254
+ },
255
+ { $match: { count: { $gt: 1 } } },
256
+ { $sort: { count: -1 } },
257
+ { $limit: 100 },
258
+ ])
259
+ .toArray();
260
+
261
+ return {
262
+ collection: collectionName,
263
+ field,
264
+ duplicateCount: duplicates.length,
265
+ duplicates,
266
+ };
267
+ },
268
+ };
269
+
270
+ const removeDuplicates = {
271
+ async execute(options, context) {
272
+ const db = context.db;
273
+ const collectionName = options.key;
274
+ const field = options.description || "email";
275
+
276
+ if (!collectionName) throw new Error("--key (collection name) is required");
277
+
278
+ const collection = db.collection(collectionName);
279
+ const duplicates = await collection
280
+ .aggregate([
281
+ {
282
+ $group: {
283
+ _id: `$${field}`,
284
+ count: { $sum: 1 },
285
+ ids: { $push: "$_id" },
286
+ },
287
+ },
288
+ { $match: { count: { $gt: 1 } } },
289
+ ])
290
+ .toArray();
291
+
292
+ let removedCount = 0;
293
+ for (const dup of duplicates) {
294
+ const idsToDelete = dup.ids.slice(1);
295
+ const result = await collection.deleteMany({ _id: { $in: idsToDelete } });
296
+ removedCount += result.deletedCount;
297
+ }
298
+
299
+ return {
300
+ collection: collectionName,
301
+ field,
302
+ groupsProcessed: duplicates.length,
303
+ removedCount,
304
+ };
305
+ },
306
+ };
307
+
308
+ const validateRefs = {
309
+ async execute(options, context) {
310
+ const db = context.db;
311
+ const collectionName = options.key;
312
+ const refField = options.description || "userId";
313
+ const refCollection = options.value || "users";
314
+
315
+ if (!collectionName) throw new Error("--key (collection name) is required");
316
+
317
+ const collection = db.collection(collectionName);
318
+ const refCollectionObj = db.collection(refCollection);
319
+ const docs = await collection
320
+ .find({ [refField]: { $exists: true, $ne: null } })
321
+ .toArray();
322
+ const invalidRefs = [];
323
+
324
+ for (const doc of docs) {
325
+ const refId = doc[refField];
326
+ const exists = await refCollectionObj.findOne({ _id: refId });
327
+ if (!exists) invalidRefs.push({ docId: doc._id, [refField]: refId });
328
+ }
329
+
330
+ return {
331
+ collection: collectionName,
332
+ refField,
333
+ refCollection,
334
+ totalDocs: docs.length,
335
+ invalidRefs: invalidRefs.length,
336
+ samples: invalidRefs.slice(0, 20),
337
+ };
338
+ },
339
+ };
340
+
341
+ const repairRefs = {
342
+ async execute(options, context) {
343
+ const db = context.db;
344
+ const collectionName = options.key;
345
+ const refField = options.description || "userId";
346
+ const refCollection = options.value || "users";
347
+ const action = options.name || "nullify";
348
+
349
+ if (!collectionName) throw new Error("--key (collection name) is required");
350
+
351
+ const collection = db.collection(collectionName);
352
+ const refCollectionObj = db.collection(refCollection);
353
+ const docs = await collection
354
+ .find({ [refField]: { $exists: true, $ne: null } })
355
+ .toArray();
356
+ let repairedCount = 0;
357
+
358
+ for (const doc of docs) {
359
+ const refId = doc[refField];
360
+ const exists = await refCollectionObj.findOne({ _id: refId });
361
+ if (!exists) {
362
+ if (action === "delete") {
363
+ await collection.deleteOne({ _id: doc._id });
364
+ } else {
365
+ await collection.updateOne(
366
+ { _id: doc._id },
367
+ { $set: { [refField]: null } },
368
+ );
369
+ }
370
+ repairedCount++;
371
+ }
372
+ }
373
+
374
+ return {
375
+ collection: collectionName,
376
+ refField,
377
+ refCollection,
378
+ action,
379
+ repairedCount,
380
+ };
381
+ },
382
+ };
383
+
384
+ const addIndex = {
385
+ async execute(options, context) {
386
+ const db = context.db;
387
+ const collectionName = options.key;
388
+ const fields = options.value;
389
+
390
+ if (!collectionName) throw new Error("--key (collection name) is required");
391
+ if (!fields)
392
+ throw new Error("--value (comma-separated fields) is required");
393
+
394
+ const collection = db.collection(collectionName);
395
+ const indexSpec = {};
396
+ fields.split(",").forEach((f) => {
397
+ indexSpec[f.trim()] = 1;
398
+ });
399
+ const indexName = await collection.createIndex(indexSpec);
400
+
401
+ return { collection: collectionName, indexName, indexSpec };
402
+ },
403
+ };
404
+
405
+ const dropIndex = {
406
+ async execute(options, context) {
407
+ const db = context.db;
408
+ const collectionName = options.key;
409
+ const indexName = options.value;
410
+
411
+ if (!collectionName) throw new Error("--key (collection name) is required");
412
+ if (!indexName) throw new Error("--value (index name) is required");
413
+
414
+ const collection = db.collection(collectionName);
415
+ await collection.dropIndex(indexName);
416
+ return { collection: collectionName, indexName, success: true };
417
+ },
418
+ };
419
+
420
+ const reindex = {
421
+ async execute(options, context) {
422
+ const db = context.db;
423
+ const collectionName = options.key;
424
+
425
+ if (!collectionName) throw new Error("--key (collection name) is required");
426
+
427
+ const collection = db.collection(collectionName);
428
+ const result = await collection.reIndex();
429
+ return {
430
+ collection: collectionName,
431
+ nIndexesWas: result.nIndexesWas,
432
+ nIndexes: result.nIndexes,
433
+ ok: result.ok,
434
+ };
435
+ },
436
+ };
437
+
438
+ const compact = {
439
+ async execute(options, context) {
440
+ const db = context.db;
441
+ const collectionName = options.key;
442
+
443
+ if (!collectionName) throw new Error("--key (collection name) is required");
444
+
445
+ const result = await db.command({ compact: collectionName });
446
+ return {
447
+ collection: collectionName,
448
+ bytesFreed: result.bytesFreed,
449
+ ok: result.ok,
450
+ };
451
+ },
452
+ };
453
+
454
+ const validateCollection = {
455
+ async execute(options, context) {
456
+ const db = context.db;
457
+ const collectionName = options.key;
458
+
459
+ if (!collectionName) throw new Error("--key (collection name) is required");
460
+
461
+ const result = await db.command({ validate: collectionName });
462
+ return {
463
+ collection: collectionName,
464
+ valid: result.valid,
465
+ errors: result.errors || [],
466
+ warnings: result.warnings || [],
467
+ ok: result.ok,
468
+ };
469
+ },
470
+ };
471
+
472
+ const renameCollection = {
473
+ async execute(options, context) {
474
+ const db = context.db;
475
+ const collectionName = options.key;
476
+ const newName = options.value;
477
+
478
+ if (!collectionName) throw new Error("--key (collection name) is required");
479
+ if (!newName) throw new Error("--value (new name) is required");
480
+
481
+ const collection = db.collection(collectionName);
482
+ await collection.rename(newName);
483
+ return { oldName: collectionName, newName, success: true };
484
+ },
485
+ };
486
+
487
+ const listCollections = {
488
+ async execute(options, context) {
489
+ const db = context.db;
490
+ const collections = await db.listCollections().toArray();
491
+ const details = [];
492
+
493
+ for (const coll of collections) {
494
+ const stats = await db.collection(coll.name).stats();
495
+ details.push({
496
+ name: coll.name,
497
+ type: coll.type,
498
+ count: stats.count,
499
+ size: stats.size,
500
+ storageSize: stats.storageSize,
501
+ indexes: stats.nindexes,
502
+ });
503
+ }
504
+
505
+ return { totalCollections: collections.length, collections: details };
506
+ },
507
+ };
508
+
509
+ const createCollection = {
510
+ async execute(options, context) {
511
+ const db = context.db;
512
+ const collectionName = options.key;
513
+ const capped = options.description === "capped";
514
+ const size = parseInt(options.value) || 1048576;
515
+
516
+ if (!collectionName) throw new Error("--key (collection name) is required");
517
+
518
+ const opts = capped ? { capped: true, size } : {};
519
+ await db.createCollection(collectionName, opts);
520
+ return { name: collectionName, capped, size: opts.size, success: true };
521
+ },
522
+ };
523
+
524
+ const dropCollection = {
525
+ async execute(options, context) {
526
+ const db = context.db;
527
+ const collectionName = options.key;
528
+
529
+ if (!collectionName) throw new Error("--key (collection name) is required");
530
+
531
+ await db.collection(collectionName).drop();
532
+ return { name: collectionName, success: true };
533
+ },
534
+ };
535
+
536
+ module.exports = {
537
+ dbStats,
538
+ dbIndexes,
539
+ dbCleanup,
540
+ batchDelete,
541
+ batchUpdate,
542
+ collectionCount,
543
+ collectionSchema,
544
+ exportCollection,
545
+ findDuplicates,
546
+ removeDuplicates,
547
+ validateRefs,
548
+ repairRefs,
549
+ addIndex,
550
+ dropIndex,
551
+ reindex,
552
+ compact,
553
+ validateCollection,
554
+ renameCollection,
555
+ listCollections,
556
+ createCollection,
557
+ dropCollection,
558
+ };