@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,557 @@
1
+ const { Command } = require('commander');
2
+ const chalk = require('chalk');
3
+ const { output } = require('../utils/output');
4
+ const { handleCliError, validateRequiredArgs, ERROR_CODES } = require('../utils/errors');
5
+ const { loadConfig, getAuthToken } = require('../utils/config');
6
+ const { setupLogger } = require('../utils/logger');
7
+
8
+ /**
9
+ * Repository management commands for AutoChangelog CLI
10
+ * Handles GitHub repository connection and management
11
+ */
12
+
13
+ function setupRepoCommands(program) {
14
+ const repo = program
15
+ .command('repo')
16
+ .description('Repository management');
17
+
18
+ // Connect repository command
19
+ repo
20
+ .command('connect')
21
+ .description('Connect a GitHub repository')
22
+ .option('--project-id <id>', 'Project ID')
23
+ .option('--owner <owner>', 'Repository owner (username or organization)')
24
+ .option('--name <name>', 'Repository name')
25
+ .option('--url <url>', 'Repository URL (alternative to owner/name)')
26
+ .option('--branch <branch>', 'Default branch to track', 'main')
27
+ .action(async (options) => {
28
+ const logger = setupLogger();
29
+ const config = loadConfig();
30
+
31
+ try {
32
+ // Validate required arguments
33
+ if (!options.projectId) {
34
+ output.error('Project ID is required. Use --project-id');
35
+ process.exit(ERROR_CODES.INVALID_ARGUMENT);
36
+ }
37
+
38
+ const token = getAuthToken();
39
+ if (!token) {
40
+ output.error('Not authenticated. Run "autochangelog auth login" first.');
41
+ process.exit(ERROR_CODES.AUTHENTICATION_FAILED);
42
+ }
43
+
44
+ // Parse repository information
45
+ let owner, name;
46
+ if (options.url) {
47
+ const parsed = parseRepoUrl(options.url);
48
+ owner = parsed.owner;
49
+ name = parsed.name;
50
+ } else if (options.owner && options.name) {
51
+ owner = options.owner;
52
+ name = options.name;
53
+ } else {
54
+ output.error('Repository information required. Use --owner and --name, or --url');
55
+ process.exit(ERROR_CODES.INVALID_ARGUMENT);
56
+ }
57
+
58
+ const repoData = {
59
+ projectId: options.projectId,
60
+ owner,
61
+ name,
62
+ defaultBranch: options.branch,
63
+ };
64
+
65
+ const result = await connectRepository(repoData, token, logger);
66
+
67
+ output.output({
68
+ success: true,
69
+ message: 'Repository connected successfully',
70
+ data: result,
71
+ metadata: {
72
+ timestamp: new Date().toISOString(),
73
+ action: 'repository_connect',
74
+ }
75
+ });
76
+
77
+ } catch (error) {
78
+ handleCliError(error, output);
79
+ }
80
+ });
81
+
82
+ // List repositories command
83
+ repo
84
+ .command('list [project-id]')
85
+ .description('List repositories for a project')
86
+ .option('--limit <limit>', 'Limit number of results', parseInt)
87
+ .option('--offset <offset>', 'Offset for pagination', parseInt)
88
+ .action(async (projectId, options) => {
89
+ const logger = setupLogger();
90
+
91
+ try {
92
+ const token = getAuthToken();
93
+ if (!token) {
94
+ output.error('Not authenticated. Run "autochangelog auth login" first.');
95
+ process.exit(ERROR_CODES.AUTHENTICATION_FAILED);
96
+ }
97
+
98
+ if (!projectId) {
99
+ output.error('Project ID is required');
100
+ process.exit(ERROR_CODES.INVALID_ARGUMENT);
101
+ }
102
+
103
+ const result = await listRepositories(projectId, options, token, logger);
104
+
105
+ if (output.isJsonMode()) {
106
+ output.output({
107
+ success: true,
108
+ data: result,
109
+ metadata: {
110
+ projectId,
111
+ total: result.length,
112
+ limit: options.limit,
113
+ offset: options.offset || 0,
114
+ }
115
+ });
116
+ } else {
117
+ if (result.length === 0) {
118
+ output.info('No repositories found for this project');
119
+ return;
120
+ }
121
+
122
+ output.info(`Found ${result.length} repository(ies):`);
123
+ console.log('');
124
+
125
+ const headers = ['ID', 'Owner', 'Name', 'Branch', 'Status', 'Last Sync'];
126
+ const rows = result.map(repo => [
127
+ repo.id || repo._id,
128
+ repo.owner,
129
+ repo.name,
130
+ repo.defaultBranch,
131
+ repo.status || 'active',
132
+ repo.lastSync ? new Date(repo.lastSync).toLocaleDateString() : 'Never',
133
+ ]);
134
+
135
+ output.table(headers, rows);
136
+ }
137
+
138
+ } catch (error) {
139
+ handleCliError(error, output);
140
+ }
141
+ });
142
+
143
+ // Sync repository command
144
+ repo
145
+ .command('sync <id>')
146
+ .description('Sync repository data from GitHub')
147
+ .option('--force', 'Force full resync')
148
+ .action(async (id, options) => {
149
+ const logger = setupLogger();
150
+
151
+ try {
152
+ const token = getAuthToken();
153
+ if (!token) {
154
+ output.error('Not authenticated. Run "autochangelog auth login" first.');
155
+ process.exit(ERROR_CODES.AUTHENTICATION_FAILED);
156
+ }
157
+
158
+ output.progress('Starting repository sync...', 0);
159
+
160
+ const result = await syncRepository(id, options.force, token, logger);
161
+
162
+ output.progress('Repository sync completed', 100);
163
+
164
+ output.output({
165
+ success: true,
166
+ message: 'Repository synced successfully',
167
+ data: result,
168
+ metadata: {
169
+ timestamp: new Date().toISOString(),
170
+ action: 'repository_sync',
171
+ }
172
+ });
173
+
174
+ } catch (error) {
175
+ handleCliError(error, output);
176
+ }
177
+ });
178
+
179
+ // Validate repository command
180
+ repo
181
+ .command('validate <id>')
182
+ .description('Validate repository access and configuration')
183
+ .action(async (id) => {
184
+ const logger = setupLogger();
185
+
186
+ try {
187
+ const token = getAuthToken();
188
+ if (!token) {
189
+ output.error('Not authenticated. Run "autochangelog auth login" first.');
190
+ process.exit(ERROR_CODES.AUTHENTICATION_FAILED);
191
+ }
192
+
193
+ output.progress('Validating repository access...');
194
+
195
+ const result = await validateRepository(id, token, logger);
196
+
197
+ output.output({
198
+ success: true,
199
+ message: 'Repository validation completed',
200
+ data: result,
201
+ });
202
+
203
+ } catch (error) {
204
+ handleCliError(error, output);
205
+ }
206
+ });
207
+
208
+ // Get repository details command
209
+ repo
210
+ .command('get <id>')
211
+ .description('Get repository details')
212
+ .action(async (id) => {
213
+ const logger = setupLogger();
214
+
215
+ try {
216
+ const token = getAuthToken();
217
+ if (!token) {
218
+ output.error('Not authenticated. Run "autochangelog auth login" first.');
219
+ process.exit(ERROR_CODES.AUTHENTICATION_FAILED);
220
+ }
221
+
222
+ const result = await getRepository(id, token, logger);
223
+
224
+ output.output({
225
+ success: true,
226
+ message: 'Repository details retrieved',
227
+ data: result,
228
+ });
229
+
230
+ } catch (error) {
231
+ handleCliError(error, output);
232
+ }
233
+ });
234
+ }
235
+
236
+ /**
237
+ * Connect a GitHub repository
238
+ * @param {Object} repoData - Repository data
239
+ * @param {string} token - Authentication token
240
+ * @param {Object} logger - Logger instance
241
+ * @returns {Promise<Object>} Connected repository
242
+ */
243
+ async function connectRepository(repoData, token, logger) {
244
+ try {
245
+ const mongoose = require('mongoose');
246
+ const Repository = require('../../autochangelog/src/models/Repository');
247
+ const GitHubService = require('../../autochangelog/src/services/github');
248
+
249
+ await mongoose.connect(loadConfig().mongodb_uri);
250
+
251
+ // Validate repository access on GitHub
252
+ const githubService = new GitHubService(token);
253
+ const repoInfo = await githubService.getRepository(repoData.owner, repoData.name);
254
+
255
+ if (!repoInfo) {
256
+ const error = new Error('Repository not found or access denied');
257
+ error.code = ERROR_CODES.PERMISSION_DENIED;
258
+ error.type = 'permission_denied';
259
+ throw error;
260
+ }
261
+
262
+ // Create repository record
263
+ const repository = new Repository({
264
+ projectId: repoData.projectId,
265
+ owner: repoData.owner,
266
+ name: repoData.name,
267
+ fullName: repoInfo.full_name,
268
+ defaultBranch: repoData.defaultBranch || 'main',
269
+ githubId: repoInfo.id,
270
+ private: repoInfo.private,
271
+ description: repoInfo.description,
272
+ url: repoInfo.html_url,
273
+ cloneUrl: repoInfo.clone_url,
274
+ status: 'active',
275
+ lastSync: new Date(),
276
+ createdAt: new Date(),
277
+ updatedAt: new Date(),
278
+ });
279
+
280
+ await repository.save();
281
+
282
+ logger.info(`Repository connected: ${repoInfo.full_name} (${repository._id})`);
283
+
284
+ return {
285
+ id: repository._id,
286
+ owner: repository.owner,
287
+ name: repository.name,
288
+ fullName: repository.fullName,
289
+ defaultBranch: repository.defaultBranch,
290
+ status: repository.status,
291
+ createdAt: repository.createdAt,
292
+ updatedAt: repository.updatedAt,
293
+ githubInfo: {
294
+ id: repoInfo.id,
295
+ private: repoInfo.private,
296
+ description: repoInfo.description,
297
+ url: repoInfo.html_url,
298
+ }
299
+ };
300
+
301
+ } catch (error) {
302
+ throw error;
303
+ }
304
+ }
305
+
306
+ /**
307
+ * List repositories for a project
308
+ * @param {string} projectId - Project ID
309
+ * @param {Object} options - Query options
310
+ * @param {string} token - Authentication token
311
+ * @param {Object} logger - Logger instance
312
+ * @returns {Promise<Array>} List of repositories
313
+ */
314
+ async function listRepositories(projectId, options, token, logger) {
315
+ try {
316
+ const mongoose = require('mongoose');
317
+ const Repository = require('../../autochangelog/src/models/Repository');
318
+
319
+ await mongoose.connect(loadConfig().mongodb_uri);
320
+
321
+ const query = { projectId };
322
+ const limit = options.limit || 50;
323
+ const offset = options.offset || 0;
324
+
325
+ const repositories = await Repository.find(query)
326
+ .sort({ createdAt: -1 })
327
+ .skip(offset)
328
+ .limit(limit)
329
+ .lean();
330
+
331
+ logger.info(`Retrieved ${repositories.length} repositories for project ${projectId}`);
332
+
333
+ return repositories.map(repo => ({
334
+ id: repo._id,
335
+ owner: repo.owner,
336
+ name: repo.name,
337
+ fullName: repo.fullName,
338
+ defaultBranch: repo.defaultBranch,
339
+ status: repo.status,
340
+ private: repo.private,
341
+ description: repo.description,
342
+ url: repo.url,
343
+ lastSync: repo.lastSync,
344
+ createdAt: repo.createdAt,
345
+ updatedAt: repo.updatedAt,
346
+ }));
347
+
348
+ } catch (error) {
349
+ throw error;
350
+ }
351
+ }
352
+
353
+ /**
354
+ * Sync repository data from GitHub
355
+ * @param {string} id - Repository ID
356
+ * @param {boolean} force - Force full resync
357
+ * @param {string} token - Authentication token
358
+ * @param {Object} logger - Logger instance
359
+ * @returns {Promise<Object>} Sync result
360
+ */
361
+ async function syncRepository(id, force, token, logger) {
362
+ try {
363
+ const mongoose = require('mongoose');
364
+ const Repository = require('../../autochangelog/src/models/Repository');
365
+ const GitHubService = require('../../autochangelog/src/services/github');
366
+
367
+ await mongoose.connect(loadConfig().mongodb_uri);
368
+
369
+ const repository = await Repository.findById(id);
370
+ if (!repository) {
371
+ const error = new Error('Repository not found');
372
+ error.code = ERROR_CODES.RESOURCE_NOT_FOUND;
373
+ error.type = 'resource_not_found';
374
+ throw error;
375
+ }
376
+
377
+ const githubService = new GitHubService(token);
378
+
379
+ // Update last sync time
380
+ repository.lastSync = new Date();
381
+ repository.updatedAt = new Date();
382
+ await repository.save();
383
+
384
+ // Sync repository info
385
+ const repoInfo = await githubService.getRepository(repository.owner, repository.name);
386
+
387
+ if (repoInfo) {
388
+ repository.fullName = repoInfo.full_name;
389
+ repository.private = repoInfo.private;
390
+ repository.description = repoInfo.description;
391
+ repository.url = repoInfo.html_url;
392
+ repository.cloneUrl = repoInfo.clone_url;
393
+ repository.updatedAt = new Date();
394
+ await repository.save();
395
+ }
396
+
397
+ logger.info(`Repository synced: ${repository.fullName}`);
398
+
399
+ return {
400
+ id: repository._id,
401
+ fullName: repository.fullName,
402
+ lastSync: repository.lastSync,
403
+ status: 'synced',
404
+ changes: {
405
+ description: repoInfo ? repoInfo.description : repository.description,
406
+ private: repoInfo ? repoInfo.private : repository.private,
407
+ }
408
+ };
409
+
410
+ } catch (error) {
411
+ throw error;
412
+ }
413
+ }
414
+
415
+ /**
416
+ * Validate repository access and configuration
417
+ * @param {string} id - Repository ID
418
+ * @param {string} token - Authentication token
419
+ * @param {Object} logger - Logger instance
420
+ * @returns {Promise<Object>} Validation result
421
+ */
422
+ async function validateRepository(id, token, logger) {
423
+ try {
424
+ const mongoose = require('mongoose');
425
+ const Repository = require('../../autochangelog/src/models/Repository');
426
+ const GitHubService = require('../../autochangelog/src/services/github');
427
+
428
+ await mongoose.connect(loadConfig().mongodb_uri);
429
+
430
+ const repository = await Repository.findById(id);
431
+ if (!repository) {
432
+ const error = new Error('Repository not found');
433
+ error.code = ERROR_CODES.RESOURCE_NOT_FOUND;
434
+ error.type = 'resource_not_found';
435
+ throw error;
436
+ }
437
+
438
+ const githubService = new GitHubService(token);
439
+
440
+ // Test repository access
441
+ const repoInfo = await githubService.getRepository(repository.owner, repository.name);
442
+
443
+ const validation = {
444
+ repositoryId: repository._id,
445
+ fullName: repository.fullName,
446
+ access: {
447
+ granted: !!repoInfo,
448
+ message: repoInfo ? 'Access granted' : 'Access denied or repository not found',
449
+ },
450
+ configuration: {
451
+ owner: repository.owner,
452
+ name: repository.name,
453
+ defaultBranch: repository.defaultBranch,
454
+ private: repository.private,
455
+ },
456
+ lastSync: repository.lastSync,
457
+ status: repository.status,
458
+ };
459
+
460
+ if (repoInfo) {
461
+ validation.githubInfo = {
462
+ id: repoInfo.id,
463
+ fullName: repoInfo.full_name,
464
+ private: repoInfo.private,
465
+ description: repoInfo.description,
466
+ defaultBranch: repoInfo.default_branch,
467
+ };
468
+ }
469
+
470
+ logger.info(`Repository validation completed: ${repository.fullName}`);
471
+
472
+ return validation;
473
+
474
+ } catch (error) {
475
+ throw error;
476
+ }
477
+ }
478
+
479
+ /**
480
+ * Get repository details
481
+ * @param {string} id - Repository ID
482
+ * @param {string} token - Authentication token
483
+ * @param {Object} logger - Logger instance
484
+ * @returns {Promise<Object>} Repository details
485
+ */
486
+ async function getRepository(id, token, logger) {
487
+ try {
488
+ const mongoose = require('mongoose');
489
+ const Repository = require('../../autochangelog/src/models/Repository');
490
+
491
+ await mongoose.connect(loadConfig().mongodb_uri);
492
+
493
+ const repository = await Repository.findById(id).lean();
494
+
495
+ if (!repository) {
496
+ const error = new Error('Repository not found');
497
+ error.code = ERROR_CODES.RESOURCE_NOT_FOUND;
498
+ error.type = 'resource_not_found';
499
+ throw error;
500
+ }
501
+
502
+ logger.info(`Retrieved repository details: ${repository.fullName}`);
503
+
504
+ return {
505
+ id: repository._id,
506
+ projectId: repository.projectId,
507
+ owner: repository.owner,
508
+ name: repository.name,
509
+ fullName: repository.fullName,
510
+ defaultBranch: repository.defaultBranch,
511
+ status: repository.status,
512
+ private: repository.private,
513
+ description: repository.description,
514
+ url: repository.url,
515
+ cloneUrl: repository.cloneUrl,
516
+ githubId: repository.githubId,
517
+ lastSync: repository.lastSync,
518
+ createdAt: repository.createdAt,
519
+ updatedAt: repository.updatedAt,
520
+ };
521
+
522
+ } catch (error) {
523
+ throw error;
524
+ }
525
+ }
526
+
527
+ /**
528
+ * Parse repository URL to extract owner and name
529
+ * @param {string} url - Repository URL
530
+ * @returns {Object} Parsed owner and name
531
+ */
532
+ function parseRepoUrl(url) {
533
+ try {
534
+ // Handle various GitHub URL formats
535
+ const patterns = [
536
+ /^https?:\/\/github\.com\/([^/]+)\/([^/]+)(?:\.git)?$/i,
537
+ /^git@github\.com:([^/]+)\/([^/]+)(?:\.git)?$/i,
538
+ /^github:([^/]+)\/([^/]+)$/i,
539
+ ];
540
+
541
+ for (const pattern of patterns) {
542
+ const match = url.match(pattern);
543
+ if (match) {
544
+ return {
545
+ owner: match[1],
546
+ name: match[2],
547
+ };
548
+ }
549
+ }
550
+
551
+ throw new Error('Invalid repository URL format');
552
+ } catch (error) {
553
+ throw new Error(`Failed to parse repository URL: ${error.message}`);
554
+ }
555
+ }
556
+
557
+ module.exports = setupRepoCommands;