@intranefr/superbackend 1.6.7 → 1.7.8

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 +9 -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,619 @@
1
+ const { Command } = require('commander');
2
+ const chalk = require('chalk');
3
+ const fs = require('fs-extra');
4
+ const path = require('path');
5
+ const { output } = require('../utils/output');
6
+ const { handleCliError, validateRequiredArgs, validateDateParams, ERROR_CODES } = require('../utils/errors');
7
+ const { loadConfig, getAuthToken, getCacheDir } = require('../utils/config');
8
+ const { setupLogger } = require('../utils/logger');
9
+
10
+ /**
11
+ * Changelog generation commands for AutoChangelog CLI
12
+ * Handles changelog creation, listing, and management
13
+ */
14
+
15
+ function setupChangelogCommands(program) {
16
+ const changelog = program
17
+ .command('changelog')
18
+ .description('Changelog management');
19
+
20
+ // Generate changelog command
21
+ changelog
22
+ .command('generate')
23
+ .description('Generate changelog for a project')
24
+ .option('--project-id <id>', 'Project ID')
25
+ .option('--repository-id <id>', 'Repository ID')
26
+ .option('--month <month>', 'Month to generate changelog for (1-12)', '0')
27
+ .option('--year <year>', 'Year to generate changelog for', new Date().getFullYear().toString())
28
+ .option('--format <format>', 'Output format (markdown, html, json)', 'markdown')
29
+ .option('--output <path>', 'Output file path')
30
+ .option('--title <title>', 'Custom changelog title')
31
+ .option('--include-merge-commits', 'Include merge commits in changelog')
32
+ .option('--include-drafts', 'Include draft changelogs')
33
+ .action(async (options) => {
34
+ const logger = setupLogger();
35
+ const config = loadConfig();
36
+
37
+ try {
38
+ validateRequiredArgs(options, ['projectId'], output);
39
+
40
+ const token = getAuthToken();
41
+ if (!token) {
42
+ output.error('Not authenticated. Run "autochangelog auth login" first.');
43
+ process.exit(ERROR_CODES.AUTHENTICATION_FAILED);
44
+ }
45
+
46
+ // Validate date parameters
47
+ validateDateParams(options.month, options.year, output);
48
+
49
+ const changelogData = {
50
+ projectId: options.projectId,
51
+ repositoryId: options.repositoryId,
52
+ month: parseInt(options.month),
53
+ year: parseInt(options.year),
54
+ format: options.format,
55
+ includeMergeCommits: options.includeMergeCommits,
56
+ includeDrafts: options.includeDrafts,
57
+ title: options.title,
58
+ };
59
+
60
+ output.progress('Generating changelog...', 0);
61
+
62
+ const result = await generateChangelog(changelogData, token, logger);
63
+
64
+ output.progress('Changelog generation completed', 100);
65
+
66
+ // Handle output
67
+ if (options.output) {
68
+ await saveChangelogToFile(result, options.output, options.format, logger);
69
+ output.success(`Changelog saved to ${options.output}`);
70
+ } else {
71
+ output.output({
72
+ success: true,
73
+ message: 'Changelog generated successfully',
74
+ data: result,
75
+ metadata: {
76
+ timestamp: new Date().toISOString(),
77
+ action: 'changelog_generate',
78
+ format: options.format,
79
+ }
80
+ });
81
+ }
82
+
83
+ } catch (error) {
84
+ handleCliError(error, output);
85
+ }
86
+ });
87
+
88
+ // List changelogs command
89
+ changelog
90
+ .command('list [project-id]')
91
+ .description('List changelogs for a project')
92
+ .option('--repository-id <id>', 'Filter by repository ID')
93
+ .option('--month <month>', 'Filter by month (1-12)')
94
+ .option('--year <year>', 'Filter by year')
95
+ .option('--format <format>', 'Filter by format')
96
+ .option('--limit <limit>', 'Limit number of results', parseInt)
97
+ .option('--offset <offset>', 'Offset for pagination', parseInt)
98
+ .action(async (projectId, options) => {
99
+ const logger = setupLogger();
100
+
101
+ try {
102
+ const token = getAuthToken();
103
+ if (!token) {
104
+ output.error('Not authenticated. Run "autochangelog auth login" first.');
105
+ process.exit(ERROR_CODES.AUTHENTICATION_FAILED);
106
+ }
107
+
108
+ if (!projectId) {
109
+ output.error('Project ID is required');
110
+ process.exit(ERROR_CODES.INVALID_ARGUMENT);
111
+ }
112
+
113
+ const result = await listChangelogs(projectId, options, token, logger);
114
+
115
+ if (output.isJsonMode()) {
116
+ output.output({
117
+ success: true,
118
+ data: result,
119
+ metadata: {
120
+ projectId,
121
+ total: result.length,
122
+ limit: options.limit,
123
+ offset: options.offset || 0,
124
+ }
125
+ });
126
+ } else {
127
+ if (result.length === 0) {
128
+ output.info('No changelogs found for this project');
129
+ return;
130
+ }
131
+
132
+ output.info(`Found ${result.length} changelog(s):`);
133
+ console.log('');
134
+
135
+ const headers = ['ID', 'Title', 'Format', 'Month', 'Year', 'Status', 'Created'];
136
+ const rows = result.map(changelog => [
137
+ changelog.id || changelog._id,
138
+ changelog.title || 'Untitled',
139
+ changelog.format,
140
+ changelog.month,
141
+ changelog.year,
142
+ changelog.status,
143
+ new Date(changelog.createdAt).toLocaleDateString(),
144
+ ]);
145
+
146
+ output.table(headers, rows);
147
+ }
148
+
149
+ } catch (error) {
150
+ handleCliError(error, output);
151
+ }
152
+ });
153
+
154
+ // Get changelog details command
155
+ changelog
156
+ .command('get <id>')
157
+ .description('Get changelog details')
158
+ .option('--content', 'Include full changelog content')
159
+ .action(async (id, options) => {
160
+ const logger = setupLogger();
161
+
162
+ try {
163
+ const token = getAuthToken();
164
+ if (!token) {
165
+ output.error('Not authenticated. Run "autochangelog auth login" first.');
166
+ process.exit(ERROR_CODES.AUTHENTICATION_FAILED);
167
+ }
168
+
169
+ const result = await getChangelog(id, options.content, token, logger);
170
+
171
+ output.output({
172
+ success: true,
173
+ message: 'Changelog details retrieved',
174
+ data: result,
175
+ });
176
+
177
+ } catch (error) {
178
+ handleCliError(error, output);
179
+ }
180
+ });
181
+
182
+ // Share changelog command
183
+ changelog
184
+ .command('share <id>')
185
+ .description('Make changelog publicly accessible')
186
+ .option('--expire <days>', 'Expiration in days (0 for never expire)', parseInt)
187
+ .action(async (id, options) => {
188
+ const logger = setupLogger();
189
+
190
+ try {
191
+ const token = getAuthToken();
192
+ if (!token) {
193
+ output.error('Not authenticated. Run "autochangelog auth login" first.');
194
+ process.exit(ERROR_CODES.AUTHENTICATION_FAILED);
195
+ }
196
+
197
+ const result = await shareChangelog(id, options.expire, token, logger);
198
+
199
+ output.output({
200
+ success: true,
201
+ message: 'Changelog shared successfully',
202
+ data: result,
203
+ });
204
+
205
+ } catch (error) {
206
+ handleCliError(error, output);
207
+ }
208
+ });
209
+
210
+ // Download changelog command
211
+ changelog
212
+ .command('download <id>')
213
+ .description('Download changelog content')
214
+ .option('--output <path>', 'Output file path')
215
+ .action(async (id, options) => {
216
+ const logger = setupLogger();
217
+
218
+ try {
219
+ const token = getAuthToken();
220
+ if (!token) {
221
+ output.error('Not authenticated. Run "autochangelog auth login" first.');
222
+ process.exit(ERROR_CODES.AUTHENTICATION_FAILED);
223
+ }
224
+
225
+ const result = await downloadChangelog(id, token, logger);
226
+
227
+ if (options.output) {
228
+ await saveChangelogToFile(result, options.output, result.format, logger);
229
+ output.success(`Changelog downloaded to ${options.output}`);
230
+ } else {
231
+ // Output content directly
232
+ if (output.isJsonMode()) {
233
+ output.output({
234
+ success: true,
235
+ data: result,
236
+ });
237
+ } else {
238
+ console.log(chalk.green('Changelog Content:'));
239
+ console.log('');
240
+ console.log(result.content);
241
+ }
242
+ }
243
+
244
+ } catch (error) {
245
+ handleCliError(error, output);
246
+ }
247
+ });
248
+
249
+ // Delete changelog command
250
+ changelog
251
+ .command('delete <id>')
252
+ .description('Delete a changelog')
253
+ .option('--force', 'Skip confirmation prompt')
254
+ .action(async (id, options) => {
255
+ const logger = setupLogger();
256
+
257
+ try {
258
+ const token = getAuthToken();
259
+ if (!token) {
260
+ output.error('Not authenticated. Run "autochangelog auth login" first.');
261
+ process.exit(ERROR_CODES.AUTHENTICATION_FAILED);
262
+ }
263
+
264
+ // Confirmation prompt (skip if --force)
265
+ if (!options.force) {
266
+ const inquirer = require('inquirer');
267
+ const answers = await inquirer.prompt([
268
+ {
269
+ type: 'confirm',
270
+ name: 'confirm',
271
+ message: `Are you sure you want to delete changelog ${id}? This action cannot be undone.`,
272
+ default: false,
273
+ }
274
+ ]);
275
+
276
+ if (!answers.confirm) {
277
+ output.info('Operation cancelled');
278
+ return;
279
+ }
280
+ }
281
+
282
+ await deleteChangelog(id, token, logger);
283
+
284
+ output.success(`Changelog ${id} deleted successfully`);
285
+
286
+ } catch (error) {
287
+ handleCliError(error, output);
288
+ }
289
+ });
290
+ }
291
+
292
+ /**
293
+ * Generate changelog for a project
294
+ * @param {Object} changelogData - Changelog generation data
295
+ * @param {string} token - Authentication token
296
+ * @param {Object} logger - Logger instance
297
+ * @returns {Promise<Object>} Generated changelog
298
+ */
299
+ async function generateChangelog(changelogData, token, logger) {
300
+ try {
301
+ const mongoose = require('mongoose');
302
+ const Changelog = require('../../autochangelog/src/models/Changelog');
303
+ const ChangelogService = require('../../autochangelog/src/services/changelog');
304
+
305
+ await mongoose.connect(loadConfig().mongodb_uri);
306
+
307
+ const changelogService = new ChangelogService();
308
+
309
+ // Generate changelog content
310
+ const content = await changelogService.generateChangelog({
311
+ projectId: changelogData.projectId,
312
+ repositoryId: changelogData.repositoryId,
313
+ month: changelogData.month,
314
+ year: changelogData.year,
315
+ format: changelogData.format,
316
+ includeMergeCommits: changelogData.includeMergeCommits,
317
+ includeDrafts: changelogData.includeDrafts,
318
+ });
319
+
320
+ // Create changelog record
321
+ const changelog = new Changelog({
322
+ projectId: changelogData.projectId,
323
+ repositoryId: changelogData.repositoryId,
324
+ title: changelogData.title || `Changelog ${changelogData.month}/${changelogData.year}`,
325
+ content: content,
326
+ format: changelogData.format,
327
+ month: changelogData.month,
328
+ year: changelogData.year,
329
+ status: 'generated',
330
+ public: false,
331
+ createdAt: new Date(),
332
+ updatedAt: new Date(),
333
+ });
334
+
335
+ await changelog.save();
336
+
337
+ logger.info(`Changelog generated: ${changelog.title} (${changelog._id})`);
338
+
339
+ return {
340
+ id: changelog._id,
341
+ projectId: changelog.projectId,
342
+ repositoryId: changelog.repositoryId,
343
+ title: changelog.title,
344
+ content: changelog.content,
345
+ format: changelog.format,
346
+ month: changelog.month,
347
+ year: changelog.year,
348
+ status: changelog.status,
349
+ public: changelog.public,
350
+ createdAt: changelog.createdAt,
351
+ updatedAt: changelog.updatedAt,
352
+ };
353
+
354
+ } catch (error) {
355
+ throw error;
356
+ }
357
+ }
358
+
359
+ /**
360
+ * List changelogs for a project
361
+ * @param {string} projectId - Project ID
362
+ * @param {Object} options - Query options
363
+ * @param {string} token - Authentication token
364
+ * @param {Object} logger - Logger instance
365
+ * @returns {Promise<Array>} List of changelogs
366
+ */
367
+ async function listChangelogs(projectId, options, token, logger) {
368
+ try {
369
+ const mongoose = require('mongoose');
370
+ const Changelog = require('../../autochangelog/src/models/Changelog');
371
+
372
+ await mongoose.connect(loadConfig().mongodb_uri);
373
+
374
+ const query = { projectId };
375
+
376
+ // Apply filters
377
+ if (options.repositoryId) {
378
+ query.repositoryId = options.repositoryId;
379
+ }
380
+ if (options.month) {
381
+ query.month = parseInt(options.month);
382
+ }
383
+ if (options.year) {
384
+ query.year = parseInt(options.year);
385
+ }
386
+ if (options.format) {
387
+ query.format = options.format;
388
+ }
389
+
390
+ const limit = options.limit || 50;
391
+ const offset = options.offset || 0;
392
+
393
+ const changelogs = await Changelog.find(query)
394
+ .sort({ createdAt: -1 })
395
+ .skip(offset)
396
+ .limit(limit)
397
+ .lean();
398
+
399
+ logger.info(`Retrieved ${changelogs.length} changelogs for project ${projectId}`);
400
+
401
+ return changelogs.map(changelog => ({
402
+ id: changelog._id,
403
+ projectId: changelog.projectId,
404
+ repositoryId: changelog.repositoryId,
405
+ title: changelog.title,
406
+ format: changelog.format,
407
+ month: changelog.month,
408
+ year: changelog.year,
409
+ status: changelog.status,
410
+ public: changelog.public,
411
+ createdAt: changelog.createdAt,
412
+ updatedAt: changelog.updatedAt,
413
+ contentLength: changelog.content ? changelog.content.length : 0,
414
+ }));
415
+
416
+ } catch (error) {
417
+ throw error;
418
+ }
419
+ }
420
+
421
+ /**
422
+ * Get changelog details
423
+ * @param {string} id - Changelog ID
424
+ * @param {boolean} includeContent - Include full content
425
+ * @param {string} token - Authentication token
426
+ * @param {Object} logger - Logger instance
427
+ * @returns {Promise<Object>} Changelog details
428
+ */
429
+ async function getChangelog(id, includeContent, token, logger) {
430
+ try {
431
+ const mongoose = require('mongoose');
432
+ const Changelog = require('../../autochangelog/src/models/Changelog');
433
+
434
+ await mongoose.connect(loadConfig().mongodb_uri);
435
+
436
+ const query = includeContent ? {} : { content: 0 };
437
+ const changelog = await Changelog.findById(id, query).lean();
438
+
439
+ if (!changelog) {
440
+ const error = new Error('Changelog not found');
441
+ error.code = ERROR_CODES.RESOURCE_NOT_FOUND;
442
+ error.type = 'resource_not_found';
443
+ throw error;
444
+ }
445
+
446
+ logger.info(`Retrieved changelog details: ${changelog.title}`);
447
+
448
+ const result = {
449
+ id: changelog._id,
450
+ projectId: changelog.projectId,
451
+ repositoryId: changelog.repositoryId,
452
+ title: changelog.title,
453
+ format: changelog.format,
454
+ month: changelog.month,
455
+ year: changelog.year,
456
+ status: changelog.status,
457
+ public: changelog.public,
458
+ createdAt: changelog.createdAt,
459
+ updatedAt: changelog.updatedAt,
460
+ contentLength: changelog.content ? changelog.content.length : 0,
461
+ };
462
+
463
+ if (includeContent) {
464
+ result.content = changelog.content;
465
+ }
466
+
467
+ return result;
468
+
469
+ } catch (error) {
470
+ throw error;
471
+ }
472
+ }
473
+
474
+ /**
475
+ * Share changelog (make public)
476
+ * @param {string} id - Changelog ID
477
+ * @param {number} expireDays - Expiration in days
478
+ * @param {string} token - Authentication token
479
+ * @param {Object} logger - Logger instance
480
+ * @returns {Promise<Object>} Share result
481
+ */
482
+ async function shareChangelog(id, expireDays, token, logger) {
483
+ try {
484
+ const mongoose = require('mongoose');
485
+ const Changelog = require('../../autochangelog/src/models/Changelog');
486
+
487
+ await mongoose.connect(loadConfig().mongodb_uri);
488
+
489
+ const updateData = {
490
+ public: true,
491
+ updatedAt: new Date(),
492
+ };
493
+
494
+ if (expireDays && expireDays > 0) {
495
+ updateData.expiresAt = new Date(Date.now() + (expireDays * 24 * 60 * 60 * 1000));
496
+ }
497
+
498
+ const changelog = await Changelog.findByIdAndUpdate(
499
+ id,
500
+ updateData,
501
+ { new: true, runValidators: true }
502
+ ).lean();
503
+
504
+ if (!changelog) {
505
+ const error = new Error('Changelog not found');
506
+ error.code = ERROR_CODES.RESOURCE_NOT_FOUND;
507
+ error.type = 'resource_not_found';
508
+ throw error;
509
+ }
510
+
511
+ logger.info(`Changelog shared: ${changelog.title}`);
512
+
513
+ return {
514
+ id: changelog._id,
515
+ title: changelog.title,
516
+ public: changelog.public,
517
+ expiresAt: changelog.expiresAt,
518
+ shareUrl: `${loadConfig().api_base_url}/api/changelogs/${changelog._id}/public`,
519
+ createdAt: changelog.createdAt,
520
+ updatedAt: changelog.updatedAt,
521
+ };
522
+
523
+ } catch (error) {
524
+ throw error;
525
+ }
526
+ }
527
+
528
+ /**
529
+ * Download changelog content
530
+ * @param {string} id - Changelog ID
531
+ * @param {string} token - Authentication token
532
+ * @param {Object} logger - Logger instance
533
+ * @returns {Promise<Object>} Download result
534
+ */
535
+ async function downloadChangelog(id, token, logger) {
536
+ try {
537
+ const mongoose = require('mongoose');
538
+ const Changelog = require('../../autochangelog/src/models/Changelog');
539
+
540
+ await mongoose.connect(loadConfig().mongodb_uri);
541
+
542
+ const changelog = await Changelog.findById(id).lean();
543
+
544
+ if (!changelog) {
545
+ const error = new Error('Changelog not found');
546
+ error.code = ERROR_CODES.RESOURCE_NOT_FOUND;
547
+ error.type = 'resource_not_found';
548
+ throw error;
549
+ }
550
+
551
+ logger.info(`Changelog downloaded: ${changelog.title}`);
552
+
553
+ return {
554
+ id: changelog._id,
555
+ title: changelog.title,
556
+ content: changelog.content,
557
+ format: changelog.format,
558
+ month: changelog.month,
559
+ year: changelog.year,
560
+ createdAt: changelog.createdAt,
561
+ };
562
+
563
+ } catch (error) {
564
+ throw error;
565
+ }
566
+ }
567
+
568
+ /**
569
+ * Delete changelog
570
+ * @param {string} id - Changelog ID
571
+ * @param {string} token - Authentication token
572
+ * @param {Object} logger - Logger instance
573
+ */
574
+ async function deleteChangelog(id, token, logger) {
575
+ try {
576
+ const mongoose = require('mongoose');
577
+ const Changelog = require('../../autochangelog/src/models/Changelog');
578
+
579
+ await mongoose.connect(loadConfig().mongodb_uri);
580
+
581
+ const changelog = await Changelog.findByIdAndDelete(id);
582
+
583
+ if (!changelog) {
584
+ const error = new Error('Changelog not found');
585
+ error.code = ERROR_CODES.RESOURCE_NOT_FOUND;
586
+ error.type = 'resource_not_found';
587
+ throw error;
588
+ }
589
+
590
+ logger.info(`Changelog deleted: ${changelog.title}`);
591
+
592
+ } catch (error) {
593
+ throw error;
594
+ }
595
+ }
596
+
597
+ /**
598
+ * Save changelog content to file
599
+ * @param {Object} changelog - Changelog data
600
+ * @param {string} filePath - Output file path
601
+ * @param {string} format - Output format
602
+ * @param {Object} logger - Logger instance
603
+ */
604
+ async function saveChangelogToFile(changelog, filePath, format, logger) {
605
+ try {
606
+ // Ensure directory exists
607
+ const dir = path.dirname(filePath);
608
+ await fs.ensureDir(dir);
609
+
610
+ // Write file
611
+ await fs.writeFile(filePath, changelog.content);
612
+
613
+ logger.info(`Changelog saved to: ${filePath}`);
614
+ } catch (error) {
615
+ throw new Error(`Failed to save changelog to file: ${error.message}`);
616
+ }
617
+ }
618
+
619
+ module.exports = setupChangelogCommands;