@utaba/ucm-mcp-server 1.0.0

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 (80) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +79 -0
  3. package/dist/clients/UcmApiClient.d.ts +53 -0
  4. package/dist/clients/UcmApiClient.js +297 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.js +68 -0
  7. package/dist/interfaces/ILogger.d.ts +8 -0
  8. package/dist/interfaces/ILogger.js +4 -0
  9. package/dist/interfaces/IMcpTool.d.ts +7 -0
  10. package/dist/interfaces/IMcpTool.js +3 -0
  11. package/dist/logging/ConsoleLogger.d.ts +16 -0
  12. package/dist/logging/ConsoleLogger.js +45 -0
  13. package/dist/logging/LoggerFactory.d.ts +9 -0
  14. package/dist/logging/LoggerFactory.js +12 -0
  15. package/dist/server/McpConfig.d.ts +26 -0
  16. package/dist/server/McpConfig.js +93 -0
  17. package/dist/server/McpHandler.d.ts +12 -0
  18. package/dist/server/McpHandler.js +69 -0
  19. package/dist/server/McpServer.d.ts +15 -0
  20. package/dist/server/McpServer.js +49 -0
  21. package/dist/server/ToolRegistry.d.ts +22 -0
  22. package/dist/server/ToolRegistry.js +85 -0
  23. package/dist/tools/artifacts/GetArtifactController.d.ts +34 -0
  24. package/dist/tools/artifacts/GetArtifactController.js +397 -0
  25. package/dist/tools/artifacts/GetLatestController.d.ts +39 -0
  26. package/dist/tools/artifacts/GetLatestController.js +469 -0
  27. package/dist/tools/artifacts/ListVersionsController.d.ts +43 -0
  28. package/dist/tools/artifacts/ListVersionsController.js +530 -0
  29. package/dist/tools/artifacts/PublishArtifactController.d.ts +37 -0
  30. package/dist/tools/artifacts/PublishArtifactController.js +605 -0
  31. package/dist/tools/base/BaseToolController.d.ts +16 -0
  32. package/dist/tools/base/BaseToolController.js +32 -0
  33. package/dist/tools/core/DeleteArtifactTool.d.ts +11 -0
  34. package/dist/tools/core/DeleteArtifactTool.js +82 -0
  35. package/dist/tools/core/GetArtifactTool.d.ts +13 -0
  36. package/dist/tools/core/GetArtifactTool.js +125 -0
  37. package/dist/tools/core/GetArtifactVersionsTool.d.ts +11 -0
  38. package/dist/tools/core/GetArtifactVersionsTool.js +63 -0
  39. package/dist/tools/core/GetChunkTool.d.ts +11 -0
  40. package/dist/tools/core/GetChunkTool.js +56 -0
  41. package/dist/tools/core/ListArtifactsTool.d.ts +11 -0
  42. package/dist/tools/core/ListArtifactsTool.js +84 -0
  43. package/dist/tools/core/PublishArtifactFromFileTool.d.ts +15 -0
  44. package/dist/tools/core/PublishArtifactFromFileTool.js +256 -0
  45. package/dist/tools/core/PublishArtifactTool.d.ts +13 -0
  46. package/dist/tools/core/PublishArtifactTool.js +197 -0
  47. package/dist/tools/discovery/BrowseCategoriesController.d.ts +25 -0
  48. package/dist/tools/discovery/BrowseCategoriesController.js +400 -0
  49. package/dist/tools/discovery/FindByPurposeController.d.ts +12 -0
  50. package/dist/tools/discovery/FindByPurposeController.js +131 -0
  51. package/dist/tools/discovery/ListAuthorsController.d.ts +20 -0
  52. package/dist/tools/discovery/ListAuthorsController.js +274 -0
  53. package/dist/tools/discovery/SearchArtifactsController.d.ts +14 -0
  54. package/dist/tools/discovery/SearchArtifactsController.js +226 -0
  55. package/dist/tools/list/ListNamespaceController.d.ts +1 -0
  56. package/dist/tools/list/ListNamespaceController.js +8 -0
  57. package/dist/tools/navigation/ExploreNamespaceController.d.ts +35 -0
  58. package/dist/tools/navigation/ExploreNamespaceController.js +548 -0
  59. package/dist/tools/utility/AuthorIndexTool.d.ts +11 -0
  60. package/dist/tools/utility/AuthorIndexTool.js +48 -0
  61. package/dist/tools/utility/HealthCheckController.d.ts +11 -0
  62. package/dist/tools/utility/HealthCheckController.js +56 -0
  63. package/dist/tools/utility/ListRepositoriesTool.d.ts +11 -0
  64. package/dist/tools/utility/ListRepositoriesTool.js +70 -0
  65. package/dist/tools/utility/QuickstartTool.d.ts +11 -0
  66. package/dist/tools/utility/QuickstartTool.js +36 -0
  67. package/dist/tools/utility/ValidatePathController.d.ts +30 -0
  68. package/dist/tools/utility/ValidatePathController.js +465 -0
  69. package/dist/types/UcmApiTypes.d.ts +40 -0
  70. package/dist/types/UcmApiTypes.js +4 -0
  71. package/dist/utils/McpErrorHandler.d.ts +25 -0
  72. package/dist/utils/McpErrorHandler.js +67 -0
  73. package/dist/utils/PathUtils.d.ts +61 -0
  74. package/dist/utils/PathUtils.js +178 -0
  75. package/dist/utils/ResponseChunker.d.ts +25 -0
  76. package/dist/utils/ResponseChunker.js +79 -0
  77. package/dist/utils/ValidationUtils.d.ts +10 -0
  78. package/dist/utils/ValidationUtils.js +50 -0
  79. package/package.json +37 -0
  80. package/package.json.backup +37 -0
