@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,367 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Additional resources: experiments, rate-limits, demo, blog-automation, execution history
5
+ */
6
+
7
+ const mongoose = require("mongoose");
8
+
9
+ const demos = {
10
+ async execute(options) {
11
+ const SuperDemo = mongoose.model("SuperDemo");
12
+ switch (options.command) {
13
+ case "list": {
14
+ const demos = await SuperDemo.find().lean();
15
+ return { items: demos, count: demos.length };
16
+ }
17
+ case "get": {
18
+ if (!options.id) throw new Error("Demo ID is required");
19
+ const demo = await SuperDemo.findById(options.id).lean();
20
+ if (!demo) throw new Error("Demo not found");
21
+ return demo;
22
+ }
23
+ case "create": {
24
+ if (!options.name) throw new Error("--name is required");
25
+ const demo = await SuperDemo.create({
26
+ name: options.name,
27
+ demoId: `demo_${Date.now()}`,
28
+ projectId: options.description || "default",
29
+ status: "draft",
30
+ });
31
+ return demo;
32
+ }
33
+ case "delete": {
34
+ if (!options.id) throw new Error("Demo ID is required");
35
+ const demo = await SuperDemo.findByIdAndDelete(options.id);
36
+ if (!demo) throw new Error("Demo not found");
37
+ return { success: true, id: options.id };
38
+ }
39
+ default:
40
+ throw new Error(`Unknown demos command: ${options.command}`);
41
+ }
42
+ },
43
+ };
44
+
45
+ const experiments = {
46
+ async execute(options) {
47
+ const Experiment = mongoose.model("Experiment");
48
+ switch (options.command) {
49
+ case "list": {
50
+ const experiments = await Experiment.find().lean();
51
+ return { items: experiments, count: experiments.length };
52
+ }
53
+ case "get": {
54
+ if (!options.id) throw new Error("Experiment ID is required");
55
+ const experiment = await Experiment.findById(options.id).lean();
56
+ if (!experiment) throw new Error("Experiment not found");
57
+ return experiment;
58
+ }
59
+ case "create": {
60
+ if (!options.name) throw new Error("--name is required");
61
+ const experiment = await Experiment.create({
62
+ name: options.name,
63
+ description: options.description || "",
64
+ status: "draft",
65
+ });
66
+ return experiment;
67
+ }
68
+ case "delete": {
69
+ if (!options.id) throw new Error("Experiment ID is required");
70
+ const experiment = await Experiment.findByIdAndDelete(options.id);
71
+ if (!experiment) throw new Error("Experiment not found");
72
+ return { success: true, id: options.id };
73
+ }
74
+ default:
75
+ throw new Error(`Unknown experiments command: ${options.command}`);
76
+ }
77
+ },
78
+ };
79
+
80
+ const experimentAssignments = {
81
+ async execute(options) {
82
+ const ExperimentAssignment = mongoose.model("ExperimentAssignment");
83
+ switch (options.command) {
84
+ case "list": {
85
+ const limit = parseInt(options.value) || 50;
86
+ const assignments = await ExperimentAssignment.find()
87
+ .sort({ createdAt: -1 })
88
+ .limit(limit)
89
+ .lean();
90
+ return { items: assignments, count: assignments.length };
91
+ }
92
+ case "get": {
93
+ if (!options.id) throw new Error("Assignment ID is required");
94
+ const assignment = await ExperimentAssignment.findById(
95
+ options.id,
96
+ ).lean();
97
+ if (!assignment) throw new Error("Assignment not found");
98
+ return assignment;
99
+ }
100
+ case "clear": {
101
+ const result = await ExperimentAssignment.deleteMany({});
102
+ return { success: true, deletedCount: result.deletedCount };
103
+ }
104
+ default:
105
+ throw new Error(
106
+ `Unknown experiment-assignments command: ${options.command}`,
107
+ );
108
+ }
109
+ },
110
+ };
111
+
112
+ const rateLimits = {
113
+ async execute(options) {
114
+ const RateLimitCounter = mongoose.model("RateLimitCounter");
115
+ switch (options.command) {
116
+ case "list": {
117
+ const limit = parseInt(options.value) || 50;
118
+ const counters = await RateLimitCounter.find()
119
+ .sort({ createdAt: -1 })
120
+ .limit(limit)
121
+ .lean();
122
+ return { items: counters, count: counters.length };
123
+ }
124
+ case "get": {
125
+ if (!options.key) throw new Error("--key (limit key) is required");
126
+ const counter = await RateLimitCounter.findOne({
127
+ key: options.key,
128
+ }).lean();
129
+ if (!counter) throw new Error("Rate limit counter not found");
130
+ return counter;
131
+ }
132
+ case "delete": {
133
+ if (!options.key) throw new Error("--key (limit key) is required");
134
+ const counter = await RateLimitCounter.findOneAndDelete({
135
+ key: options.key,
136
+ });
137
+ if (!counter) throw new Error("Rate limit counter not found");
138
+ return { success: true, key: options.key };
139
+ }
140
+ case "clear": {
141
+ const result = await RateLimitCounter.deleteMany({});
142
+ return { success: true, deletedCount: result.deletedCount };
143
+ }
144
+ default:
145
+ throw new Error(`Unknown rate-limits command: ${options.command}`);
146
+ }
147
+ },
148
+ };
149
+
150
+ const demoProjects = {
151
+ async execute(options) {
152
+ const SuperDemoProject = mongoose.model("SuperDemoProject");
153
+ switch (options.command) {
154
+ case "list": {
155
+ const projects = await SuperDemoProject.find().lean();
156
+ return { items: projects, count: projects.length };
157
+ }
158
+ case "get": {
159
+ if (!options.id) throw new Error("Demo project ID is required");
160
+ const project = await SuperDemoProject.findById(options.id).lean();
161
+ if (!project) throw new Error("Demo project not found");
162
+ return project;
163
+ }
164
+ case "create": {
165
+ if (!options.name) throw new Error("--name is required");
166
+ const project = await SuperDemoProject.create({
167
+ name: options.name,
168
+ description: options.description || "",
169
+ });
170
+ return project;
171
+ }
172
+ case "delete": {
173
+ if (!options.id) throw new Error("Demo project ID is required");
174
+ const project = await SuperDemoProject.findByIdAndDelete(options.id);
175
+ if (!project) throw new Error("Demo project not found");
176
+ return { success: true, id: options.id };
177
+ }
178
+ default:
179
+ throw new Error(`Unknown demo-projects command: ${options.command}`);
180
+ }
181
+ },
182
+ };
183
+
184
+ const demoSteps = {
185
+ async execute(options) {
186
+ const SuperDemoStep = mongoose.model("SuperDemoStep");
187
+ switch (options.command) {
188
+ case "list": {
189
+ const limit = parseInt(options.value) || 50;
190
+ const steps = await SuperDemoStep.find()
191
+ .sort({ createdAt: -1 })
192
+ .limit(limit)
193
+ .lean();
194
+ return { items: steps, count: steps.length };
195
+ }
196
+ case "get": {
197
+ if (!options.id) throw new Error("Demo step ID is required");
198
+ const step = await SuperDemoStep.findById(options.id).lean();
199
+ if (!step) throw new Error("Demo step not found");
200
+ return step;
201
+ }
202
+ case "delete": {
203
+ if (!options.id) throw new Error("Demo step ID is required");
204
+ const step = await SuperDemoStep.findByIdAndDelete(options.id);
205
+ if (!step) throw new Error("Demo step not found");
206
+ return { success: true, id: options.id };
207
+ }
208
+ case "clear": {
209
+ const result = await SuperDemoStep.deleteMany({});
210
+ return { success: true, deletedCount: result.deletedCount };
211
+ }
212
+ default:
213
+ throw new Error(`Unknown demo-steps command: ${options.command}`);
214
+ }
215
+ },
216
+ };
217
+
218
+ const blogAutomationLocks = {
219
+ async execute(options) {
220
+ const BlogAutomationLock = mongoose.model("BlogAutomationLock");
221
+ switch (options.command) {
222
+ case "list": {
223
+ const locks = await BlogAutomationLock.find().lean();
224
+ return { items: locks, count: locks.length };
225
+ }
226
+ case "clear": {
227
+ const result = await BlogAutomationLock.deleteMany({});
228
+ return { success: true, deletedCount: result.deletedCount };
229
+ }
230
+ default:
231
+ throw new Error(
232
+ `Unknown blog-automation-locks command: ${options.command}`,
233
+ );
234
+ }
235
+ },
236
+ };
237
+
238
+ const blogAutomationRuns = {
239
+ async execute(options) {
240
+ const BlogAutomationRun = mongoose.model("BlogAutomationRun");
241
+ switch (options.command) {
242
+ case "list": {
243
+ const limit = parseInt(options.value) || 50;
244
+ const runs = await BlogAutomationRun.find()
245
+ .sort({ createdAt: -1 })
246
+ .limit(limit)
247
+ .lean();
248
+ return { items: runs, count: runs.length };
249
+ }
250
+ case "get": {
251
+ if (!options.id) throw new Error("Automation run ID is required");
252
+ const run = await BlogAutomationRun.findById(options.id).lean();
253
+ if (!run) throw new Error("Automation run not found");
254
+ return run;
255
+ }
256
+ case "clear": {
257
+ const result = await BlogAutomationRun.deleteMany({});
258
+ return { success: true, deletedCount: result.deletedCount };
259
+ }
260
+ default:
261
+ throw new Error(
262
+ `Unknown blog-automation-runs command: ${options.command}`,
263
+ );
264
+ }
265
+ },
266
+ };
267
+
268
+ const cronExecutions = {
269
+ async execute(options) {
270
+ const CronExecution = mongoose.model("CronExecution");
271
+ switch (options.command) {
272
+ case "list": {
273
+ const limit = parseInt(options.value) || 50;
274
+ const executions = await CronExecution.find()
275
+ .sort({ createdAt: -1 })
276
+ .limit(limit)
277
+ .lean();
278
+ return { items: executions, count: executions.length };
279
+ }
280
+ case "clear": {
281
+ const days = parseInt(options.value) || 7;
282
+ const cutoffDate = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
283
+ const result = await CronExecution.deleteMany({
284
+ createdAt: { $lt: cutoffDate },
285
+ });
286
+ return {
287
+ success: true,
288
+ deletedCount: result.deletedCount,
289
+ olderThan: cutoffDate.toISOString(),
290
+ };
291
+ }
292
+ default:
293
+ throw new Error(`Unknown cron-executions command: ${options.command}`);
294
+ }
295
+ },
296
+ };
297
+
298
+ const workflowExecutions = {
299
+ async execute(options) {
300
+ const WorkflowExecution = mongoose.model("WorkflowExecution");
301
+ switch (options.command) {
302
+ case "list": {
303
+ const limit = parseInt(options.value) || 50;
304
+ const executions = await WorkflowExecution.find()
305
+ .sort({ createdAt: -1 })
306
+ .limit(limit)
307
+ .lean();
308
+ return { items: executions, count: executions.length };
309
+ }
310
+ case "get": {
311
+ if (!options.id) throw new Error("Workflow execution ID is required");
312
+ const execution = await WorkflowExecution.findById(options.id).lean();
313
+ if (!execution) throw new Error("Workflow execution not found");
314
+ return execution;
315
+ }
316
+ case "clear": {
317
+ const result = await WorkflowExecution.deleteMany({});
318
+ return { success: true, deletedCount: result.deletedCount };
319
+ }
320
+ default:
321
+ throw new Error(
322
+ `Unknown workflow-executions command: ${options.command}`,
323
+ );
324
+ }
325
+ },
326
+ };
327
+
328
+ const scriptRuns = {
329
+ async execute(options) {
330
+ const ScriptRun = mongoose.model("ScriptRun");
331
+ switch (options.command) {
332
+ case "list": {
333
+ const limit = parseInt(options.value) || 50;
334
+ const runs = await ScriptRun.find()
335
+ .sort({ createdAt: -1 })
336
+ .limit(limit)
337
+ .lean();
338
+ return { items: runs, count: runs.length };
339
+ }
340
+ case "get": {
341
+ if (!options.id) throw new Error("Script run ID is required");
342
+ const run = await ScriptRun.findById(options.id).lean();
343
+ if (!run) throw new Error("Script run not found");
344
+ return run;
345
+ }
346
+ case "clear": {
347
+ const result = await ScriptRun.deleteMany({});
348
+ return { success: true, deletedCount: result.deletedCount };
349
+ }
350
+ default:
351
+ throw new Error(`Unknown script-runs command: ${options.command}`);
352
+ }
353
+ },
354
+ };
355
+
356
+ module.exports = {
357
+ experiments,
358
+ experimentAssignments,
359
+ rateLimits,
360
+ demoProjects,
361
+ demoSteps,
362
+ blogAutomationLocks,
363
+ blogAutomationRuns,
364
+ cronExecutions,
365
+ workflowExecutions,
366
+ scriptRuns,
367
+ };
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Health & Metrics: health-incidents, health-attempts, error-aggregates, metric-buckets
5
+ */
6
+
7
+ const mongoose = require("mongoose");
8
+
9
+ const healthIncidents = {
10
+ async execute(options) {
11
+ const HealthIncident = mongoose.model("HealthIncident");
12
+ switch (options.command) {
13
+ case "list": {
14
+ const incidents = await HealthIncident.find()
15
+ .sort({ createdAt: -1 })
16
+ .lean();
17
+ return { items: incidents, count: incidents.length };
18
+ }
19
+ case "clear": {
20
+ const result = await HealthIncident.deleteMany({});
21
+ return { success: true, deletedCount: result.deletedCount };
22
+ }
23
+ default:
24
+ throw new Error(`Unknown health-incidents command: ${options.command}`);
25
+ }
26
+ },
27
+ };
28
+
29
+ const healthAttempts = {
30
+ async execute(options) {
31
+ const HealthAutoHealAttempt = mongoose.model("HealthAutoHealAttempt");
32
+ switch (options.command) {
33
+ case "list": {
34
+ const attempts = await HealthAutoHealAttempt.find()
35
+ .sort({ createdAt: -1 })
36
+ .lean();
37
+ return { items: attempts, count: attempts.length };
38
+ }
39
+ case "clear": {
40
+ const result = await HealthAutoHealAttempt.deleteMany({});
41
+ return { success: true, deletedCount: result.deletedCount };
42
+ }
43
+ default:
44
+ throw new Error(`Unknown health-attempts command: ${options.command}`);
45
+ }
46
+ },
47
+ };
48
+
49
+ const errorAggregates = {
50
+ async execute(options) {
51
+ const ErrorAggregate = mongoose.model("ErrorAggregate");
52
+ switch (options.command) {
53
+ case "list": {
54
+ const aggregates = await ErrorAggregate.find()
55
+ .sort({ count: -1 })
56
+ .lean();
57
+ return { items: aggregates, count: aggregates.length };
58
+ }
59
+ case "clear": {
60
+ const result = await ErrorAggregate.deleteMany({});
61
+ return { success: true, deletedCount: result.deletedCount };
62
+ }
63
+ default:
64
+ throw new Error(`Unknown error-aggregates command: ${options.command}`);
65
+ }
66
+ },
67
+ };
68
+
69
+ const metricBuckets = {
70
+ async execute(options) {
71
+ const RateLimitMetricBucket = mongoose.model("RateLimitMetricBucket");
72
+ switch (options.command) {
73
+ case "list": {
74
+ const limit = parseInt(options.value) || 50;
75
+ const buckets = await RateLimitMetricBucket.find()
76
+ .sort({ createdAt: -1 })
77
+ .limit(limit)
78
+ .lean();
79
+ return { items: buckets, count: buckets.length };
80
+ }
81
+ case "clear": {
82
+ const result = await RateLimitMetricBucket.deleteMany({});
83
+ return { success: true, deletedCount: result.deletedCount };
84
+ }
85
+ default:
86
+ throw new Error(`Unknown metric-buckets command: ${options.command}`);
87
+ }
88
+ },
89
+ };
90
+
91
+ const virtualEjsFiles = {
92
+ async execute(options) {
93
+ const VirtualEjsFile = mongoose.model("VirtualEjsFile");
94
+ switch (options.command) {
95
+ case "list": {
96
+ const files = await VirtualEjsFile.find().lean();
97
+ return { items: files, count: files.length };
98
+ }
99
+ case "get": {
100
+ if (!options.id) throw new Error("Virtual file ID is required");
101
+ const file = await VirtualEjsFile.findById(options.id).lean();
102
+ if (!file) throw new Error("Virtual file not found");
103
+ return file;
104
+ }
105
+ case "delete": {
106
+ if (!options.id) throw new Error("Virtual file ID is required");
107
+ const file = await VirtualEjsFile.findByIdAndDelete(options.id);
108
+ if (!file) throw new Error("Virtual file not found");
109
+ return { success: true, id: options.id };
110
+ }
111
+ case "clear": {
112
+ const result = await VirtualEjsFile.deleteMany({});
113
+ return { success: true, deletedCount: result.deletedCount };
114
+ }
115
+ default:
116
+ throw new Error(
117
+ `Unknown virtual-ejs-files command: ${options.command}`,
118
+ );
119
+ }
120
+ },
121
+ };
122
+
123
+ const virtualEjsGroups = {
124
+ async execute(options) {
125
+ const VirtualEjsGroup = mongoose.model("VirtualEjsGroup");
126
+ switch (options.command) {
127
+ case "list": {
128
+ const groups = await VirtualEjsGroup.find().lean();
129
+ return { items: groups, count: groups.length };
130
+ }
131
+ case "delete": {
132
+ if (!options.id) throw new Error("Virtual group ID is required");
133
+ const group = await VirtualEjsGroup.findByIdAndDelete(options.id);
134
+ if (!group) throw new Error("Virtual group not found");
135
+ return { success: true, id: options.id };
136
+ }
137
+ default:
138
+ throw new Error(
139
+ `Unknown virtual-ejs-groups command: ${options.command}`,
140
+ );
141
+ }
142
+ },
143
+ };
144
+
145
+ module.exports = {
146
+ healthIncidents,
147
+ healthAttempts,
148
+ errorAggregates,
149
+ metricBuckets,
150
+ virtualEjsFiles,
151
+ virtualEjsGroups,
152
+ };
@@ -0,0 +1,182 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Integration resources: telegram, webhooks, stripe-items, stripe-events, external-dbs
5
+ */
6
+
7
+ const mongoose = require('mongoose');
8
+
9
+ const telegram = {
10
+ async execute(options) {
11
+ const TelegramBot = mongoose.model('TelegramBot');
12
+ switch (options.command) {
13
+ case 'list': {
14
+ const bots = await TelegramBot.find().lean();
15
+ return { items: bots, count: bots.length };
16
+ }
17
+ case 'get': {
18
+ if (!options.id) throw new Error('Bot ID is required');
19
+ const bot = await TelegramBot.findById(options.id).lean();
20
+ if (!bot) throw new Error('Bot not found');
21
+ return bot;
22
+ }
23
+ case 'create': {
24
+ if (!options.name) throw new Error('--name is required');
25
+ if (!options.key) throw new Error('--key (bot token) is required');
26
+ const bot = await TelegramBot.create({ name: options.name, token: options.key, enabled: true });
27
+ return bot;
28
+ }
29
+ case 'delete': {
30
+ if (!options.id) throw new Error('Bot ID is required');
31
+ const bot = await TelegramBot.findByIdAndDelete(options.id);
32
+ if (!bot) throw new Error('Bot not found');
33
+ return { success: true, id: options.id };
34
+ }
35
+ case 'enable': {
36
+ if (!options.id) throw new Error('Bot ID is required');
37
+ const bot = await TelegramBot.findByIdAndUpdate(options.id, { enabled: true }, { new: true });
38
+ if (!bot) throw new Error('Bot not found');
39
+ return bot;
40
+ }
41
+ case 'disable': {
42
+ if (!options.id) throw new Error('Bot ID is required');
43
+ const bot = await TelegramBot.findByIdAndUpdate(options.id, { enabled: false }, { new: true });
44
+ if (!bot) throw new Error('Bot not found');
45
+ return bot;
46
+ }
47
+ default:
48
+ throw new Error(`Unknown telegram command: ${options.command}`);
49
+ }
50
+ },
51
+ };
52
+
53
+ const webhooks = {
54
+ async execute(options) {
55
+ const Webhook = mongoose.model('Webhook');
56
+ switch (options.command) {
57
+ case 'list': {
58
+ const webhooks = await Webhook.find().lean();
59
+ return { items: webhooks, count: webhooks.length };
60
+ }
61
+ case 'get': {
62
+ if (!options.id) throw new Error('Webhook ID is required');
63
+ const webhook = await Webhook.findById(options.id).lean();
64
+ if (!webhook) throw new Error('Webhook not found');
65
+ return webhook;
66
+ }
67
+ case 'create': {
68
+ if (!options.name) throw new Error('--name is required');
69
+ if (!options.key) throw new Error('--key (URL) is required');
70
+ const webhook = await Webhook.create({ name: options.name, url: options.key, enabled: true });
71
+ return webhook;
72
+ }
73
+ case 'delete': {
74
+ if (!options.id) throw new Error('Webhook ID is required');
75
+ const webhook = await Webhook.findByIdAndDelete(options.id);
76
+ if (!webhook) throw new Error('Webhook not found');
77
+ return { success: true, id: options.id };
78
+ }
79
+ case 'enable': {
80
+ if (!options.id) throw new Error('Webhook ID is required');
81
+ const webhook = await Webhook.findByIdAndUpdate(options.id, { enabled: true }, { new: true });
82
+ if (!webhook) throw new Error('Webhook not found');
83
+ return webhook;
84
+ }
85
+ case 'disable': {
86
+ if (!options.id) throw new Error('Webhook ID is required');
87
+ const webhook = await Webhook.findByIdAndUpdate(options.id, { enabled: false }, { new: true });
88
+ if (!webhook) throw new Error('Webhook not found');
89
+ return webhook;
90
+ }
91
+ default:
92
+ throw new Error(`Unknown webhooks command: ${options.command}`);
93
+ }
94
+ },
95
+ };
96
+
97
+ const stripeItems = {
98
+ async execute(options) {
99
+ const StripeCatalogItem = mongoose.model('StripeCatalogItem');
100
+ switch (options.command) {
101
+ case 'list': {
102
+ const items = await StripeCatalogItem.find().lean();
103
+ return { items, count: items.length };
104
+ }
105
+ case 'get': {
106
+ if (!options.id) throw new Error('Stripe item ID is required');
107
+ const item = await StripeCatalogItem.findById(options.id).lean();
108
+ if (!item) throw new Error('Stripe item not found');
109
+ return item;
110
+ }
111
+ case 'clear': {
112
+ const result = await StripeCatalogItem.deleteMany({});
113
+ return { success: true, deletedCount: result.deletedCount };
114
+ }
115
+ default:
116
+ throw new Error(`Unknown stripe-items command: ${options.command}`);
117
+ }
118
+ },
119
+ };
120
+
121
+ const stripeEvents = {
122
+ async execute(options) {
123
+ const StripeWebhookEvent = mongoose.model('StripeWebhookEvent');
124
+ switch (options.command) {
125
+ case 'list': {
126
+ const limit = parseInt(options.value) || 50;
127
+ const events = await StripeWebhookEvent.find().sort({ createdAt: -1 }).limit(limit).lean();
128
+ return { items: events, count: events.length };
129
+ }
130
+ case 'get': {
131
+ if (!options.id) throw new Error('Stripe event ID is required');
132
+ const event = await StripeWebhookEvent.findById(options.id).lean();
133
+ if (!event) throw new Error('Stripe event not found');
134
+ return event;
135
+ }
136
+ case 'clear': {
137
+ const result = await StripeWebhookEvent.deleteMany({});
138
+ return { success: true, deletedCount: result.deletedCount };
139
+ }
140
+ default:
141
+ throw new Error(`Unknown stripe-events command: ${options.command}`);
142
+ }
143
+ },
144
+ };
145
+
146
+ const externalDbs = {
147
+ async execute(options) {
148
+ const ExternalDbConnection = mongoose.model('ExternalDbConnection');
149
+ switch (options.command) {
150
+ case 'list': {
151
+ const connections = await ExternalDbConnection.find().lean();
152
+ return { items: connections, count: connections.length };
153
+ }
154
+ case 'get': {
155
+ if (!options.id) throw new Error('External DB connection ID is required');
156
+ const connection = await ExternalDbConnection.findById(options.id).lean();
157
+ if (!connection) throw new Error('External DB connection not found');
158
+ return connection;
159
+ }
160
+ case 'create': {
161
+ if (!options.name) throw new Error('--name is required');
162
+ if (!options.key) throw new Error('--key (connection string) is required');
163
+ const connection = await ExternalDbConnection.create({
164
+ name: options.name,
165
+ connectionString: options.key,
166
+ type: options.description || 'mongodb',
167
+ });
168
+ return connection;
169
+ }
170
+ case 'delete': {
171
+ if (!options.id) throw new Error('External DB connection ID is required');
172
+ const connection = await ExternalDbConnection.findByIdAndDelete(options.id);
173
+ if (!connection) throw new Error('External DB connection not found');
174
+ return { success: true, id: options.id };
175
+ }
176
+ default:
177
+ throw new Error(`Unknown external-dbs command: ${options.command}`);
178
+ }
179
+ },
180
+ };
181
+
182
+ module.exports = { telegram, webhooks, stripeItems, stripeEvents, externalDbs };