@adminide-stack/marketplace-module-server 12.0.4-alpha.92 → 13.0.1-alpha.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.
- package/Readme.md +321 -0
- package/lib/containers/module.d.ts +8 -0
- package/lib/containers/module.d.ts.map +1 -1
- package/lib/containers/module.js +16 -5
- package/lib/containers/module.js.map +1 -1
- package/lib/dataloaders/index.d.ts +2 -0
- package/lib/dataloaders/index.d.ts.map +1 -0
- package/lib/dataloaders/publisher-data-loader.d.ts +6 -0
- package/lib/dataloaders/publisher-data-loader.d.ts.map +1 -0
- package/lib/demo/test-graphql-examples.d.ts +73 -0
- package/lib/demo/test-graphql-examples.d.ts.map +1 -0
- package/lib/graphql/resolvers/form-templates-resolver.d.ts +220 -0
- package/lib/graphql/resolvers/form-templates-resolver.d.ts.map +1 -0
- package/lib/graphql/resolvers/form-templates-resolver.js +170 -0
- package/lib/graphql/resolvers/form-templates-resolver.js.map +1 -0
- package/lib/graphql/resolvers/gallery-resolver.d.ts +15 -0
- package/lib/graphql/resolvers/gallery-resolver.d.ts.map +1 -0
- package/lib/graphql/resolvers/gallery-resolver.js +35 -0
- package/lib/graphql/resolvers/gallery-resolver.js.map +1 -0
- package/lib/graphql/resolvers/index.d.ts +247 -1
- package/lib/graphql/resolvers/index.d.ts.map +1 -1
- package/lib/graphql/resolvers/index.js +1 -0
- package/lib/graphql/resolvers/index.js.map +1 -0
- package/lib/graphql/resolvers/installed-extension-resolver.d.ts +5 -0
- package/lib/graphql/resolvers/installed-extension-resolver.d.ts.map +1 -0
- package/lib/graphql/resolvers/installed-extension-resolver.js +309 -0
- package/lib/graphql/resolvers/installed-extension-resolver.js.map +1 -0
- package/lib/graphql/resolvers/marketplace-form-resolver.d.ts +13 -0
- package/lib/graphql/resolvers/marketplace-form-resolver.d.ts.map +1 -0
- package/lib/graphql/resolvers/marketplace-form-resolver.js +90 -0
- package/lib/graphql/resolvers/marketplace-form-resolver.js.map +1 -0
- package/lib/graphql/resolvers/publisher-analytics-resolver.d.ts +14 -0
- package/lib/graphql/resolvers/publisher-analytics-resolver.d.ts.map +1 -0
- package/lib/graphql/resolvers/publisher-analytics-resolver.js +221 -0
- package/lib/graphql/resolvers/publisher-analytics-resolver.js.map +1 -0
- package/lib/graphql/resolvers/publisher-resolver.d.ts +5 -0
- package/lib/graphql/resolvers/publisher-resolver.d.ts.map +1 -0
- package/lib/graphql/resolvers/publisher-resolver.js +183 -0
- package/lib/graphql/resolvers/publisher-resolver.js.map +1 -0
- package/lib/graphql/resolvers/registry-extension-resolver.d.ts +5 -0
- package/lib/graphql/resolvers/registry-extension-resolver.d.ts.map +1 -0
- package/lib/graphql/resolvers/registry-extension-resolver.js +46 -0
- package/lib/graphql/resolvers/registry-extension-resolver.js.map +1 -0
- package/lib/graphql/schemas/extension-pricing.graphql +546 -0
- package/lib/graphql/schemas/extension-pricing.graphql.js +1 -0
- package/lib/graphql/schemas/extension-pricing.graphql.js.map +1 -0
- package/lib/graphql/schemas/extension-registry.graphql +107 -0
- package/lib/graphql/schemas/extension-registry.graphql.js +1 -0
- package/lib/graphql/schemas/extension-registry.graphql.js.map +1 -0
- package/lib/graphql/schemas/form-templates.graphql +269 -0
- package/lib/graphql/schemas/form-templates.graphql.js +1 -0
- package/lib/graphql/schemas/form-templates.graphql.js.map +1 -0
- package/lib/graphql/schemas/gallery-schema.graphql +247 -0
- package/lib/graphql/schemas/gallery-schema.graphql.js +1 -0
- package/lib/graphql/schemas/gallery-schema.graphql.js.map +1 -0
- package/lib/graphql/schemas/index.d.ts.map +1 -1
- package/lib/graphql/schemas/index.js +3 -4
- package/lib/graphql/schemas/index.js.map +1 -1
- package/lib/graphql/schemas/installed-extension.graphql +324 -0
- package/lib/graphql/schemas/installed-extension.graphql.js +1 -0
- package/lib/graphql/schemas/installed-extension.graphql.js.map +1 -0
- package/lib/graphql/schemas/publisher-analytics.graphql +305 -0
- package/lib/graphql/schemas/publisher-analytics.graphql.js +1 -0
- package/lib/graphql/schemas/publisher-analytics.graphql.js.map +1 -0
- package/lib/graphql/schemas/publisher.graphql +584 -0
- package/lib/graphql/schemas/publisher.graphql.js +1 -0
- package/lib/graphql/schemas/publisher.graphql.js.map +1 -0
- package/lib/graphql/schemas/service.graphql +196 -0
- package/lib/index.d.ts +3 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/migrations/dbMigrations/DropOldPublisherIndexMigration.d.ts +20 -0
- package/lib/migrations/dbMigrations/DropOldPublisherIndexMigration.d.ts.map +1 -0
- package/lib/migrations/dbMigrations/DropOldPublisherIndexMigration.js +61 -0
- package/lib/migrations/dbMigrations/DropOldPublisherIndexMigration.js.map +1 -0
- package/lib/migrations/index.d.ts +2 -0
- package/lib/migrations/index.d.ts.map +1 -0
- package/lib/module.d.ts +1 -1
- package/lib/module.d.ts.map +1 -1
- package/lib/module.js +12 -25
- package/lib/module.js.map +1 -1
- package/lib/plugins/extension-moleculer-service.d.ts +86 -0
- package/lib/plugins/extension-moleculer-service.d.ts.map +1 -0
- package/lib/plugins/index.d.ts +2 -0
- package/lib/plugins/index.d.ts.map +1 -0
- package/lib/services/extension-gallery-repository.d.ts +17 -0
- package/lib/services/extension-gallery-repository.d.ts.map +1 -0
- package/lib/services/extension-gallery-repository.js +192 -0
- package/lib/services/extension-gallery-repository.js.map +1 -0
- package/lib/services/extension-gallery-service-new.d.ts +39 -0
- package/lib/services/extension-gallery-service-new.d.ts.map +1 -0
- package/lib/services/extension-gallery-service.d.ts +30 -0
- package/lib/services/extension-gallery-service.d.ts.map +1 -0
- package/lib/services/extension-gallery-service.js +334 -0
- package/lib/services/extension-gallery-service.js.map +1 -0
- package/lib/services/index.d.ts +6 -1
- package/lib/services/index.d.ts.map +1 -1
- package/lib/services/installed-extension-service-ext.d.ts +16 -0
- package/lib/services/installed-extension-service-ext.d.ts.map +1 -0
- package/lib/services/installed-extension-service-ext.js +518 -0
- package/lib/services/installed-extension-service-ext.js.map +1 -0
- package/lib/services/installed-extension-service.d.ts +110 -0
- package/lib/services/installed-extension-service.d.ts.map +1 -0
- package/lib/services/installed-extension-service.js +633 -0
- package/lib/services/installed-extension-service.js.map +1 -0
- package/lib/services/installed-extension-service.test.d.ts +1 -0
- package/lib/services/installed-extension-service.test.d.ts.map +1 -0
- package/lib/services/publisher-analytics-service.d.ts +128 -0
- package/lib/services/publisher-analytics-service.d.ts.map +1 -0
- package/lib/services/publisher-event-service.d.ts +48 -0
- package/lib/services/publisher-event-service.d.ts.map +1 -0
- package/lib/services/publisher-event-service.js +296 -0
- package/lib/services/publisher-event-service.js.map +1 -0
- package/lib/services/publisher-service-context.d.ts +1 -0
- package/lib/services/publisher-service-context.d.ts.map +1 -0
- package/lib/services/publisher-service.d.ts +62 -0
- package/lib/services/publisher-service.d.ts.map +1 -0
- package/lib/services/publisher-service.js +135 -0
- package/lib/services/publisher-service.js.map +1 -0
- package/lib/store/index.d.ts +1 -1
- package/lib/store/index.d.ts.map +1 -1
- package/lib/store/models/index.d.ts +2 -1
- package/lib/store/models/index.d.ts.map +1 -1
- package/lib/store/models/installed-extension-model.d.ts +4 -0
- package/lib/store/models/installed-extension-model.d.ts.map +1 -0
- package/lib/store/models/installed-extension-model.js +269 -0
- package/lib/store/models/installed-extension-model.js.map +1 -0
- package/lib/store/models/publisher-event-model.d.ts +11 -0
- package/lib/store/models/publisher-event-model.d.ts.map +1 -0
- package/lib/store/models/publisher-model.d.ts +5 -0
- package/lib/store/models/publisher-model.d.ts.map +1 -0
- package/lib/store/models/publisher-model.js +117 -0
- package/lib/store/models/publisher-model.js.map +1 -0
- package/lib/store/models/publisher-stats-model.d.ts +1 -0
- package/lib/store/models/publisher-stats-model.d.ts.map +1 -0
- package/lib/store/repositories/index.d.ts +3 -0
- package/lib/store/repositories/index.d.ts.map +1 -0
- package/lib/store/repositories/installed-extension-repository.d.ts +77 -0
- package/lib/store/repositories/installed-extension-repository.d.ts.map +1 -0
- package/lib/store/repositories/installed-extension-repository.js +462 -0
- package/lib/store/repositories/installed-extension-repository.js.map +1 -0
- package/lib/store/repositories/publisher-analytics-repository.d.ts +1 -0
- package/lib/store/repositories/publisher-analytics-repository.d.ts.map +1 -0
- package/lib/store/repositories/publisher-repository.d.ts +19 -0
- package/lib/store/repositories/publisher-repository.d.ts.map +1 -0
- package/lib/store/repositories/publisher-repository.js +87 -0
- package/lib/store/repositories/publisher-repository.js.map +1 -0
- package/lib/templates/constants/DB_COLL_NAMES.ts.template +5 -0
- package/lib/templates/constants/SERVER_TYPES.ts.template +10 -4
- package/lib/templates/repositories/ExtensionGalleryRepository.ts.template +44 -0
- package/lib/templates/repositories/InstalledExtensionRepository.ts.template +99 -0
- package/lib/templates/repositories/MarketplacePublisherRepository.ts.template +24 -0
- package/lib/templates/repositories/RegistryExtensionRepository.ts.template +10 -15
- package/lib/templates/services/ExtensionGalleryDataLoader.ts.template +2 -0
- package/lib/templates/services/ExtensionGalleryService.ts.template +79 -0
- package/lib/templates/services/InstalledExtensionDataLoader.ts.template +2 -0
- package/lib/templates/services/InstalledExtensionService.ts.template +199 -0
- package/lib/templates/services/MarketplacePublisherService.ts.template +51 -0
- package/lib/templates/services/PublisherDataLoader.ts.template +3 -0
- package/lib/templates/services/PublisherEventService.ts.template +56 -0
- package/lib/templates/services/RegistryExtensionService.ts.template +62 -18
- package/lib/tests/extension-integration.test.d.ts +1 -0
- package/lib/tests/extension-integration.test.d.ts.map +1 -0
- package/lib/tests/install-extension-graphql.test.d.ts +2 -0
- package/lib/tests/install-extension-graphql.test.d.ts.map +1 -0
- package/lib/tests/test-extension-services.d.ts +1 -0
- package/lib/tests/test-extension-services.d.ts.map +1 -0
- package/lib/utils/publisherValidation.d.ts +23 -0
- package/lib/utils/publisherValidation.d.ts.map +1 -0
- package/lib/utils/publisherValidation.js +144 -0
- package/lib/utils/publisherValidation.js.map +1 -0
- package/package.json +16 -7
- package/lib/graphql/resolvers/resolvers.d.ts +0 -2
- package/lib/graphql/resolvers/resolvers.d.ts.map +0 -1
- package/lib/graphql/resolvers/resolvers.js +0 -167
- package/lib/graphql/resolvers/resolvers.js.map +0 -1
- package/lib/graphql/schemas/extension.graphql +0 -57
- package/lib/graphql/schemas/extension.graphql.js +0 -1
- package/lib/graphql/schemas/extension.graphql.js.map +0 -1
- package/lib/services/extension-service.d.ts +0 -54
- package/lib/services/extension-service.d.ts.map +0 -1
- package/lib/services/extension-service.js +0 -42
- package/lib/services/extension-service.js.map +0 -1
- package/lib/store/models/registry-extension-model.d.ts +0 -10
- package/lib/store/models/registry-extension-model.d.ts.map +0 -1
- package/lib/store/models/registry-extension-model.js +0 -62
- package/lib/store/models/registry-extension-model.js.map +0 -1
- package/lib/store/repository/index.d.ts +0 -2
- package/lib/store/repository/index.d.ts.map +0 -1
- package/lib/store/repository/registry-extension-repository.d.ts +0 -31
- package/lib/store/repository/registry-extension-repository.d.ts.map +0 -1
- package/lib/store/repository/registry-extension-repository.js +0 -135
- package/lib/store/repository/registry-extension-repository.js.map +0 -1
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import {__decorate,__param,__metadata}from'tslib';import {injectable,inject}from'inversify';import'@cdm-logger/core';import*as fs from'fs';import*as https from'https';import*as http from'http';let ExtensionGalleryRepository = class ExtensionGalleryRepository {
|
|
2
|
+
logger;
|
|
3
|
+
constructor(logger) {
|
|
4
|
+
this.logger = logger;
|
|
5
|
+
this.logger = logger;
|
|
6
|
+
}
|
|
7
|
+
async asset(extensionSlug, version, asset) {
|
|
8
|
+
this.logger.trace('ExtensionGalleryRepository.asset: %s@%s/%s', extensionSlug, version, asset);
|
|
9
|
+
try {
|
|
10
|
+
// Try to fetch asset from different sources
|
|
11
|
+
const assetUrl = this.buildAssetUrl(extensionSlug, version, asset);
|
|
12
|
+
if (assetUrl.startsWith('http')) {
|
|
13
|
+
// Fetch from remote URL
|
|
14
|
+
return await this.fetchHttpAsset(assetUrl);
|
|
15
|
+
}
|
|
16
|
+
// Try to read from local filesystem
|
|
17
|
+
return await this.readLocalAsset(assetUrl);
|
|
18
|
+
} catch (error) {
|
|
19
|
+
this.logger.warn('Failed to fetch asset %s@%s/%s: %s', extensionSlug, version, asset, error.message);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
buildAssetUrl(extensionSlug, version, asset) {
|
|
24
|
+
// Build URL based on common extension repository patterns
|
|
25
|
+
const baseUrl = process.env.EXTENSION_REGISTRY_URL || 'https://marketplace.visualstudio.com/_apis/public/gallery';
|
|
26
|
+
return `${baseUrl}/publishers/${extensionSlug}/vsextensions/${version}/vspackage/${asset}`;
|
|
27
|
+
}
|
|
28
|
+
async fetchHttpAsset(url) {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const client = url.startsWith('https') ? https : http;
|
|
31
|
+
const req = client.get(url, response => {
|
|
32
|
+
if (response.statusCode !== 200) {
|
|
33
|
+
reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
let data = '';
|
|
37
|
+
response.setEncoding('utf8');
|
|
38
|
+
response.on('data', chunk => {
|
|
39
|
+
data += chunk;
|
|
40
|
+
});
|
|
41
|
+
response.on('end', () => {
|
|
42
|
+
try {
|
|
43
|
+
// Try to parse as JSON first, fallback to string
|
|
44
|
+
const result = data.startsWith('{') || data.startsWith('[') ? JSON.parse(data) : data;
|
|
45
|
+
resolve(result);
|
|
46
|
+
} catch (parseError) {
|
|
47
|
+
resolve(data);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
req.on('error', error => {
|
|
52
|
+
reject(error);
|
|
53
|
+
});
|
|
54
|
+
req.setTimeout(10000, () => {
|
|
55
|
+
req.destroy();
|
|
56
|
+
reject(new Error('Request timeout'));
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async readLocalAsset(filePath) {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
fs.readFile(filePath, 'utf8', (err, data) => {
|
|
63
|
+
if (err) {
|
|
64
|
+
reject(err);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
// Try to parse as JSON first, fallback to string
|
|
69
|
+
const result = data.startsWith('{') || data.startsWith('[') ? JSON.parse(data) : data;
|
|
70
|
+
resolve(result);
|
|
71
|
+
} catch (parseError) {
|
|
72
|
+
resolve(data);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
async get(id, fields) {
|
|
78
|
+
this.logger.trace('ExtensionGalleryRepository.get: %s fields: %j', id, fields);
|
|
79
|
+
try {
|
|
80
|
+
// In a real implementation, this would:
|
|
81
|
+
// 1. Parse the ID (could be extension slug, UUID, etc.)
|
|
82
|
+
// 2. Query the database/registry for matching extensions
|
|
83
|
+
// 3. Apply field filtering to optimize response size
|
|
84
|
+
// 4. Handle multiple IDs if the id parameter supports it
|
|
85
|
+
// For now, we validate the inputs and return empty result
|
|
86
|
+
if (!id || !id.trim()) {
|
|
87
|
+
throw new Error('Extension ID is required');
|
|
88
|
+
}
|
|
89
|
+
// Validate fields array
|
|
90
|
+
const validFields = this.validateFields(fields);
|
|
91
|
+
this.logger.info('Looking for extension with ID: %s, fields: %j', id, validFields);
|
|
92
|
+
// This would be replaced with actual database/API query
|
|
93
|
+
const extensions = [];
|
|
94
|
+
return extensions;
|
|
95
|
+
} catch (error) {
|
|
96
|
+
this.logger.error('Failed to get extension %s: %s', id, error.message);
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
validateFields(fields) {
|
|
101
|
+
if (!fields || fields.length === 0) {
|
|
102
|
+
// Return default fields if none specified
|
|
103
|
+
return ['id', 'name', 'version', 'displayName', 'description', 'publisher'];
|
|
104
|
+
}
|
|
105
|
+
// Define allowed fields to prevent data leakage
|
|
106
|
+
const allowedFields = ['id', 'name', 'version', 'displayName', 'description', 'publisher', 'assets', 'categories', 'tags', 'statistics', 'releaseDate', 'lastUpdated', 'shortDescription', 'installCount'];
|
|
107
|
+
return fields.filter(field => allowedFields.includes(field));
|
|
108
|
+
}
|
|
109
|
+
async download(extension) {
|
|
110
|
+
this.logger.trace('ExtensionGalleryRepository.download: %s', extension.id);
|
|
111
|
+
try {
|
|
112
|
+
// Get download URL from extension assets
|
|
113
|
+
const downloadAsset = extension.assets?.download;
|
|
114
|
+
if (!downloadAsset?.uri) {
|
|
115
|
+
throw new Error('No download URL available');
|
|
116
|
+
}
|
|
117
|
+
// Verify the download is accessible
|
|
118
|
+
const isAccessible = await this.verifyDownloadUrl(downloadAsset.uri);
|
|
119
|
+
if (!isAccessible) {
|
|
120
|
+
throw new Error('Download URL is not accessible');
|
|
121
|
+
}
|
|
122
|
+
// In a real implementation, you might:
|
|
123
|
+
// 1. Download the file to a local cache
|
|
124
|
+
// 2. Verify the package integrity
|
|
125
|
+
// 3. Store download metrics
|
|
126
|
+
// 4. Return download stream or file path
|
|
127
|
+
this.logger.info('Extension %s download verified successfully', extension.id);
|
|
128
|
+
return true;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
this.logger.error('Download failed for %s: %s', extension.id, error.message);
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async verifyDownloadUrl(url) {
|
|
135
|
+
return new Promise(resolve => {
|
|
136
|
+
const client = url.startsWith('https') ? https : http;
|
|
137
|
+
const req = client.request(url, {
|
|
138
|
+
method: 'HEAD'
|
|
139
|
+
}, response => {
|
|
140
|
+
const isSuccess = response.statusCode >= 200 && response.statusCode < 300;
|
|
141
|
+
resolve(isSuccess);
|
|
142
|
+
});
|
|
143
|
+
req.on('error', () => {
|
|
144
|
+
resolve(false);
|
|
145
|
+
});
|
|
146
|
+
req.setTimeout(5000, () => {
|
|
147
|
+
req.destroy();
|
|
148
|
+
resolve(false);
|
|
149
|
+
});
|
|
150
|
+
req.end();
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
async query(query) {
|
|
154
|
+
this.logger.trace('ExtensionGalleryRepository.query: %j', query);
|
|
155
|
+
try {
|
|
156
|
+
// Extract common query parameters
|
|
157
|
+
const pageSize = Math.min(query.pageSize || 50, 100); // Cap at 100
|
|
158
|
+
// In a real implementation, this would:
|
|
159
|
+
// 1. Query a search engine (Elasticsearch, etc.)
|
|
160
|
+
// 2. Query a database with proper indexing
|
|
161
|
+
// 3. Call external APIs like VS Code Marketplace
|
|
162
|
+
// 4. Apply filters like: query.search, query.category, query.publisher, etc.
|
|
163
|
+
// For now, return a structured empty result with proper pagination
|
|
164
|
+
const mockResult = {
|
|
165
|
+
results: [],
|
|
166
|
+
total: 0,
|
|
167
|
+
pageSize
|
|
168
|
+
};
|
|
169
|
+
this.logger.info('Extension query completed: %d results', mockResult.total);
|
|
170
|
+
return mockResult;
|
|
171
|
+
} catch (error) {
|
|
172
|
+
this.logger.error('Extension query failed: %s', error.message);
|
|
173
|
+
// Return empty result on error
|
|
174
|
+
return {
|
|
175
|
+
results: [],
|
|
176
|
+
total: 0,
|
|
177
|
+
pageSize: 50
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
extractFilters(query) {
|
|
182
|
+
const filters = {};
|
|
183
|
+
// Extract common filter parameters
|
|
184
|
+
if (query.category) filters.category = query.category;
|
|
185
|
+
if (query.publisher) filters.publisher = query.publisher;
|
|
186
|
+
if (query.featured) filters.featured = query.featured;
|
|
187
|
+
if (query.verified) filters.verified = query.verified;
|
|
188
|
+
if (query.targetPlatform) filters.targetPlatform = query.targetPlatform;
|
|
189
|
+
return filters;
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
ExtensionGalleryRepository = __decorate([injectable(), __param(0, inject('Logger')), __metadata("design:paramtypes", [Object])], ExtensionGalleryRepository);export{ExtensionGalleryRepository};//# sourceMappingURL=extension-gallery-repository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension-gallery-repository.js","sources":["../../src/services/extension-gallery-repository.ts"],"sourcesContent":[null],"names":[],"mappings":"iMAgCI,IAAA,0BAAqB,GAAA,MAAA,0BAAA,CAAA;;aA2CP,CAAA,MAAA,EAAA;AAmBD,IAAA,IAAI,CAAA,MAAI,GAAM,MAAE;AA8B7B,IAAA,IAAA,CAAA,MAAQ,GAAA,MAAA;;aA0DM,CAAA,aAAA,EAAiB,OAAA,EAAA,KAAA,EAAA;AAqBlB,IAAA,IAAA,CAAK,MAAM,CAAA,KAAE,CAAA,2DAAsD,EAAA,OAAA,EAAA,KAAA,CAAA;AAkChF,IAAA,IAAA;AAYH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { CdmLogger } from '@cdm-logger/core';
|
|
2
|
+
import { IMarketplacePublisherService, IRegistryExtensionService, IGalleryExtension, IExtensionIdentifier, IExtensionManifest } from 'common/server';
|
|
3
|
+
export interface IExtensionGalleryService {
|
|
4
|
+
isEnabled(): boolean;
|
|
5
|
+
query(options?: any): Promise<any>;
|
|
6
|
+
getExtension(identifier: IExtensionIdentifier | string, version?: string): Promise<IGalleryExtension | null>;
|
|
7
|
+
download(extension: IGalleryExtension, operation: any): Promise<string>;
|
|
8
|
+
getReadme(extension: IGalleryExtension, token?: unknown): Promise<string>;
|
|
9
|
+
getManifest(extension: IGalleryExtension, token?: unknown): Promise<IExtensionManifest | null>;
|
|
10
|
+
getChangelog(extension: IGalleryExtension, token?: unknown): Promise<string>;
|
|
11
|
+
getLicense(extension: IGalleryExtension, token?: unknown): Promise<string>;
|
|
12
|
+
loadCompatibleVersion(extension: IGalleryExtension): Promise<IGalleryExtension>;
|
|
13
|
+
}
|
|
14
|
+
export declare class ExtensionGalleryService implements IExtensionGalleryService {
|
|
15
|
+
private readonly logger;
|
|
16
|
+
private readonly registryExtensionService;
|
|
17
|
+
private readonly publisherService;
|
|
18
|
+
private readonly disposables;
|
|
19
|
+
private readonly _onDidChange;
|
|
20
|
+
readonly onDidChange: import("@adminide-stack/core").Event<void>;
|
|
21
|
+
constructor(logger: CdmLogger.ILogger, registryExtensionService: IRegistryExtensionService, publisherService: IMarketplacePublisherService);
|
|
22
|
+
isEnabled(): boolean;
|
|
23
|
+
query(options?: any): Promise<any>;
|
|
24
|
+
getExtension(identifier: IExtensionIdentifier | string, version?: string): Promise<IGalleryExtension | null>;
|
|
25
|
+
download(extension: IGalleryExtension, operation: any): Promise<string>;
|
|
26
|
+
getReadme(extension: IGalleryExtension, token?: unknown): Promise<string>;
|
|
27
|
+
getManifest(extension: IGalleryExtension, token?: unknown): Promise<IExtensionManifest | null>;
|
|
28
|
+
getChangelog(extension: IGalleryExtension, token?: unknown): Promise<string>;
|
|
29
|
+
getLicense(extension: IGalleryExtension, token?: unknown): Promise<string>;
|
|
30
|
+
loadCompatibleVersion(extension: IGalleryExtension): Promise<IGalleryExtension>;
|
|
31
|
+
private toGalleryExtension;
|
|
32
|
+
/**
|
|
33
|
+
* Helper method to get manifest from the current release
|
|
34
|
+
* Since manifests are stored in releases, not directly in the registry extension
|
|
35
|
+
*/
|
|
36
|
+
private getManifestFromRelease;
|
|
37
|
+
dispose(): void;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=extension-gallery-service-new.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension-gallery-service-new.d.ts","sourceRoot":"","sources":["../../src/services/extension-gallery-service-new.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EACH,4BAA4B,EAC5B,yBAAyB,EAGzB,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAIrB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,wBAAwB;IACrC,SAAS,IAAI,OAAO,CAAC;IACrB,KAAK,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACnC,YAAY,CAAC,UAAU,EAAE,oBAAoB,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IAC7G,QAAQ,CAAC,SAAS,EAAE,iBAAiB,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxE,SAAS,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1E,WAAW,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC;IAC/F,YAAY,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7E,UAAU,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3E,qBAAqB,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CACnF;AAED,qBACa,uBAAwB,YAAW,wBAAwB;IAO9C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEzC,OAAO,CAAC,QAAQ,CAAC,wBAAwB;IAEzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAVrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;IAC1D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuB;IAEpD,SAAgB,WAAW,6CAA2B;gBAGf,MAAM,EAAE,SAAS,CAAC,OAAO,EAE3C,wBAAwB,EAAE,yBAAyB,EAEnD,gBAAgB,EAAE,4BAA4B;IAK5D,SAAS,IAAI,OAAO;IAId,KAAK,CAAC,OAAO,GAAE,GAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAkCtC,YAAY,CACrB,UAAU,EAAE,oBAAoB,GAAG,MAAM,EACzC,OAAO,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAqBvB,QAAQ,CAAC,SAAS,EAAE,iBAAiB,EAAE,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC;IAKvE,SAAS,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAOzE,WAAW,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAK9F,YAAY,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAO5E,UAAU,CAAC,SAAS,EAAE,iBAAiB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAO1E,qBAAqB,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAI9E,kBAAkB;IAwIhC;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAoEvB,OAAO,IAAI,IAAI;CAGzB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { CdmLogger } from '@cdm-logger/core';
|
|
2
|
+
import { IMarketplacePublisherService, IRegistryExtensionService, IGalleryExtension, IExtensionIdentifier, IExtensionManifest, IGalleryPager, IExtensionGalleryService, IQueryOptions, IExtensionGalleryRepository } from 'common/server';
|
|
3
|
+
export declare class ExtensionGalleryService implements IExtensionGalleryService {
|
|
4
|
+
private readonly logger;
|
|
5
|
+
private readonly registryExtensionService;
|
|
6
|
+
private readonly publisherService;
|
|
7
|
+
private readonly galleryRepository;
|
|
8
|
+
private readonly disposables;
|
|
9
|
+
private readonly _onDidChange;
|
|
10
|
+
readonly onDidChange: import("@adminide-stack/core").Event<void>;
|
|
11
|
+
constructor(logger: CdmLogger.ILogger, registryExtensionService: IRegistryExtensionService, publisherService: IMarketplacePublisherService, galleryRepository: IExtensionGalleryRepository);
|
|
12
|
+
isEnabled(): boolean;
|
|
13
|
+
query(options?: IQueryOptions): Promise<IGalleryPager>;
|
|
14
|
+
getExtension(identifier: IExtensionIdentifier | string): Promise<IGalleryExtension | null>;
|
|
15
|
+
download(extension: IGalleryExtension): Promise<string>;
|
|
16
|
+
getReadme(extension: IGalleryExtension): Promise<string>;
|
|
17
|
+
getManifest(extension: IGalleryExtension): Promise<IExtensionManifest | null>;
|
|
18
|
+
getChangelog(extension: IGalleryExtension): Promise<string>;
|
|
19
|
+
getLicense(extension: IGalleryExtension): Promise<string>;
|
|
20
|
+
loadCompatibleVersion(extension: IGalleryExtension): Promise<IGalleryExtension>;
|
|
21
|
+
private toGalleryExtension;
|
|
22
|
+
getAllVersions(extension: IGalleryExtension): Promise<IGalleryExtension[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Helper method to get manifest from the current release
|
|
25
|
+
* Since manifests are stored in releases, not directly in the registry extension
|
|
26
|
+
*/
|
|
27
|
+
private getManifestFromRelease;
|
|
28
|
+
dispose(): void;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=extension-gallery-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension-gallery-service.d.ts","sourceRoot":"","sources":["../../src/services/extension-gallery-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,OAAO,EACH,4BAA4B,EAC5B,yBAAyB,EAGzB,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EAClB,aAAa,EAGb,wBAAwB,EACxB,aAAa,EACb,2BAA2B,EAC9B,MAAM,eAAe,CAAC;AAEvB,qBACa,uBAAwB,YAAW,wBAAwB;IAQ9C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEzC,OAAO,CAAC,QAAQ,CAAC,wBAAwB;IAEzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAEjC,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAbtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA8B;IAE1D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAuB;IAEpD,SAAgB,WAAW,6CAA2B;gBAGf,MAAM,EAAE,SAAS,CAAC,OAAO,EAE3C,wBAAwB,EAAE,yBAAyB,EAEnD,gBAAgB,EAAE,4BAA4B,EAE9C,iBAAiB,EAAE,2BAA2B;IAK5D,SAAS,IAAI,OAAO;IAId,KAAK,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;IAkC1D,YAAY,CAAC,UAAU,EAAE,oBAAoB,GAAG,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAqB1F,QAAQ,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAkBvD,SAAS,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAsBxD,WAAW,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;IAuB7E,YAAY,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAsB3D,UAAU,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAsBzD,qBAAqB,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC;YAsC9E,kBAAkB;IA0InB,cAAc,CAAC,SAAS,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IA2BvF;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IA8CvB,OAAO,IAAI,IAAI;CAGzB"}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import {__decorate,__param,__metadata}from'tslib';import {injectable,inject}from'inversify';import'@cdm-logger/core';import {DisposableCollection,Emitter}from'@adminide-stack/core';import {SERVER_TYPES,ExtensionRegistryStatus}from'common/server';let ExtensionGalleryService = class ExtensionGalleryService {
|
|
2
|
+
logger;
|
|
3
|
+
registryExtensionService;
|
|
4
|
+
publisherService;
|
|
5
|
+
galleryRepository;
|
|
6
|
+
disposables = new DisposableCollection();
|
|
7
|
+
_onDidChange = new Emitter();
|
|
8
|
+
onDidChange = this._onDidChange.event;
|
|
9
|
+
constructor(logger, registryExtensionService, publisherService, galleryRepository) {
|
|
10
|
+
this.logger = logger;
|
|
11
|
+
this.registryExtensionService = registryExtensionService;
|
|
12
|
+
this.publisherService = publisherService;
|
|
13
|
+
this.galleryRepository = galleryRepository;
|
|
14
|
+
this.disposables.push(this._onDidChange);
|
|
15
|
+
}
|
|
16
|
+
isEnabled() {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
async query(options = {}) {
|
|
20
|
+
this.logger.trace('ExtensionGalleryService.query with options: %j', options);
|
|
21
|
+
try {
|
|
22
|
+
const {
|
|
23
|
+
text = '',
|
|
24
|
+
pageSize = 50
|
|
25
|
+
} = options;
|
|
26
|
+
const extensions = await this.registryExtensionService.findExtensions(pageSize, text, false,
|
|
27
|
+
// local
|
|
28
|
+
true);
|
|
29
|
+
const galleryExtensions = await Promise.all(extensions.map(ext => this.toGalleryExtension(ext)));
|
|
30
|
+
return {
|
|
31
|
+
__typename: 'GalleryPager',
|
|
32
|
+
firstPage: galleryExtensions,
|
|
33
|
+
total: galleryExtensions.length,
|
|
34
|
+
pageSize,
|
|
35
|
+
page: 0
|
|
36
|
+
};
|
|
37
|
+
} catch (error) {
|
|
38
|
+
this.logger.error('ExtensionGalleryService.query error: %s', error.message);
|
|
39
|
+
return {
|
|
40
|
+
__typename: 'GalleryPager',
|
|
41
|
+
firstPage: [],
|
|
42
|
+
total: 0,
|
|
43
|
+
pageSize: options.pageSize || 50,
|
|
44
|
+
page: 0
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
async getExtension(identifier) {
|
|
49
|
+
this.logger.trace('ExtensionGalleryService.getExtension: %s', typeof identifier === 'string' ? identifier : identifier.id);
|
|
50
|
+
try {
|
|
51
|
+
const extensionId = typeof identifier === 'string' ? identifier : identifier.id;
|
|
52
|
+
const extension = await this.registryExtensionService.findExtension(extensionId);
|
|
53
|
+
if (!extension) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return this.toGalleryExtension(extension);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
this.logger.error('ExtensionGalleryService.getExtension error: %s', error.message);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async download(extension) {
|
|
63
|
+
this.logger.trace('ExtensionGalleryService.download: %s', extension.id);
|
|
64
|
+
try {
|
|
65
|
+
const success = await this.galleryRepository.download(extension);
|
|
66
|
+
if (success) {
|
|
67
|
+
// Return the download URL for the extension
|
|
68
|
+
const downloadUrl = extension.assets?.download?.uri || `${extension.url}/${extension.version}.vsix`;
|
|
69
|
+
this.logger.info('Extension download prepared: %s -> %s', extension.id, downloadUrl);
|
|
70
|
+
return downloadUrl;
|
|
71
|
+
}
|
|
72
|
+
throw new Error(`Failed to prepare download for extension: ${extension.id}`);
|
|
73
|
+
} catch (error) {
|
|
74
|
+
this.logger.error('ExtensionGalleryService.download error: %s', error.message);
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async getReadme(extension) {
|
|
79
|
+
this.logger.trace('ExtensionGalleryService.getReadme: %s', extension.id);
|
|
80
|
+
try {
|
|
81
|
+
const readmeUrl = extension.assets?.readme?.uri;
|
|
82
|
+
if (!readmeUrl) {
|
|
83
|
+
return 'No README available for this extension.';
|
|
84
|
+
}
|
|
85
|
+
const readmeAsset = await this.galleryRepository.asset(extension.extensionSlug || extension.id, extension.version, 'README.md');
|
|
86
|
+
return readmeAsset || 'README content could not be loaded.';
|
|
87
|
+
} catch (error) {
|
|
88
|
+
this.logger.warn('Failed to fetch README for %s: %s', extension.id, error.message);
|
|
89
|
+
return 'Error loading README content.';
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async getManifest(extension) {
|
|
93
|
+
this.logger.trace('ExtensionGalleryService.getManifest: %s', extension.id);
|
|
94
|
+
try {
|
|
95
|
+
// First try to return the already loaded manifest
|
|
96
|
+
if (extension.manifest) {
|
|
97
|
+
return extension.manifest;
|
|
98
|
+
}
|
|
99
|
+
// If not available, try to fetch from repository
|
|
100
|
+
const manifestAsset = await this.galleryRepository.asset(extension.extensionSlug || extension.id, extension.version, 'package.json');
|
|
101
|
+
return manifestAsset;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
this.logger.warn('Failed to fetch manifest for %s: %s', extension.id, error.message);
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async getChangelog(extension) {
|
|
108
|
+
this.logger.trace('ExtensionGalleryService.getChangelog: %s', extension.id);
|
|
109
|
+
try {
|
|
110
|
+
const changelogUrl = extension.assets?.changelog?.uri;
|
|
111
|
+
if (!changelogUrl) {
|
|
112
|
+
return 'No changelog available for this extension.';
|
|
113
|
+
}
|
|
114
|
+
const changelogAsset = await this.galleryRepository.asset(extension.extensionSlug || extension.id, extension.version, 'CHANGELOG.md');
|
|
115
|
+
return changelogAsset || 'Changelog content could not be loaded.';
|
|
116
|
+
} catch (error) {
|
|
117
|
+
this.logger.warn('Failed to fetch changelog for %s: %s', extension.id, error.message);
|
|
118
|
+
return 'Error loading changelog content.';
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async getLicense(extension) {
|
|
122
|
+
this.logger.trace('ExtensionGalleryService.getLicense: %s', extension.id);
|
|
123
|
+
try {
|
|
124
|
+
const licenseUrl = extension.assets?.license?.uri;
|
|
125
|
+
if (!licenseUrl) {
|
|
126
|
+
return 'No license information available for this extension.';
|
|
127
|
+
}
|
|
128
|
+
const licenseAsset = await this.galleryRepository.asset(extension.extensionSlug || extension.id, extension.version, 'LICENSE');
|
|
129
|
+
return licenseAsset || 'License content could not be loaded.';
|
|
130
|
+
} catch (error) {
|
|
131
|
+
this.logger.warn('Failed to fetch license for %s: %s', extension.id, error.message);
|
|
132
|
+
return 'Error loading license information.';
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async loadCompatibleVersion(extension) {
|
|
136
|
+
this.logger.trace('ExtensionGalleryService.loadCompatibleVersion: %s', extension.id);
|
|
137
|
+
try {
|
|
138
|
+
// Get all extensions from registry (search for this specific extension)
|
|
139
|
+
const allExtensions = await this.registryExtensionService.findExtensions(100, `${extension.publisher.displayName}.${extension.name}`, true, true);
|
|
140
|
+
// Filter to get versions of the same extension
|
|
141
|
+
const extensionVersions = allExtensions.filter(ext => ext.name === extension.name);
|
|
142
|
+
if (!extensionVersions || extensionVersions.length === 0) {
|
|
143
|
+
// If no versions found, return the current extension
|
|
144
|
+
return extension;
|
|
145
|
+
}
|
|
146
|
+
// Find the latest compatible version
|
|
147
|
+
const latestVersion = extensionVersions.sort((a, b) => b.version.localeCompare(a.version, undefined, {
|
|
148
|
+
numeric: true
|
|
149
|
+
}))[0];
|
|
150
|
+
// Convert to gallery extension if different from current
|
|
151
|
+
if (latestVersion.version !== extension.version) {
|
|
152
|
+
return this.toGalleryExtension(latestVersion);
|
|
153
|
+
}
|
|
154
|
+
return extension;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
this.logger.warn('Failed to load compatible version for %s: %s', extension.id, error.message);
|
|
157
|
+
// Return original extension if we can't find a compatible version
|
|
158
|
+
return extension;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
async toGalleryExtension(registryExt) {
|
|
162
|
+
let publisherInfo = null;
|
|
163
|
+
try {
|
|
164
|
+
const publisherId = registryExt.publisherId || registryExt.publisher;
|
|
165
|
+
if (publisherId) {
|
|
166
|
+
publisherInfo = await this.publisherService.findById(publisherId);
|
|
167
|
+
}
|
|
168
|
+
} catch (error) {
|
|
169
|
+
this.logger.warn('Failed to get publisher info: %s', error.message);
|
|
170
|
+
}
|
|
171
|
+
const manifest = this.getManifestFromRelease(registryExt);
|
|
172
|
+
// Get the raw manifest as JSON string for resources.manifest
|
|
173
|
+
const rawManifest = manifest ? JSON.stringify(manifest) : null;
|
|
174
|
+
const galleryExtension = {
|
|
175
|
+
__typename: 'GalleryExtension',
|
|
176
|
+
id: registryExt.id || registryExt._id?.toString() || '',
|
|
177
|
+
uuid: registryExt.uuid,
|
|
178
|
+
name: registryExt.name,
|
|
179
|
+
displayName: manifest?.displayName || registryExt.name,
|
|
180
|
+
description: manifest?.description || '',
|
|
181
|
+
version: registryExt.version || '0.0.1',
|
|
182
|
+
extensionSlug: registryExt.extensionSlug,
|
|
183
|
+
manifest: {
|
|
184
|
+
...manifest,
|
|
185
|
+
raw: rawManifest || undefined,
|
|
186
|
+
// Include raw manifest in manifest object
|
|
187
|
+
screenshots: manifest?.screenshots || [],
|
|
188
|
+
author: manifest?.author || undefined,
|
|
189
|
+
license: manifest?.license || undefined,
|
|
190
|
+
preview: manifest?.preview || false
|
|
191
|
+
},
|
|
192
|
+
publisher: publisherInfo,
|
|
193
|
+
publisherId: publisherInfo?.id || '',
|
|
194
|
+
installed: registryExt.installed || false,
|
|
195
|
+
updatedAt: registryExt.updatedAt,
|
|
196
|
+
url: registryExt.url,
|
|
197
|
+
remoteURL: registryExt.remoteURL,
|
|
198
|
+
status: ExtensionRegistryStatus.Active,
|
|
199
|
+
viewerCanAdminister: registryExt.viewerCanAdminister || false,
|
|
200
|
+
isLocal: registryExt.isLocal || false,
|
|
201
|
+
categories: manifest?.categories || [],
|
|
202
|
+
tags: manifest?.tags || manifest?.keywords || [],
|
|
203
|
+
releases: registryExt.releases || [],
|
|
204
|
+
downloadCount: 0,
|
|
205
|
+
installCount: 0,
|
|
206
|
+
weeklyDownloads: 0,
|
|
207
|
+
rating: 0,
|
|
208
|
+
ratingCount: 0,
|
|
209
|
+
featured: false,
|
|
210
|
+
preview: manifest?.preview || false,
|
|
211
|
+
date: registryExt.updatedAt?.toISOString(),
|
|
212
|
+
assets: {
|
|
213
|
+
__typename: 'GalleryExtensionAssets',
|
|
214
|
+
icon: {
|
|
215
|
+
__typename: 'GalleryExtensionAsset',
|
|
216
|
+
uri: manifest?.icon || './media/defaultIcon.png',
|
|
217
|
+
fallbackUri: './media/defaultIcon.png'
|
|
218
|
+
},
|
|
219
|
+
readme: {
|
|
220
|
+
__typename: 'GalleryExtensionAsset',
|
|
221
|
+
uri: `${registryExt.url}/README.md`,
|
|
222
|
+
fallbackUri: `${registryExt.url}/README.md`
|
|
223
|
+
},
|
|
224
|
+
changelog: {
|
|
225
|
+
__typename: 'GalleryExtensionAsset',
|
|
226
|
+
uri: `${registryExt.url}/CHANGELOG.md`,
|
|
227
|
+
fallbackUri: `${registryExt.url}/CHANGELOG.md`
|
|
228
|
+
},
|
|
229
|
+
license: {
|
|
230
|
+
__typename: 'GalleryExtensionAsset',
|
|
231
|
+
uri: `${registryExt.url}/LICENSE`,
|
|
232
|
+
fallbackUri: `${registryExt.url}/LICENSE`
|
|
233
|
+
},
|
|
234
|
+
download: {
|
|
235
|
+
__typename: 'GalleryExtensionAsset',
|
|
236
|
+
uri: `${registryExt.url}/${registryExt.version}.vsix`,
|
|
237
|
+
fallbackUri: `${registryExt.url}/${registryExt.version}.vsix`
|
|
238
|
+
},
|
|
239
|
+
manifest: {
|
|
240
|
+
__typename: 'GalleryExtensionAsset',
|
|
241
|
+
uri: `${registryExt.url}/package.json`,
|
|
242
|
+
fallbackUri: `${registryExt.url}/package.json`
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
properties: {
|
|
246
|
+
__typename: 'GalleryExtensionProperties',
|
|
247
|
+
dependencies: manifest?.extensionDependencies || [],
|
|
248
|
+
extensionPack: manifest?.extensionPack || [],
|
|
249
|
+
engine: manifest?.engines?.vscode || 'unknown',
|
|
250
|
+
localizedLanguages: []
|
|
251
|
+
},
|
|
252
|
+
resources: {
|
|
253
|
+
__typename: 'GalleryExtensionResources',
|
|
254
|
+
license: `${registryExt.url}/LICENSE`,
|
|
255
|
+
repository: manifest?.repository?.url || '',
|
|
256
|
+
changelog: `${registryExt.url}/CHANGELOG.md`,
|
|
257
|
+
download: `${registryExt.url}/${registryExt.version}.vsix`,
|
|
258
|
+
icon: manifest?.icon || './media/defaultIcon.png',
|
|
259
|
+
manifest: rawManifest || `${registryExt.url}/package.json`,
|
|
260
|
+
// Store raw manifest JSON string
|
|
261
|
+
readme: `${registryExt.url}/README.md`
|
|
262
|
+
},
|
|
263
|
+
coreExtension: registryExt,
|
|
264
|
+
identifier: {
|
|
265
|
+
__typename: 'ExtensionIdentifier',
|
|
266
|
+
id: registryExt.extensionSlug || registryExt.id,
|
|
267
|
+
uuid: registryExt.uuid
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
return galleryExtension;
|
|
271
|
+
}
|
|
272
|
+
async getAllVersions(extension) {
|
|
273
|
+
this.logger.trace('ExtensionGalleryService.getAllVersions: %s', extension.id);
|
|
274
|
+
try {
|
|
275
|
+
// Get all versions from registry
|
|
276
|
+
const allExtensions = await this.registryExtensionService.findExtensions(1000,
|
|
277
|
+
// Get more versions
|
|
278
|
+
`${extension.publisher.displayName}.${extension.name}`, true, true);
|
|
279
|
+
// Filter to get all versions of the same extension
|
|
280
|
+
const extensionVersions = allExtensions.filter(ext => ext.name === extension.name);
|
|
281
|
+
// Convert all to gallery extensions and sort by version (newest first)
|
|
282
|
+
const galleryVersions = await Promise.all(extensionVersions.map(ext => this.toGalleryExtension(ext)));
|
|
283
|
+
// Sort by version (descending)
|
|
284
|
+
return galleryVersions.sort((a, b) => b.version.localeCompare(a.version, undefined, {
|
|
285
|
+
numeric: true
|
|
286
|
+
}));
|
|
287
|
+
} catch (error) {
|
|
288
|
+
this.logger.warn('Failed to get all versions for %s: %s', extension.id, error.message);
|
|
289
|
+
// Return empty array if we can't find versions
|
|
290
|
+
return [];
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Helper method to get manifest from the current release
|
|
295
|
+
* Since manifests are stored in releases, not directly in the registry extension
|
|
296
|
+
*/
|
|
297
|
+
getManifestFromRelease(registryExt) {
|
|
298
|
+
const {
|
|
299
|
+
releases
|
|
300
|
+
} = registryExt;
|
|
301
|
+
if (!releases || releases.length === 0) {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
// Find the current release that matches the extension's version
|
|
305
|
+
const currentRelease = releases.find(release => release.version === registryExt.version);
|
|
306
|
+
if (!currentRelease || !currentRelease.manifest) {
|
|
307
|
+
// If no matching release, try the first release
|
|
308
|
+
const firstRelease = releases[0];
|
|
309
|
+
if (!firstRelease || !firstRelease.manifest) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
try {
|
|
313
|
+
// Parse the manifest from the release (stored as JSON string or object)
|
|
314
|
+
const parsedManifest = typeof firstRelease.manifest === 'string' ? JSON.parse(firstRelease.manifest) : firstRelease.manifest;
|
|
315
|
+
return parsedManifest;
|
|
316
|
+
} catch (error) {
|
|
317
|
+
this.logger.warn('Failed to parse extension manifest for', registryExt.extensionSlug, ':', error);
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
try {
|
|
322
|
+
// Parse the manifest from the release (stored as JSON string or object)
|
|
323
|
+
const parsedManifest = typeof currentRelease.manifest === 'string' ? JSON.parse(currentRelease.manifest) : currentRelease.manifest;
|
|
324
|
+
return parsedManifest;
|
|
325
|
+
} catch (error) {
|
|
326
|
+
this.logger.warn('Failed to parse extension manifest for', registryExt.extensionSlug, ':', error);
|
|
327
|
+
return null;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
dispose() {
|
|
331
|
+
this.disposables.dispose();
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
ExtensionGalleryService = __decorate([injectable(), __param(0, inject('Logger')), __param(1, inject(SERVER_TYPES.IRegistryExtensionService)), __param(2, inject(SERVER_TYPES.IMarketplacePublisherService)), __param(3, inject(SERVER_TYPES.IExtensionGalleryRepository)), __metadata("design:paramtypes", [Object, Object, Object, Object])], ExtensionGalleryService);export{ExtensionGalleryService};//# sourceMappingURL=extension-gallery-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extension-gallery-service.js","sources":["../../src/services/extension-gallery-service.ts"],"sourcesContent":[null],"names":[],"mappings":"0PAgCQ,uBAAiB,GAAA,MAAA,uBAAgB,CAAA;QAEjC;AAbJ,EAAA,wBAAiB;AAEjB,EAAA,gBAAQ;AAER,EAAA;AAGuC,EAAA,WAAA,GAAA,IAAA,oBAAkB;AAWlD,EAAA,eAAa,IAAA,OAAO,EAAA;oBAIC,CAAA,YAAkB,MAAG;AAkCpC,EAAA,WAAA,CAAA,MAAa,EAAA,wBAAY,EAAA,gBAAgC,EAAA,iBAAQ,EAAA;IAqBjE,IAAA,CAAA,eAAoB;IAkBpB,IAAA,CAAA,wBAAqB,GAAA,wBAAmC;IAsBxD,IAAA,CAAA,gBAAqB,GAAE,gBAAiB;IAuBxC,IAAA,CAAA,iBAAsB,GAAE;IAsBxB,IAAA,CAAA,gBAAoB,CAAE,IAAA,CAAA,YAAiB;;cA4DtC;IA0ID,OAAA,IAAA;AA2Bb,EAAA;;;AAGG,IAAA,IAAA;AACH,MAAA,MAAQ;AA8CD,QAAA,OAAW,EAAA;AAGrB,QAAA,QAAA,GAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/lib/services/index.d.ts
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
export * from './extension-service';
|
|
1
|
+
export * from './installed-extension-service';
|
|
2
|
+
export * from './installed-extension-service-ext';
|
|
3
|
+
export * from './publisher-service';
|
|
4
|
+
export * from './publisher-event-service';
|
|
5
|
+
export * from './extension-gallery-service';
|
|
6
|
+
export * from './extension-gallery-repository';
|
|
2
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ServiceBroker } from 'moleculer';
|
|
2
|
+
import { CdmLogger } from '@cdm-logger/core';
|
|
3
|
+
import { IRegistryExtensionService, IInstalledExtensionRepository, ISlugService, IRedisCacheManager } from 'common/server';
|
|
4
|
+
import { InstalledExtensionService } from './installed-extension-service';
|
|
5
|
+
/**
|
|
6
|
+
* Extended InstalledExtensionService that handles Moleculer event broadcasting
|
|
7
|
+
* Follows the pattern of AccountService/AccountServiceExt
|
|
8
|
+
*/
|
|
9
|
+
export declare class InstalledExtensionServiceExt extends InstalledExtensionService {
|
|
10
|
+
protected slugService: ISlugService;
|
|
11
|
+
protected readonly redisCacheManager: IRedisCacheManager;
|
|
12
|
+
constructor(repository: IInstalledExtensionRepository, registryService: IRegistryExtensionService, slugService: ISlugService, redisCacheManager: IRedisCacheManager, broker: ServiceBroker, logger: CdmLogger.ILogger);
|
|
13
|
+
private setupEventListeners;
|
|
14
|
+
private dropCache;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=installed-extension-service-ext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installed-extension-service-ext.d.ts","sourceRoot":"","sources":["../../src/services/installed-extension-service-ext.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAgBH,yBAAyB,EACzB,6BAA6B,EAO7B,YAAY,EACZ,kBAAkB,EACrB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AA0D1E;;;GAGG;AACH,qBACa,4BAA6B,SAAQ,yBAAyB;IAKnE,SAAS,CAAC,WAAW,EAAE,YAAY;IAEnC,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,kBAAkB;gBALJ,UAAU,EAAE,6BAA6B,EAC7C,eAAe,EAAE,yBAAyB,EAEhF,WAAW,EAAE,YAAY,EAEhB,iBAAiB,EAAE,kBAAkB,EACnB,MAAM,EAAE,aAAa,EAC/B,MAAM,EAAE,SAAS,CAAC,OAAO;IAMxD,OAAO,CAAC,mBAAmB;YA6gBb,SAAS;CA8C1B"}
|