@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.
- package/.beads/.br_history/issues.20260314_212352_900045509.jsonl +0 -0
- package/.beads/.br_history/issues.20260314_212352_900045509.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_087140743.jsonl +1 -0
- package/.beads/.br_history/issues.20260314_212353_087140743.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_285881504.jsonl +2 -0
- package/.beads/.br_history/issues.20260314_212353_285881504.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_473915419.jsonl +3 -0
- package/.beads/.br_history/issues.20260314_212353_473915419.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_659476307.jsonl +4 -0
- package/.beads/.br_history/issues.20260314_212353_659476307.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212353_869998925.jsonl +5 -0
- package/.beads/.br_history/issues.20260314_212353_869998925.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_212354_054785029.jsonl +6 -0
- package/.beads/.br_history/issues.20260314_212354_054785029.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_175893691.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_175893691.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_338509797.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_338509797.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_515443192.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_515443192.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_676417592.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_676417592.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213336_839182422.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213336_839182422.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213337_004349113.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213337_004349113.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213337_179824080.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213337_179824080.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213701_705075332.jsonl +7 -0
- package/.beads/.br_history/issues.20260314_213701_705075332.jsonl.meta.json +1 -0
- package/.beads/.br_history/issues.20260314_213706_783128702.jsonl +8 -0
- package/.beads/.br_history/issues.20260314_213706_783128702.jsonl.meta.json +1 -0
- package/.beads/config.yaml +4 -0
- package/.beads/issues.jsonl +8 -0
- package/.beads/metadata.json +4 -0
- package/.env.example +8 -0
- package/autochangelog/.env.example +36 -0
- package/autochangelog/README.md +412 -0
- package/autochangelog/config/database.js +27 -0
- package/autochangelog/package.json +47 -0
- package/autochangelog/public/landing.html +581 -0
- package/autochangelog/server.js +104 -0
- package/autochangelog/src/app.js +181 -0
- package/autochangelog/src/config/database.js +26 -0
- package/autochangelog/src/controllers/auth.js +488 -0
- package/autochangelog/src/controllers/changelog.js +682 -0
- package/autochangelog/src/controllers/project.js +580 -0
- package/autochangelog/src/controllers/repository.js +780 -0
- package/autochangelog/src/middleware/auth.js +386 -0
- package/autochangelog/src/models/Changelog.js +443 -0
- package/autochangelog/src/models/Project.js +226 -0
- package/autochangelog/src/models/Repository.js +366 -0
- package/autochangelog/src/models/User.js +223 -0
- package/autochangelog/src/routes/auth.routes.js +32 -0
- package/autochangelog/src/routes/changelog.routes.js +42 -0
- package/autochangelog/src/routes/github-auth.routes.js +102 -0
- package/autochangelog/src/routes/project.routes.js +50 -0
- package/autochangelog/src/routes/repository.routes.js +54 -0
- package/autochangelog/src/services/changelog.js +722 -0
- package/autochangelog/src/services/github.js +243 -0
- package/autochangelog/utils/logger.js +77 -0
- package/autochangelog/views/404.ejs +18 -0
- package/autochangelog/views/dashboard.ejs +596 -0
- package/autochangelog/views/index.ejs +231 -0
- package/autochangelog/views/layouts/main.ejs +44 -0
- package/autochangelog/views/login.ejs +104 -0
- package/autochangelog/views/partials/footer.ejs +20 -0
- package/autochangelog/views/partials/navbar.ejs +51 -0
- package/autochangelog/views/register.ejs +109 -0
- package/autochangelog-cli/README.md +266 -0
- package/autochangelog-cli/bin/autochangelog +120 -0
- package/autochangelog-cli/package.json +46 -0
- package/autochangelog-cli/src/cli/commands/auth.js +291 -0
- package/autochangelog-cli/src/cli/commands/changelog.js +619 -0
- package/autochangelog-cli/src/cli/commands/project.js +427 -0
- package/autochangelog-cli/src/cli/commands/repo.js +557 -0
- package/autochangelog-cli/src/cli/commands/stats.js +706 -0
- package/autochangelog-cli/src/cli/utils/config.js +277 -0
- package/autochangelog-cli/src/cli/utils/errors.js +307 -0
- package/autochangelog-cli/src/cli/utils/logger.js +75 -0
- package/autochangelog-cli/src/cli/utils/output.js +357 -0
- package/package.json +8 -3
- package/plugins/supercli/README.md +108 -0
- package/plugins/supercli/plugin.json +123 -0
- package/server.js +1 -1
- package/src/cli/api.js +380 -0
- package/src/cli/direct/agent-utils.js +61 -0
- package/src/cli/direct/cli-utils.js +112 -0
- package/src/cli/direct/data-seeding.js +307 -0
- package/src/cli/direct/db-admin.js +84 -0
- package/src/cli/direct/db-advanced.js +372 -0
- package/src/cli/direct/db-utils.js +558 -0
- package/src/cli/direct/help.js +195 -0
- package/src/cli/direct/migration.js +107 -0
- package/src/cli/direct/rbac-advanced.js +132 -0
- package/src/cli/direct/resources-additional.js +400 -0
- package/src/cli/direct/resources-cms-advanced.js +173 -0
- package/src/cli/direct/resources-cms.js +247 -0
- package/src/cli/direct/resources-core.js +253 -0
- package/src/cli/direct/resources-execution.js +367 -0
- package/src/cli/direct/resources-health.js +152 -0
- package/src/cli/direct/resources-integrations.js +182 -0
- package/src/cli/direct/resources-logs.js +204 -0
- package/src/cli/direct/resources-org-rbac.js +187 -0
- package/src/cli/direct/resources-system.js +236 -0
- package/src/cli/direct.js +556 -0
- package/src/controllers/admin.controller.js +4 -0
- package/src/controllers/auth.controller.js +148 -1
- package/src/controllers/waitingList.controller.js +130 -1
- package/src/models/RbacRole.js +1 -1
- package/src/models/User.js +39 -5
- package/src/routes/auth.routes.js +6 -0
- package/src/routes/waitingList.routes.js +12 -2
- package/src/routes/waitingListAdmin.routes.js +3 -0
- package/src/services/email.service.js +1 -0
- package/src/services/github.service.js +255 -0
- package/src/services/rateLimiter.service.js +29 -1
- package/src/services/waitingListJson.service.js +32 -3
- 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;
|