@@ -0,0 +1,530 @@
1
+ import { BaseToolController } from '../base/BaseToolController.js';
2
+ import { ValidationUtils } from '../../utils/ValidationUtils.js';
3
+ import { parsePath } from '../../utils/PathUtils.js';
4
+ export class ListVersionsController extends BaseToolController {
5
+ constructor(ucmClient, logger) {
6
+ super(ucmClient, logger);
7
+ }
8
+ get name() {
9
+ return 'mcp_ucm_list_versions';
10
+ }
11
+ get description() {
12
+ return 'List all available versions of a UCM artifact with detailed version information and comparison';
13
+ }
14
+ get inputSchema() {
15
+ return {
16
+ type: 'object',
17
+ properties: {
18
+ artifactPath: {
19
+ type: 'string',
20
+ description: 'Artifact path without version (e.g., "utaba/commands/create-user/typescript" or "utaba/commands/create-user")',
21
+ minLength: 5,
22
+ maxLength: 150
23
+ },
24
+ includeMetadata: {
25
+ type: 'boolean',
26
+ default: false,
27
+ description: 'Include detailed metadata for each version'
28
+ },
29
+ includeChangeSummary: {
30
+ type: 'boolean',
31
+ default: true,
32
+ description: 'Include summary of changes between versions'
33
+ },
34
+ includeStats: {
35
+ type: 'boolean',
36
+ default: false,
37
+ description: 'Include download and usage statistics for each version'
38
+ },
39
+ sortBy: {
40
+ type: 'string',
41
+ enum: ['version', 'date', 'downloads', 'rating'],
42
+ default: 'version',
43
+ description: 'Sort versions by specified criteria'
44
+ },
45
+ sortOrder: {
46
+ type: 'string',
47
+ enum: ['asc', 'desc'],
48
+ default: 'desc',
49
+ description: 'Sort order (newest first by default)'
50
+ },
51
+ limit: {
52
+ type: 'number',
53
+ minimum: 1,
54
+ maximum: 100,
55
+ default: 20,
56
+ description: 'Maximum number of versions to return'
57
+ },
58
+ sinceVersion: {
59
+ type: 'string',
60
+ pattern: '^[0-9]+\\.[0-9]+\\.[0-9]+',
61
+ description: 'Only show versions newer than this version'
62
+ },
63
+ versionPattern: {
64
+ type: 'string',
65
+ description: 'Filter versions matching this pattern (e.g., "1.*", "*.0.0")'
66
+ }
67
+ },
68
+ required: ['artifactPath']
69
+ };
70
+ }
71
+ async handleExecute(params) {
72
+ const { artifactPath, includeMetadata = false, includeChangeSummary = true, includeStats = false, sortBy = 'version', sortOrder = 'desc', limit = 20, sinceVersion, versionPattern } = params;
73
+ // Validate the artifact path (should not include version)
74
+ this.validateBasePath(artifactPath);
75
+ if (sinceVersion) {
76
+ ValidationUtils.validateVersion(sinceVersion);
77
+ }
78
+ this.logger.debug('ListVersionsController', `Listing versions for: ${artifactPath}`);
79
+ try {
80
+ // Parse the path to get component parts
81
+ const parsed = parsePath(artifactPath);
82
+ // Get all versions from UCM API
83
+ const allVersions = await this.ucmClient.getArtifactVersions(parsed.author, parsed.category, parsed.subcategory);
84
+ if (!allVersions || allVersions.length === 0) {
85
+ return {
86
+ artifactPath,
87
+ versions: [],
88
+ totalVersions: 0,
89
+ message: 'No versions found for this artifact'
90
+ };
91
+ }
92
+ // Apply filters
93
+ let filteredVersions = allVersions;
94
+ if (sinceVersion) {
95
+ filteredVersions = this.filterVersionsSince(filteredVersions, sinceVersion);
96
+ }
97
+ if (versionPattern) {
98
+ filteredVersions = this.filterVersionsByPattern(filteredVersions, versionPattern);
99
+ }
100
+ // Process and enrich version data
101
+ const enrichedVersions = await this.enrichVersionData(filteredVersions, { includeMetadata, includeChangeSummary, includeStats });
102
+ // Sort versions
103
+ const sortedVersions = this.sortVersions(enrichedVersions, sortBy, sortOrder);
104
+ // Apply limit
105
+ const limitedVersions = sortedVersions.slice(0, limit);
106
+ // Build response
107
+ const response = {
108
+ artifactPath,
109
+ versions: limitedVersions,
110
+ pagination: {
111
+ total: filteredVersions.length,
112
+ returned: limitedVersions.length,
113
+ hasMore: filteredVersions.length > limit
114
+ },
115
+ sorting: {
116
+ sortBy,
117
+ sortOrder
118
+ },
119
+ filters: {
120
+ sinceVersion,
121
+ versionPattern
122
+ },
123
+ summary: this.generateVersionSummary(allVersions, filteredVersions),
124
+ versionAnalysis: this.analyzeVersionHistory(sortedVersions),
125
+ recommendations: this.generateVersionRecommendations(sortedVersions),
126
+ metadata: {
127
+ timestamp: new Date().toISOString(),
128
+ includeMetadata,
129
+ includeChangeSummary,
130
+ includeStats
131
+ }
132
+ };
133
+ this.logger.info('ListVersionsController', `Listed ${limitedVersions.length} versions (${filteredVersions.length} total)`);
134
+ return response;
135
+ }
136
+ catch (error) {
137
+ this.logger.error('ListVersionsController', `Failed to list versions for: ${artifactPath}`, '', error);
138
+ throw error;
139
+ }
140
+ }
141
+ validateBasePath(path) {
142
+ // Ensure path doesn't end with a version number
143
+ const pathParts = path.split('/');
144
+ const lastPart = pathParts[pathParts.length - 1];
145
+ if (lastPart.match(/^[0-9]+\.[0-9]+\.[0-9]+/)) {
146
+ throw this.formatError(new Error('Artifact path should not include version number'));
147
+ }
148
+ if (pathParts.length < 3) {
149
+ throw this.formatError(new Error('Artifact path must include at least author/category/subcategory'));
150
+ }
151
+ }
152
+ filterVersionsSince(versions, sinceVersion) {
153
+ return versions.filter(version => {
154
+ const versionNumber = version.metadata?.version || '0.0.0';
155
+ return this.compareVersions(versionNumber, sinceVersion) > 0;
156
+ });
157
+ }
158
+ filterVersionsByPattern(versions, pattern) {
159
+ const regex = new RegExp(pattern.replace(/\*/g, '.*').replace(/\./g, '\\.'));
160
+ return versions.filter(version => {
161
+ const versionNumber = version.metadata?.version || '0.0.0';
162
+ return regex.test(versionNumber);
163
+ });
164
+ }
165
+ async enrichVersionData(versions, options) {
166
+ const { includeMetadata, includeChangeSummary, includeStats } = options;
167
+ const enrichedVersions = [];
168
+ for (let i = 0; i < versions.length; i++) {
169
+ const version = versions[i];
170
+ const enriched = {
171
+ version: version.metadata?.version || 'unknown',
172
+ path: version.path,
173
+ publishedAt: version.publishedAt,
174
+ lastUpdated: version.lastUpdated,
175
+ contractVersion: version.metadata?.contractVersion,
176
+ // Basic version information
177
+ releaseType: this.determineReleaseType(version.metadata?.version),
178
+ isPreRelease: this.isPreRelease(version.metadata?.version),
179
+ lifecycle: this.determineLifecycleStage(version),
180
+ stability: this.assessVersionStability(version)
181
+ };
182
+ // Include metadata if requested
183
+ if (includeMetadata && version.metadata) {
184
+ enriched.metadata = {
185
+ ...version.metadata,
186
+ qualityScore: this.calculateQualityScore(version.metadata),
187
+ completeness: this.assessMetadataCompleteness(version.metadata)
188
+ };
189
+ }
190
+ // Include change summary if requested
191
+ if (includeChangeSummary) {
192
+ const previousVersion = i < versions.length - 1 ? versions[i + 1] : null;
193
+ enriched.changeSummary = await this.generateChangeSummary(version, previousVersion);
194
+ }
195
+ // Include statistics if requested
196
+ if (includeStats) {
197
+ enriched.statistics = {
198
+ downloadCount: this.getDownloadCount(version),
199
+ rating: this.calculateRating(version),
200
+ usageMetrics: this.getUsageMetrics(version),
201
+ adoptionRate: this.calculateAdoptionRate(version, versions)
202
+ };
203
+ }
204
+ enrichedVersions.push(enriched);
205
+ }
206
+ return enrichedVersions;
207
+ }
208
+ sortVersions(versions, sortBy, sortOrder) {
209
+ return versions.sort((a, b) => {
210
+ let comparison = 0;
211
+ switch (sortBy) {
212
+ case 'version':
213
+ comparison = this.compareVersions(a.version, b.version);
214
+ break;
215
+ case 'date':
216
+ const aDate = new Date(a.publishedAt || 0);
217
+ const bDate = new Date(b.publishedAt || 0);
218
+ comparison = aDate.getTime() - bDate.getTime();
219
+ break;
220
+ case 'downloads':
221
+ const aDownloads = a.statistics?.downloadCount || 0;
222
+ const bDownloads = b.statistics?.downloadCount || 0;
223
+ comparison = aDownloads - bDownloads;
224
+ break;
225
+ case 'rating':
226
+ const aRating = a.statistics?.rating || 0;
227
+ const bRating = b.statistics?.rating || 0;
228
+ comparison = aRating - bRating;
229
+ break;
230
+ default:
231
+ comparison = this.compareVersions(a.version, b.version);
232
+ }
233
+ return sortOrder === 'desc' ? -comparison : comparison;
234
+ });
235
+ }
236
+ generateVersionSummary(allVersions, filteredVersions) {
237
+ const versionNumbers = allVersions.map(v => v.metadata?.version || '0.0.0');
238
+ const latest = this.getLatestVersion(versionNumbers);
239
+ const oldest = this.getOldestVersion(versionNumbers);
240
+ return {
241
+ totalVersions: allVersions.length,
242
+ filteredVersions: filteredVersions.length,
243
+ latestVersion: latest,
244
+ oldestVersion: oldest,
245
+ versionSpan: this.calculateVersionSpan(oldest, latest),
246
+ releaseFrequency: this.calculateReleaseFrequency(allVersions),
247
+ averageTimeBetweenReleases: this.calculateAverageTimeBetweenReleases(allVersions)
248
+ };
249
+ }
250
+ analyzeVersionHistory(versions) {
251
+ const analysis = {
252
+ patterns: {
253
+ majorReleases: 0,
254
+ minorReleases: 0,
255
+ patchReleases: 0,
256
+ preReleases: 0
257
+ },
258
+ trends: {
259
+ releaseVelocity: 'stable',
260
+ breakingChangeFrequency: 'low',
261
+ stabilityTrend: 'improving'
262
+ },
263
+ insights: []
264
+ };
265
+ // Analyze release patterns
266
+ versions.forEach(version => {
267
+ switch (version.releaseType) {
268
+ case 'major':
269
+ analysis.patterns.majorReleases++;
270
+ break;
271
+ case 'minor':
272
+ analysis.patterns.minorReleases++;
273
+ break;
274
+ case 'patch':
275
+ analysis.patterns.patchReleases++;
276
+ break;
277
+ default:
278
+ if (version.isPreRelease) {
279
+ analysis.patterns.preReleases++;
280
+ }
281
+ }
282
+ });
283
+ // Generate insights
284
+ if (analysis.patterns.majorReleases > versions.length * 0.3) {
285
+ analysis.insights.push('Frequent major releases - API may be evolving rapidly');
286
+ }
287
+ if (analysis.patterns.patchReleases > versions.length * 0.6) {
288
+ analysis.insights.push('High patch release frequency - good maintenance practices');
289
+ }
290
+ if (analysis.patterns.preReleases > 0) {
291
+ analysis.insights.push('Pre-release versions available - bleeding edge features');
292
+ }
293
+ return analysis;
294
+ }
295
+ generateVersionRecommendations(versions) {
296
+ const recommendations = {
297
+ recommended: null,
298
+ alternatives: [],
299
+ warnings: []
300
+ };
301
+ if (versions.length === 0) {
302
+ return recommendations;
303
+ }
304
+ // Find recommended version (latest stable)
305
+ const stableVersions = versions.filter(v => !v.isPreRelease && v.stability !== 'experimental');
306
+ if (stableVersions.length > 0) {
307
+ recommendations.recommended = {
308
+ version: stableVersions[0].version,
309
+ reason: 'Latest stable version',
310
+ confidence: 'high'
311
+ };
312
+ }
313
+ else {
314
+ recommendations.recommended = {
315
+ version: versions[0].version,
316
+ reason: 'Latest available version',
317
+ confidence: 'medium'
318
+ };
319
+ }
320
+ // Find alternatives
321
+ const majorVersions = this.groupByMajorVersion(versions);
322
+ for (const [major, versionList] of Object.entries(majorVersions)) {
323
+ if (versionList.length > 0 && versionList[0].version !== recommendations.recommended.version) {
324
+ recommendations.alternatives.push({
325
+ version: versionList[0].version,
326
+ reason: `Latest in v${major}.x series`,
327
+ stability: versionList[0].stability
328
+ });
329
+ }
330
+ }
331
+ // Generate warnings
332
+ const latestVersion = versions[0];
333
+ if (latestVersion?.isPreRelease) {
334
+ recommendations.warnings.push('Latest version is a pre-release - use with caution in production');
335
+ }
336
+ if (latestVersion?.lifecycle === 'legacy') {
337
+ recommendations.warnings.push('This artifact may be deprecated - consider alternatives');
338
+ }
339
+ return recommendations;
340
+ }
341
+ async generateChangeSummary(version, previousVersion) {
342
+ if (!previousVersion) {
343
+ return {
344
+ isFirst: true,
345
+ message: 'Initial version'
346
+ };
347
+ }
348
+ const summary = {
349
+ isFirst: false,
350
+ previousVersion: previousVersion.metadata?.version,
351
+ changeType: this.determineChangeType(previousVersion.metadata?.version, version.metadata?.version),
352
+ timespan: this.calculateTimespan(previousVersion.publishedAt, version.publishedAt),
353
+ breaking: this.hasBreakingChanges(previousVersion, version),
354
+ features: this.detectNewFeatures(previousVersion, version),
355
+ improvements: this.detectImprovements(previousVersion, version),
356
+ fixes: this.detectFixes(previousVersion, version)
357
+ };
358
+ return summary;
359
+ }
360
+ // Helper methods
361
+ compareVersions(version1, version2) {
362
+ const v1Parts = version1.split('.').map(Number);
363
+ const v2Parts = version2.split('.').map(Number);
364
+ for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
365
+ const v1Part = v1Parts[i] || 0;
366
+ const v2Part = v2Parts[i] || 0;
367
+ if (v1Part !== v2Part) {
368
+ return v1Part - v2Part;
369
+ }
370
+ }
371
+ return 0;
372
+ }
373
+ determineReleaseType(version) {
374
+ if (!version)
375
+ return 'unknown';
376
+ const [major, minor, patch] = version.split('.').map(Number);
377
+ if (major > 0 && minor === 0 && patch === 0)
378
+ return 'major';
379
+ if (minor > 0 && patch === 0)
380
+ return 'minor';
381
+ return 'patch';
382
+ }
383
+ isPreRelease(version) {
384
+ return !!(version && (version.includes('alpha') || version.includes('beta') || version.includes('rc')));
385
+ }
386
+ determineLifecycleStage(version) {
387
+ const publishedAt = new Date(version.publishedAt || Date.now());
388
+ const daysSincePublished = (Date.now() - publishedAt.getTime()) / (1000 * 60 * 60 * 24);
389
+ if (daysSincePublished < 30)
390
+ return 'new';
391
+ if (daysSincePublished < 365)
392
+ return 'active';
393
+ if (daysSincePublished < 1095)
394
+ return 'mature';
395
+ return 'legacy';
396
+ }
397
+ assessVersionStability(version) {
398
+ if (this.isPreRelease(version.metadata?.version))
399
+ return 'experimental';
400
+ if (this.determineLifecycleStage(version) === 'new')
401
+ return 'testing';
402
+ return 'stable';
403
+ }
404
+ calculateQualityScore(metadata) {
405
+ let score = 50;
406
+ if (metadata.description?.length > 20)
407
+ score += 20;
408
+ if (metadata.tags?.length > 0)
409
+ score += 10;
410
+ if (metadata.dependencies)
411
+ score += 10;
412
+ if (metadata.contractVersion)
413
+ score += 10;
414
+ return Math.min(score, 100);
415
+ }
416
+ assessMetadataCompleteness(metadata) {
417
+ const fields = ['name', 'description', 'author', 'category', 'version'];
418
+ const presentFields = fields.filter(field => metadata[field]);
419
+ return Math.round((presentFields.length / fields.length) * 100);
420
+ }
421
+ getLatestVersion(versions) {
422
+ return versions.sort((a, b) => this.compareVersions(b, a))[0];
423
+ }
424
+ getOldestVersion(versions) {
425
+ return versions.sort((a, b) => this.compareVersions(a, b))[0];
426
+ }
427
+ calculateVersionSpan(oldest, latest) {
428
+ const comparison = this.compareVersions(latest, oldest);
429
+ if (comparison === 0)
430
+ return 'Single version';
431
+ const [oldMajor] = oldest.split('.').map(Number);
432
+ const [newMajor] = latest.split('.').map(Number);
433
+ const majorSpan = newMajor - oldMajor;
434
+ if (majorSpan > 0)
435
+ return `${majorSpan} major version${majorSpan > 1 ? 's' : ''}`;
436
+ return 'Minor/patch versions';
437
+ }
438
+ calculateReleaseFrequency(versions) {
439
+ if (versions.length < 2)
440
+ return 'insufficient-data';
441
+ const timespan = this.calculateAverageTimeBetweenReleases(versions);
442
+ if (timespan < 30)
443
+ return 'high';
444
+ if (timespan < 90)
445
+ return 'moderate';
446
+ return 'low';
447
+ }
448
+ calculateAverageTimeBetweenReleases(versions) {
449
+ if (versions.length < 2)
450
+ return 0;
451
+ const dates = versions
452
+ .map(v => new Date(v.publishedAt || 0))
453
+ .sort((a, b) => a.getTime() - b.getTime());
454
+ let totalDays = 0;
455
+ for (let i = 1; i < dates.length; i++) {
456
+ totalDays += (dates[i].getTime() - dates[i - 1].getTime()) / (1000 * 60 * 60 * 24);
457
+ }
458
+ return totalDays / (dates.length - 1);
459
+ }
460
+ groupByMajorVersion(versions) {
461
+ const groups = {};
462
+ versions.forEach(version => {
463
+ const [major] = version.version.split('.');
464
+ if (!groups[major])
465
+ groups[major] = [];
466
+ groups[major].push(version);
467
+ });
468
+ return groups;
469
+ }
470
+ determineChangeType(oldVersion, newVersion) {
471
+ const comparison = this.compareVersions(newVersion, oldVersion);
472
+ const [oldMajor, oldMinor] = oldVersion.split('.').map(Number);
473
+ const [newMajor, newMinor] = newVersion.split('.').map(Number);
474
+ if (newMajor > oldMajor)
475
+ return 'major';
476
+ if (newMinor > oldMinor)
477
+ return 'minor';
478
+ return 'patch';
479
+ }
480
+ calculateTimespan(oldDate, newDate) {
481
+ const old = new Date(oldDate || 0);
482
+ const current = new Date(newDate || Date.now());
483
+ const diffMs = current.getTime() - old.getTime();
484
+ const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
485
+ if (diffDays < 1)
486
+ return 'same day';
487
+ if (diffDays < 7)
488
+ return `${diffDays} days`;
489
+ if (diffDays < 30)
490
+ return `${Math.floor(diffDays / 7)} weeks`;
491
+ if (diffDays < 365)
492
+ return `${Math.floor(diffDays / 30)} months`;
493
+ return `${Math.floor(diffDays / 365)} years`;
494
+ }
495
+ // Simulated methods for demo
496
+ hasBreakingChanges(oldVersion, newVersion) {
497
+ return oldVersion.metadata?.contractVersion !== newVersion.metadata?.contractVersion;
498
+ }
499
+ detectNewFeatures(oldVersion, newVersion) {
500
+ const oldTags = oldVersion.metadata?.tags || [];
501
+ const newTags = newVersion.metadata?.tags || [];
502
+ return newTags.filter((tag) => !oldTags.includes(tag));
503
+ }
504
+ detectImprovements(oldVersion, newVersion) {
505
+ const improvements = [];
506
+ if ((newVersion.metadata?.description?.length || 0) > (oldVersion.metadata?.description?.length || 0)) {
507
+ improvements.push('Enhanced documentation');
508
+ }
509
+ return improvements;
510
+ }
511
+ detectFixes(oldVersion, newVersion) {
512
+ return ['General bug fixes and improvements']; // Simulated
513
+ }
514
+ getDownloadCount(version) {
515
+ return Math.floor(Math.random() * 1000); // Simulated
516
+ }
517
+ calculateRating(version) {
518
+ return 3.0 + Math.random() * 2; // Simulated
519
+ }
520
+ getUsageMetrics(version) {
521
+ return {
522
+ activeUsers: Math.floor(Math.random() * 100),
523
+ lastAccessed: new Date().toISOString()
524
+ };
525
+ }
526
+ calculateAdoptionRate(version, allVersions) {
527
+ return Math.random(); // Simulated
528
+ }
529
+ }
530
+ //# sourceMappingURL=ListVersionsController.js.map
@@ -0,0 +1,37 @@
1
+ import { BaseToolController } from '../base/BaseToolController.js';
2
+ import { UcmApiClient } from '../../clients/UcmApiClient.js';
3
+ import { ILogger } from '../../interfaces/ILogger.js';
4
+ export declare class PublishArtifactController extends BaseToolController {
5
+ constructor(ucmClient: UcmApiClient, logger: ILogger);
6
+ get name(): string;
7
+ get description(): string;
8
+ get inputSchema(): any;
9
+ protected handleExecute(params: any): Promise<any>;
10
+ private validatePublishRequest;
11
+ private performPrePublishValidation;
12
+ private handleExistingArtifact;
13
+ private preparePublishData;
14
+ private performPostPublishProcessing;
15
+ private validateContent;
16
+ private performSecurityScan;
17
+ private validateDependencies;
18
+ private performQualityChecks;
19
+ private parseArtifactPath;
20
+ private extractAuthorFromPath;
21
+ private extractCategoryFromPath;
22
+ private extractTechnologyFromMetadata;
23
+ private calculateContentHash;
24
+ private detectContentType;
25
+ private detectLanguageFromContent;
26
+ private isCodeContent;
27
+ private validateSyntax;
28
+ private generateDocumentation;
29
+ private buildViewUrl;
30
+ private buildDownloadUrl;
31
+ private buildApiUrl;
32
+ private indexForSearch;
33
+ private updateCaches;
34
+ private sendMaintainerNotifications;
35
+ private recordPublishAnalytics;
36
+ }
37
+ //# sourceMappingURL=PublishArtifactController.d.ts.map