@codingame/monaco-vscode-extension-gallery-service-override 1.83.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extensionGallery.d.ts +12 -0
- package/extensionGallery.js +76 -0
- package/external/rollup-plugin-styles/dist/runtime/inject-css.js +3 -0
- package/external/tslib/tslib.es6.js +11 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/override/vs/platform/dialogs/common/dialogs.js +8 -0
- package/package.json +30 -0
- package/vscode/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.js +784 -0
- package/vscode/src/vs/platform/extensionManagement/common/extensionEnablementService.js +142 -0
- package/vscode/src/vs/platform/extensionManagement/common/extensionGalleryService.js +855 -0
- package/vscode/src/vs/platform/extensionManagement/common/extensionManagementIpc.js +119 -0
- package/vscode/src/vs/platform/extensionManagement/common/extensionTipsService.js +57 -0
- package/vscode/src/vs/platform/extensionManagement/common/unsupportedExtensionsMigration.js +58 -0
- package/vscode/src/vs/platform/externalServices/common/marketplace.js +17 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.js +492 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/browserRuntimeExtensionsEditor.js +28 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/configBasedRecommendations.js +78 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/deprecatedExtensionsChecker.js +87 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/exeBasedRecommendations.js +60 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionEditor.js +1868 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionEnablementWorkspaceTrustTransitionParticipant.js +52 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.js +437 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionRecommendations.js +17 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionRecommendationsService.js +221 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensions.contribution.js +2063 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensions.web.contribution.js +13 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsActivationProgress.js +46 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsCompletionItemsProvider.js +65 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsDependencyChecker.js +98 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsList.js +224 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsQuickAccess.js +121 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsViewer.js +285 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.js +912 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsViews.js +1270 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.js +824 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.js +1730 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/fileBasedRecommendations.js +324 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/keymapRecommendations.js +28 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/languageRecommendations.js +28 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/media/extension.css.js +6 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css.js +6 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/media/extensionsViewlet.css.js +6 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/media/extensionsWidgets.css.js +6 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/media/runtimeExtensionsEditor.css.js +6 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/remoteRecommendations.js +29 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/unsupportedExtensionsMigrationContribution.js +26 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/webRecommendations.js +38 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/workspaceRecommendations.js +88 -0
- package/vscode/src/vs/workbench/contrib/extensions/common/extensionQuery.js +67 -0
- package/vscode/src/vs/workbench/contrib/extensions/common/extensionsInput.js +43 -0
- package/vscode/src/vs/workbench/contrib/extensions/common/extensionsUtils.js +104 -0
- package/vscode/src/vs/workbench/contrib/extensions/common/reportExtensionIssueAction.js +31 -0
- package/vscode/src/vs/workbench/contrib/extensions/common/runtimeExtensionsInput.js +41 -0
- package/vscode/src/vs/workbench/contrib/markdown/browser/markdownDocumentRenderer.js +207 -0
- package/vscode/src/vs/workbench/contrib/update/common/update.js +3 -0
- package/vscode/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.js +84 -0
- package/vscode/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.js +634 -0
- package/vscode/src/vs/workbench/services/extensionManagement/browser/webExtensionsScannerService.js +883 -0
- package/vscode/src/vs/workbench/services/extensionManagement/common/extensionManagementChannelClient.js +109 -0
- package/vscode/src/vs/workbench/services/extensionManagement/common/extensionManagementServerService.js +62 -0
- package/vscode/src/vs/workbench/services/extensionManagement/common/extensionManagementService.js +633 -0
- package/vscode/src/vs/workbench/services/extensionManagement/common/remoteExtensionManagementService.js +58 -0
- package/vscode/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.js +269 -0
- package/vscode/src/vs/workbench/services/extensionRecommendations/common/extensionIgnoredRecommendationsService.js +83 -0
- package/vscode/src/vs/workbench/services/remote/common/remoteExtensionsScanner.js +73 -0
|
@@ -0,0 +1,855 @@
|
|
|
1
|
+
import { __decorate, __param } from '../../../../../../external/tslib/tslib.es6.js';
|
|
2
|
+
import { distinct } from 'monaco-editor/esm/vs/base/common/arrays.js';
|
|
3
|
+
import { CancellationToken } from 'monaco-editor/esm/vs/base/common/cancellation.js';
|
|
4
|
+
import { getErrorMessage, isCancellationError, CancellationError } from 'monaco-editor/esm/vs/base/common/errors.js';
|
|
5
|
+
import { isWeb, platform } from 'monaco-editor/esm/vs/base/common/platform.js';
|
|
6
|
+
import { arch } from 'monaco-editor/esm/vs/base/common/process.js';
|
|
7
|
+
import { isBoolean } from 'monaco-editor/esm/vs/base/common/types.js';
|
|
8
|
+
import { URI } from 'monaco-editor/esm/vs/base/common/uri.js';
|
|
9
|
+
import { IConfigurationService } from 'monaco-editor/esm/vs/platform/configuration/common/configuration.js';
|
|
10
|
+
import { IEnvironmentService } from 'monaco-editor/esm/vs/platform/environment/common/environment.js';
|
|
11
|
+
import { getTargetPlatform, isNotWebExtensionInWebTargetPlatform, isTargetPlatformCompatible, toTargetPlatform, WEB_EXTENSION_TAG, getFallbackTargetPlarforms } from 'vscode/vscode/vs/platform/extensionManagement/common/extensionManagement';
|
|
12
|
+
import { getGalleryExtensionId, areSameExtensions, getGalleryExtensionTelemetryData, adoptToGalleryExtensionId } from 'vscode/vscode/vs/platform/extensionManagement/common/extensionManagementUtil';
|
|
13
|
+
import { isEngineValid } from 'vscode/vscode/vs/platform/extensions/common/extensionValidator';
|
|
14
|
+
import { IFileService } from 'monaco-editor/esm/vs/platform/files/common/files.js';
|
|
15
|
+
import { ILogService } from 'monaco-editor/esm/vs/platform/log/common/log.js';
|
|
16
|
+
import { IProductService } from 'monaco-editor/esm/vs/platform/product/common/productService.js';
|
|
17
|
+
import { asJson, isSuccess, asTextOrError, IRequestService } from 'vscode/vscode/vs/platform/request/common/request';
|
|
18
|
+
import { resolveMarketplaceHeaders } from '../../externalServices/common/marketplace.js';
|
|
19
|
+
import { IStorageService } from 'monaco-editor/esm/vs/platform/storage/common/storage.js';
|
|
20
|
+
import { ITelemetryService } from 'monaco-editor/esm/vs/platform/telemetry/common/telemetry.js';
|
|
21
|
+
import { StopWatch } from 'monaco-editor/esm/vs/base/common/stopwatch.js';
|
|
22
|
+
|
|
23
|
+
const CURRENT_TARGET_PLATFORM = isWeb ? "web" : getTargetPlatform(platform, arch);
|
|
24
|
+
const ACTIVITY_HEADER_NAME = 'X-Market-Search-Activity-Id';
|
|
25
|
+
var Flags;
|
|
26
|
+
( (function(Flags) {
|
|
27
|
+
Flags[Flags["None"] = 0] = "None";
|
|
28
|
+
Flags[Flags["IncludeVersions"] = 1] = "IncludeVersions";
|
|
29
|
+
Flags[Flags["IncludeFiles"] = 2] = "IncludeFiles";
|
|
30
|
+
Flags[Flags["IncludeCategoryAndTags"] = 4] = "IncludeCategoryAndTags";
|
|
31
|
+
Flags[Flags["IncludeSharedAccounts"] = 8] = "IncludeSharedAccounts";
|
|
32
|
+
Flags[Flags["IncludeVersionProperties"] = 16] = "IncludeVersionProperties";
|
|
33
|
+
Flags[Flags["ExcludeNonValidated"] = 32] = "ExcludeNonValidated";
|
|
34
|
+
Flags[Flags["IncludeInstallationTargets"] = 64] = "IncludeInstallationTargets";
|
|
35
|
+
Flags[Flags["IncludeAssetUri"] = 128] = "IncludeAssetUri";
|
|
36
|
+
Flags[Flags["IncludeStatistics"] = 256] = "IncludeStatistics";
|
|
37
|
+
Flags[Flags["IncludeLatestVersionOnly"] = 512] = "IncludeLatestVersionOnly";
|
|
38
|
+
Flags[Flags["Unpublished"] = 4096] = "Unpublished";
|
|
39
|
+
Flags[Flags["IncludeNameConflictInfo"] = 32768] = "IncludeNameConflictInfo";
|
|
40
|
+
})(Flags || (Flags = {})));
|
|
41
|
+
function flagsToString(...flags) {
|
|
42
|
+
return String(flags.reduce((r, f) => r | f, 0));
|
|
43
|
+
}
|
|
44
|
+
var FilterType;
|
|
45
|
+
( (function(FilterType) {
|
|
46
|
+
FilterType[FilterType["Tag"] = 1] = "Tag";
|
|
47
|
+
FilterType[FilterType["ExtensionId"] = 4] = "ExtensionId";
|
|
48
|
+
FilterType[FilterType["Category"] = 5] = "Category";
|
|
49
|
+
FilterType[FilterType["ExtensionName"] = 7] = "ExtensionName";
|
|
50
|
+
FilterType[FilterType["Target"] = 8] = "Target";
|
|
51
|
+
FilterType[FilterType["Featured"] = 9] = "Featured";
|
|
52
|
+
FilterType[FilterType["SearchText"] = 10] = "SearchText";
|
|
53
|
+
FilterType[FilterType["ExcludeWithFlags"] = 12] = "ExcludeWithFlags";
|
|
54
|
+
})(FilterType || (FilterType = {})));
|
|
55
|
+
const AssetType = {
|
|
56
|
+
Icon: 'Microsoft.VisualStudio.Services.Icons.Default',
|
|
57
|
+
Details: 'Microsoft.VisualStudio.Services.Content.Details',
|
|
58
|
+
Changelog: 'Microsoft.VisualStudio.Services.Content.Changelog',
|
|
59
|
+
Manifest: 'Microsoft.VisualStudio.Code.Manifest',
|
|
60
|
+
VSIX: 'Microsoft.VisualStudio.Services.VSIXPackage',
|
|
61
|
+
License: 'Microsoft.VisualStudio.Services.Content.License',
|
|
62
|
+
Repository: 'Microsoft.VisualStudio.Services.Links.Source',
|
|
63
|
+
Signature: 'Microsoft.VisualStudio.Services.VsixSignature'
|
|
64
|
+
};
|
|
65
|
+
const PropertyType = {
|
|
66
|
+
Dependency: 'Microsoft.VisualStudio.Code.ExtensionDependencies',
|
|
67
|
+
ExtensionPack: 'Microsoft.VisualStudio.Code.ExtensionPack',
|
|
68
|
+
Engine: 'Microsoft.VisualStudio.Code.Engine',
|
|
69
|
+
PreRelease: 'Microsoft.VisualStudio.Code.PreRelease',
|
|
70
|
+
LocalizedLanguages: 'Microsoft.VisualStudio.Code.LocalizedLanguages',
|
|
71
|
+
WebExtension: 'Microsoft.VisualStudio.Code.WebExtension',
|
|
72
|
+
SponsorLink: 'Microsoft.VisualStudio.Code.SponsorLink'
|
|
73
|
+
};
|
|
74
|
+
const DefaultPageSize = 10;
|
|
75
|
+
const DefaultQueryState = {
|
|
76
|
+
pageNumber: 1,
|
|
77
|
+
pageSize: DefaultPageSize,
|
|
78
|
+
sortBy: 0 ,
|
|
79
|
+
sortOrder: 0 ,
|
|
80
|
+
flags: Flags.None,
|
|
81
|
+
criteria: [],
|
|
82
|
+
assetTypes: []
|
|
83
|
+
};
|
|
84
|
+
class Query {
|
|
85
|
+
constructor(state = DefaultQueryState) {
|
|
86
|
+
this.state = state;
|
|
87
|
+
}
|
|
88
|
+
get pageNumber() { return this.state.pageNumber; }
|
|
89
|
+
get pageSize() { return this.state.pageSize; }
|
|
90
|
+
get sortBy() { return this.state.sortBy; }
|
|
91
|
+
get sortOrder() { return this.state.sortOrder; }
|
|
92
|
+
get flags() { return this.state.flags; }
|
|
93
|
+
get criteria() { return this.state.criteria; }
|
|
94
|
+
withPage(pageNumber, pageSize = this.state.pageSize) {
|
|
95
|
+
return ( new Query({ ...this.state, pageNumber, pageSize }));
|
|
96
|
+
}
|
|
97
|
+
withFilter(filterType, ...values) {
|
|
98
|
+
const criteria = [
|
|
99
|
+
...this.state.criteria,
|
|
100
|
+
...(values.length ? ( values.map(value => ({ filterType, value }))) : [{ filterType }])
|
|
101
|
+
];
|
|
102
|
+
return ( new Query({ ...this.state, criteria }));
|
|
103
|
+
}
|
|
104
|
+
withSortBy(sortBy) {
|
|
105
|
+
return ( new Query({ ...this.state, sortBy }));
|
|
106
|
+
}
|
|
107
|
+
withSortOrder(sortOrder) {
|
|
108
|
+
return ( new Query({ ...this.state, sortOrder }));
|
|
109
|
+
}
|
|
110
|
+
withFlags(...flags) {
|
|
111
|
+
return ( new Query({ ...this.state, flags: flags.reduce((r, f) => r | f, 0) }));
|
|
112
|
+
}
|
|
113
|
+
withAssetTypes(...assetTypes) {
|
|
114
|
+
return ( new Query({ ...this.state, assetTypes }));
|
|
115
|
+
}
|
|
116
|
+
withSource(source) {
|
|
117
|
+
return ( new Query({ ...this.state, source }));
|
|
118
|
+
}
|
|
119
|
+
get raw() {
|
|
120
|
+
const { criteria, pageNumber, pageSize, sortBy, sortOrder, flags, assetTypes } = this.state;
|
|
121
|
+
const filters = [{ criteria, pageNumber, pageSize, sortBy, sortOrder }];
|
|
122
|
+
return { filters, assetTypes, flags };
|
|
123
|
+
}
|
|
124
|
+
get searchText() {
|
|
125
|
+
const criterium = this.state.criteria.filter(criterium => criterium.filterType === FilterType.SearchText)[0];
|
|
126
|
+
return criterium && criterium.value ? criterium.value : '';
|
|
127
|
+
}
|
|
128
|
+
get telemetryData() {
|
|
129
|
+
return {
|
|
130
|
+
filterTypes: ( this.state.criteria.map(criterium => String(criterium.filterType))),
|
|
131
|
+
flags: this.state.flags,
|
|
132
|
+
sortBy: String(this.sortBy),
|
|
133
|
+
sortOrder: String(this.sortOrder),
|
|
134
|
+
pageNumber: String(this.pageNumber),
|
|
135
|
+
source: this.state.source,
|
|
136
|
+
searchTextLength: this.searchText.length
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function getStatistic(statistics, name) {
|
|
141
|
+
const result = (statistics || []).filter(s => s.statisticName === name)[0];
|
|
142
|
+
return result ? result.value : 0;
|
|
143
|
+
}
|
|
144
|
+
function getCoreTranslationAssets(version) {
|
|
145
|
+
const coreTranslationAssetPrefix = 'Microsoft.VisualStudio.Code.Translation.';
|
|
146
|
+
const result = version.files.filter(f => f.assetType.indexOf(coreTranslationAssetPrefix) === 0);
|
|
147
|
+
return result.reduce((result, file) => {
|
|
148
|
+
const asset = getVersionAsset(version, file.assetType);
|
|
149
|
+
if (asset) {
|
|
150
|
+
result.push([file.assetType.substring(coreTranslationAssetPrefix.length), asset]);
|
|
151
|
+
}
|
|
152
|
+
return result;
|
|
153
|
+
}, []);
|
|
154
|
+
}
|
|
155
|
+
function getRepositoryAsset(version) {
|
|
156
|
+
if (version.properties) {
|
|
157
|
+
const results = version.properties.filter(p => p.key === AssetType.Repository);
|
|
158
|
+
const gitRegExp = ( new RegExp('((git|ssh|http(s)?)|(git@[\\w.]+))(:(//)?)([\\w.@:/\\-~]+)(.git)(/)?'));
|
|
159
|
+
const uri = results.filter(r => gitRegExp.test(r.value))[0];
|
|
160
|
+
return uri ? { uri: uri.value, fallbackUri: uri.value } : null;
|
|
161
|
+
}
|
|
162
|
+
return getVersionAsset(version, AssetType.Repository);
|
|
163
|
+
}
|
|
164
|
+
function getDownloadAsset(version) {
|
|
165
|
+
return {
|
|
166
|
+
uri: `${version.fallbackAssetUri}/${AssetType.VSIX}?redirect=true${version.targetPlatform ? `&targetPlatform=${version.targetPlatform}` : ''}`,
|
|
167
|
+
fallbackUri: `${version.fallbackAssetUri}/${AssetType.VSIX}${version.targetPlatform ? `?targetPlatform=${version.targetPlatform}` : ''}`
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
function getVersionAsset(version, type) {
|
|
171
|
+
const result = version.files.filter(f => f.assetType === type)[0];
|
|
172
|
+
return result ? {
|
|
173
|
+
uri: `${version.assetUri}/${type}${version.targetPlatform ? `?targetPlatform=${version.targetPlatform}` : ''}`,
|
|
174
|
+
fallbackUri: `${version.fallbackAssetUri}/${type}${version.targetPlatform ? `?targetPlatform=${version.targetPlatform}` : ''}`
|
|
175
|
+
} : null;
|
|
176
|
+
}
|
|
177
|
+
function getExtensions(version, property) {
|
|
178
|
+
const values = version.properties ? version.properties.filter(p => p.key === property) : [];
|
|
179
|
+
const value = values.length > 0 && values[0].value;
|
|
180
|
+
return value ? ( value.split(',').map(v => adoptToGalleryExtensionId(v))) : [];
|
|
181
|
+
}
|
|
182
|
+
function getEngine(version) {
|
|
183
|
+
const values = version.properties ? version.properties.filter(p => p.key === PropertyType.Engine) : [];
|
|
184
|
+
return (values.length > 0 && values[0].value) || '';
|
|
185
|
+
}
|
|
186
|
+
function isPreReleaseVersion(version) {
|
|
187
|
+
const values = version.properties ? version.properties.filter(p => p.key === PropertyType.PreRelease) : [];
|
|
188
|
+
return values.length > 0 && values[0].value === 'true';
|
|
189
|
+
}
|
|
190
|
+
function getLocalizedLanguages(version) {
|
|
191
|
+
const values = version.properties ? version.properties.filter(p => p.key === PropertyType.LocalizedLanguages) : [];
|
|
192
|
+
const value = (values.length > 0 && values[0].value) || '';
|
|
193
|
+
return value ? value.split(',') : [];
|
|
194
|
+
}
|
|
195
|
+
function getSponsorLink(version) {
|
|
196
|
+
return version.properties?.find(p => p.key === PropertyType.SponsorLink)?.value;
|
|
197
|
+
}
|
|
198
|
+
function getIsPreview(flags) {
|
|
199
|
+
return flags.indexOf('preview') !== -1;
|
|
200
|
+
}
|
|
201
|
+
function getTargetPlatformForExtensionVersion(version) {
|
|
202
|
+
return version.targetPlatform ? toTargetPlatform(version.targetPlatform) : "undefined" ;
|
|
203
|
+
}
|
|
204
|
+
function getAllTargetPlatforms(rawGalleryExtension) {
|
|
205
|
+
const allTargetPlatforms = distinct(( rawGalleryExtension.versions.map(getTargetPlatformForExtensionVersion)));
|
|
206
|
+
const isWebExtension = !!rawGalleryExtension.tags?.includes(WEB_EXTENSION_TAG);
|
|
207
|
+
const webTargetPlatformIndex = allTargetPlatforms.indexOf("web" );
|
|
208
|
+
if (isWebExtension) {
|
|
209
|
+
if (webTargetPlatformIndex === -1) {
|
|
210
|
+
allTargetPlatforms.push("web" );
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
if (webTargetPlatformIndex !== -1) {
|
|
215
|
+
allTargetPlatforms.splice(webTargetPlatformIndex, 1);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return allTargetPlatforms;
|
|
219
|
+
}
|
|
220
|
+
function sortExtensionVersions(versions, preferredTargetPlatform) {
|
|
221
|
+
const fallbackTargetPlatforms = getFallbackTargetPlarforms(preferredTargetPlatform);
|
|
222
|
+
for (let index = 0; index < versions.length; index++) {
|
|
223
|
+
const version = versions[index];
|
|
224
|
+
if (version.version === versions[index - 1]?.version) {
|
|
225
|
+
let insertionIndex = index;
|
|
226
|
+
const versionTargetPlatform = getTargetPlatformForExtensionVersion(version);
|
|
227
|
+
if (versionTargetPlatform === preferredTargetPlatform) {
|
|
228
|
+
while (insertionIndex > 0 && versions[insertionIndex - 1].version === version.version) {
|
|
229
|
+
insertionIndex--;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else if (fallbackTargetPlatforms.includes(versionTargetPlatform)) {
|
|
233
|
+
while (insertionIndex > 0 && versions[insertionIndex - 1].version === version.version && getTargetPlatformForExtensionVersion(versions[insertionIndex - 1]) !== preferredTargetPlatform) {
|
|
234
|
+
insertionIndex--;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (insertionIndex !== index) {
|
|
238
|
+
versions.splice(index, 1);
|
|
239
|
+
versions.splice(insertionIndex, 0, version);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return versions;
|
|
244
|
+
}
|
|
245
|
+
function setTelemetry(extension, index, querySource) {
|
|
246
|
+
extension.telemetryData = { index, querySource, queryActivityId: extension.queryContext?.[ACTIVITY_HEADER_NAME] };
|
|
247
|
+
}
|
|
248
|
+
function toExtension(galleryExtension, version, allTargetPlatforms, queryContext) {
|
|
249
|
+
const latestVersion = galleryExtension.versions[0];
|
|
250
|
+
const assets = {
|
|
251
|
+
manifest: getVersionAsset(version, AssetType.Manifest),
|
|
252
|
+
readme: getVersionAsset(version, AssetType.Details),
|
|
253
|
+
changelog: getVersionAsset(version, AssetType.Changelog),
|
|
254
|
+
license: getVersionAsset(version, AssetType.License),
|
|
255
|
+
repository: getRepositoryAsset(version),
|
|
256
|
+
download: getDownloadAsset(version),
|
|
257
|
+
icon: getVersionAsset(version, AssetType.Icon),
|
|
258
|
+
signature: getVersionAsset(version, AssetType.Signature),
|
|
259
|
+
coreTranslations: getCoreTranslationAssets(version)
|
|
260
|
+
};
|
|
261
|
+
return {
|
|
262
|
+
identifier: {
|
|
263
|
+
id: getGalleryExtensionId(galleryExtension.publisher.publisherName, galleryExtension.extensionName),
|
|
264
|
+
uuid: galleryExtension.extensionId
|
|
265
|
+
},
|
|
266
|
+
name: galleryExtension.extensionName,
|
|
267
|
+
version: version.version,
|
|
268
|
+
displayName: galleryExtension.displayName,
|
|
269
|
+
publisherId: galleryExtension.publisher.publisherId,
|
|
270
|
+
publisher: galleryExtension.publisher.publisherName,
|
|
271
|
+
publisherDisplayName: galleryExtension.publisher.displayName,
|
|
272
|
+
publisherDomain: galleryExtension.publisher.domain ? { link: galleryExtension.publisher.domain, verified: !!galleryExtension.publisher.isDomainVerified } : undefined,
|
|
273
|
+
publisherSponsorLink: getSponsorLink(latestVersion),
|
|
274
|
+
description: galleryExtension.shortDescription || '',
|
|
275
|
+
installCount: getStatistic(galleryExtension.statistics, 'install'),
|
|
276
|
+
rating: getStatistic(galleryExtension.statistics, 'averagerating'),
|
|
277
|
+
ratingCount: getStatistic(galleryExtension.statistics, 'ratingcount'),
|
|
278
|
+
categories: galleryExtension.categories || [],
|
|
279
|
+
tags: galleryExtension.tags || [],
|
|
280
|
+
releaseDate: Date.parse(galleryExtension.releaseDate),
|
|
281
|
+
lastUpdated: Date.parse(galleryExtension.lastUpdated),
|
|
282
|
+
allTargetPlatforms,
|
|
283
|
+
assets,
|
|
284
|
+
properties: {
|
|
285
|
+
dependencies: getExtensions(version, PropertyType.Dependency),
|
|
286
|
+
extensionPack: getExtensions(version, PropertyType.ExtensionPack),
|
|
287
|
+
engine: getEngine(version),
|
|
288
|
+
localizedLanguages: getLocalizedLanguages(version),
|
|
289
|
+
targetPlatform: getTargetPlatformForExtensionVersion(version),
|
|
290
|
+
isPreReleaseVersion: isPreReleaseVersion(version)
|
|
291
|
+
},
|
|
292
|
+
hasPreReleaseVersion: isPreReleaseVersion(latestVersion),
|
|
293
|
+
hasReleaseVersion: true,
|
|
294
|
+
preview: getIsPreview(galleryExtension.flags),
|
|
295
|
+
isSigned: !!assets.signature,
|
|
296
|
+
queryContext
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
let AbstractExtensionGalleryService = class AbstractExtensionGalleryService {
|
|
300
|
+
constructor(storageService, requestService, logService, environmentService, telemetryService, fileService, productService, configurationService) {
|
|
301
|
+
this.requestService = requestService;
|
|
302
|
+
this.logService = logService;
|
|
303
|
+
this.environmentService = environmentService;
|
|
304
|
+
this.telemetryService = telemetryService;
|
|
305
|
+
this.fileService = fileService;
|
|
306
|
+
this.productService = productService;
|
|
307
|
+
this.configurationService = configurationService;
|
|
308
|
+
const config = productService.extensionsGallery;
|
|
309
|
+
const isPPEEnabled = config?.servicePPEUrl && configurationService.getValue('_extensionsGallery.enablePPE');
|
|
310
|
+
this.extensionsGalleryUrl = isPPEEnabled ? config.servicePPEUrl : config?.serviceUrl;
|
|
311
|
+
this.extensionsGallerySearchUrl = isPPEEnabled ? undefined : config?.searchUrl;
|
|
312
|
+
this.extensionsControlUrl = config?.controlUrl;
|
|
313
|
+
this.commonHeadersPromise = resolveMarketplaceHeaders(productService.version, productService, this.environmentService, this.configurationService, this.fileService, storageService, this.telemetryService);
|
|
314
|
+
}
|
|
315
|
+
api(path = '') {
|
|
316
|
+
return `${this.extensionsGalleryUrl}${path}`;
|
|
317
|
+
}
|
|
318
|
+
isEnabled() {
|
|
319
|
+
return !!this.extensionsGalleryUrl;
|
|
320
|
+
}
|
|
321
|
+
async getExtensions(extensionInfos, arg1, arg2) {
|
|
322
|
+
const options = CancellationToken.isCancellationToken(arg1) ? {} : arg1;
|
|
323
|
+
const token = CancellationToken.isCancellationToken(arg1) ? arg1 : arg2;
|
|
324
|
+
const names = [];
|
|
325
|
+
const ids = [], includePreReleases = [], versions = [];
|
|
326
|
+
let isQueryForReleaseVersionFromPreReleaseVersion = true;
|
|
327
|
+
for (const extensionInfo of extensionInfos) {
|
|
328
|
+
if (extensionInfo.uuid) {
|
|
329
|
+
ids.push(extensionInfo.uuid);
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
names.push(extensionInfo.id);
|
|
333
|
+
}
|
|
334
|
+
const includePreRelease = !!(extensionInfo.version || extensionInfo.preRelease);
|
|
335
|
+
includePreReleases.push({ id: extensionInfo.id, uuid: extensionInfo.uuid, includePreRelease });
|
|
336
|
+
if (extensionInfo.version) {
|
|
337
|
+
versions.push({ id: extensionInfo.id, uuid: extensionInfo.uuid, version: extensionInfo.version });
|
|
338
|
+
}
|
|
339
|
+
isQueryForReleaseVersionFromPreReleaseVersion = isQueryForReleaseVersionFromPreReleaseVersion && (!!extensionInfo.hasPreRelease && !includePreRelease);
|
|
340
|
+
}
|
|
341
|
+
if (!ids.length && !names.length) {
|
|
342
|
+
return [];
|
|
343
|
+
}
|
|
344
|
+
let query = ( new Query()).withPage(1, extensionInfos.length);
|
|
345
|
+
if (ids.length) {
|
|
346
|
+
query = query.withFilter(FilterType.ExtensionId, ...ids);
|
|
347
|
+
}
|
|
348
|
+
if (names.length) {
|
|
349
|
+
query = query.withFilter(FilterType.ExtensionName, ...names);
|
|
350
|
+
}
|
|
351
|
+
if (options.queryAllVersions || isQueryForReleaseVersionFromPreReleaseVersion ) {
|
|
352
|
+
query = query.withFlags(query.flags, Flags.IncludeVersions);
|
|
353
|
+
}
|
|
354
|
+
if (options.source) {
|
|
355
|
+
query = query.withSource(options.source);
|
|
356
|
+
}
|
|
357
|
+
const { extensions } = await this.queryGalleryExtensions(query, { targetPlatform: options.targetPlatform ?? CURRENT_TARGET_PLATFORM, includePreRelease: includePreReleases, versions, compatible: !!options.compatible }, token);
|
|
358
|
+
if (options.source) {
|
|
359
|
+
extensions.forEach((e, index) => setTelemetry(e, index, options.source));
|
|
360
|
+
}
|
|
361
|
+
return extensions;
|
|
362
|
+
}
|
|
363
|
+
async getCompatibleExtension(extension, includePreRelease, targetPlatform) {
|
|
364
|
+
if (isNotWebExtensionInWebTargetPlatform(extension.allTargetPlatforms, targetPlatform)) {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
if (await this.isExtensionCompatible(extension, includePreRelease, targetPlatform)) {
|
|
368
|
+
return extension;
|
|
369
|
+
}
|
|
370
|
+
const query = ( new Query())
|
|
371
|
+
.withFlags(Flags.IncludeVersions)
|
|
372
|
+
.withPage(1, 1)
|
|
373
|
+
.withFilter(FilterType.ExtensionId, extension.identifier.uuid);
|
|
374
|
+
const { extensions } = await this.queryGalleryExtensions(query, { targetPlatform, compatible: true, includePreRelease }, CancellationToken.None);
|
|
375
|
+
return extensions[0] || null;
|
|
376
|
+
}
|
|
377
|
+
async isExtensionCompatible(extension, includePreRelease, targetPlatform) {
|
|
378
|
+
if (!isTargetPlatformCompatible(extension.properties.targetPlatform, extension.allTargetPlatforms, targetPlatform)) {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
if (!includePreRelease && extension.properties.isPreReleaseVersion) {
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
let engine = extension.properties.engine;
|
|
385
|
+
if (!engine) {
|
|
386
|
+
const manifest = await this.getManifest(extension, CancellationToken.None);
|
|
387
|
+
if (!manifest) {
|
|
388
|
+
throw new Error('Manifest was not found');
|
|
389
|
+
}
|
|
390
|
+
engine = manifest.engines.vscode;
|
|
391
|
+
}
|
|
392
|
+
return isEngineValid(engine, this.productService.version, this.productService.date);
|
|
393
|
+
}
|
|
394
|
+
async isValidVersion(rawGalleryExtensionVersion, versionType, compatible, allTargetPlatforms, targetPlatform) {
|
|
395
|
+
if (!isTargetPlatformCompatible(getTargetPlatformForExtensionVersion(rawGalleryExtensionVersion), allTargetPlatforms, targetPlatform)) {
|
|
396
|
+
return false;
|
|
397
|
+
}
|
|
398
|
+
if (versionType !== 'any' && isPreReleaseVersion(rawGalleryExtensionVersion) !== (versionType === 'prerelease')) {
|
|
399
|
+
return false;
|
|
400
|
+
}
|
|
401
|
+
if (compatible) {
|
|
402
|
+
try {
|
|
403
|
+
const engine = await this.getEngine(rawGalleryExtensionVersion);
|
|
404
|
+
if (!isEngineValid(engine, this.productService.version, this.productService.date)) {
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
this.logService.error(`Error while getting the engine for the version ${rawGalleryExtensionVersion.version}.`, getErrorMessage(error));
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
async query(options, token) {
|
|
416
|
+
let text = options.text || '';
|
|
417
|
+
const pageSize = options.pageSize ?? 50;
|
|
418
|
+
let query = ( new Query())
|
|
419
|
+
.withPage(1, pageSize);
|
|
420
|
+
if (text) {
|
|
421
|
+
text = text.replace(/\bcategory:("([^"]*)"|([^"]\S*))(\s+|\b|$)/g, (_, quotedCategory, category) => {
|
|
422
|
+
query = query.withFilter(FilterType.Category, category || quotedCategory);
|
|
423
|
+
return '';
|
|
424
|
+
});
|
|
425
|
+
text = text.replace(/\btag:("([^"]*)"|([^"]\S*))(\s+|\b|$)/g, (_, quotedTag, tag) => {
|
|
426
|
+
query = query.withFilter(FilterType.Tag, tag || quotedTag);
|
|
427
|
+
return '';
|
|
428
|
+
});
|
|
429
|
+
text = text.replace(/\bfeatured(\s+|\b|$)/g, () => {
|
|
430
|
+
query = query.withFilter(FilterType.Featured);
|
|
431
|
+
return '';
|
|
432
|
+
});
|
|
433
|
+
text = text.trim();
|
|
434
|
+
if (text) {
|
|
435
|
+
text = text.length < 200 ? text : text.substring(0, 200);
|
|
436
|
+
query = query.withFilter(FilterType.SearchText, text);
|
|
437
|
+
}
|
|
438
|
+
query = query.withSortBy(0 );
|
|
439
|
+
}
|
|
440
|
+
else if (options.ids) {
|
|
441
|
+
query = query.withFilter(FilterType.ExtensionId, ...options.ids);
|
|
442
|
+
}
|
|
443
|
+
else if (options.names) {
|
|
444
|
+
query = query.withFilter(FilterType.ExtensionName, ...options.names);
|
|
445
|
+
}
|
|
446
|
+
else {
|
|
447
|
+
query = query.withSortBy(4 );
|
|
448
|
+
}
|
|
449
|
+
if (typeof options.sortBy === 'number') {
|
|
450
|
+
query = query.withSortBy(options.sortBy);
|
|
451
|
+
}
|
|
452
|
+
if (typeof options.sortOrder === 'number') {
|
|
453
|
+
query = query.withSortOrder(options.sortOrder);
|
|
454
|
+
}
|
|
455
|
+
if (options.source) {
|
|
456
|
+
query = query.withSource(options.source);
|
|
457
|
+
}
|
|
458
|
+
const runQuery = async (query, token) => {
|
|
459
|
+
const { extensions, total } = await this.queryGalleryExtensions(query, { targetPlatform: CURRENT_TARGET_PLATFORM, compatible: false, includePreRelease: !!options.includePreRelease }, token);
|
|
460
|
+
extensions.forEach((e, index) => setTelemetry(e, ((query.pageNumber - 1) * query.pageSize) + index, options.source));
|
|
461
|
+
return { extensions, total };
|
|
462
|
+
};
|
|
463
|
+
const { extensions, total } = await runQuery(query, token);
|
|
464
|
+
const getPage = async (pageIndex, ct) => {
|
|
465
|
+
if (ct.isCancellationRequested) {
|
|
466
|
+
throw new CancellationError();
|
|
467
|
+
}
|
|
468
|
+
const { extensions } = await runQuery(query.withPage(pageIndex + 1), ct);
|
|
469
|
+
return extensions;
|
|
470
|
+
};
|
|
471
|
+
return { firstPage: extensions, total, pageSize: query.pageSize, getPage };
|
|
472
|
+
}
|
|
473
|
+
async queryGalleryExtensions(query, criteria, token) {
|
|
474
|
+
const flags = query.flags;
|
|
475
|
+
if (!!(query.flags & Flags.IncludeLatestVersionOnly) && !!(query.flags & Flags.IncludeVersions)) {
|
|
476
|
+
query = query.withFlags(query.flags & ~Flags.IncludeVersions, Flags.IncludeLatestVersionOnly);
|
|
477
|
+
}
|
|
478
|
+
if (!(query.flags & Flags.IncludeLatestVersionOnly) && !(query.flags & Flags.IncludeVersions)) {
|
|
479
|
+
query = query.withFlags(query.flags, Flags.IncludeLatestVersionOnly);
|
|
480
|
+
}
|
|
481
|
+
if (criteria.versions?.length) {
|
|
482
|
+
query = query.withFlags(query.flags & ~Flags.IncludeLatestVersionOnly, Flags.IncludeVersions);
|
|
483
|
+
}
|
|
484
|
+
query = query.withFlags(query.flags, Flags.IncludeAssetUri, Flags.IncludeCategoryAndTags, Flags.IncludeFiles, Flags.IncludeStatistics, Flags.IncludeVersionProperties);
|
|
485
|
+
const { galleryExtensions: rawGalleryExtensions, total, context } = await this.queryRawGalleryExtensions(query, token);
|
|
486
|
+
const hasAllVersions = !(query.flags & Flags.IncludeLatestVersionOnly);
|
|
487
|
+
if (hasAllVersions) {
|
|
488
|
+
const extensions = [];
|
|
489
|
+
for (const rawGalleryExtension of rawGalleryExtensions) {
|
|
490
|
+
const extension = await this.toGalleryExtensionWithCriteria(rawGalleryExtension, criteria, context);
|
|
491
|
+
if (extension) {
|
|
492
|
+
extensions.push(extension);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return { extensions, total };
|
|
496
|
+
}
|
|
497
|
+
const result = [];
|
|
498
|
+
const needAllVersions = ( new Map());
|
|
499
|
+
for (let index = 0; index < rawGalleryExtensions.length; index++) {
|
|
500
|
+
const rawGalleryExtension = rawGalleryExtensions[index];
|
|
501
|
+
const extensionIdentifier = { id: getGalleryExtensionId(rawGalleryExtension.publisher.publisherName, rawGalleryExtension.extensionName), uuid: rawGalleryExtension.extensionId };
|
|
502
|
+
const includePreRelease = isBoolean(criteria.includePreRelease) ? criteria.includePreRelease : !!criteria.includePreRelease.find(extensionIdentifierWithPreRelease => areSameExtensions(extensionIdentifierWithPreRelease, extensionIdentifier))?.includePreRelease;
|
|
503
|
+
if (criteria.compatible && isNotWebExtensionInWebTargetPlatform(getAllTargetPlatforms(rawGalleryExtension), criteria.targetPlatform)) {
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
506
|
+
const extension = await this.toGalleryExtensionWithCriteria(rawGalleryExtension, criteria, context);
|
|
507
|
+
if (!extension
|
|
508
|
+
|| (extension.properties.isPreReleaseVersion && (!includePreRelease || !extension.hasReleaseVersion))
|
|
509
|
+
|| (!extension.properties.isPreReleaseVersion && extension.properties.targetPlatform !== criteria.targetPlatform && extension.hasPreReleaseVersion)) {
|
|
510
|
+
needAllVersions.set(rawGalleryExtension.extensionId, index);
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
result.push([index, extension]);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
if (needAllVersions.size) {
|
|
517
|
+
const stopWatch = ( new StopWatch());
|
|
518
|
+
const query = ( new Query())
|
|
519
|
+
.withFlags(flags & ~Flags.IncludeLatestVersionOnly, Flags.IncludeVersions)
|
|
520
|
+
.withPage(1, needAllVersions.size)
|
|
521
|
+
.withFilter(FilterType.ExtensionId, ...( needAllVersions.keys()));
|
|
522
|
+
const { extensions } = await this.queryGalleryExtensions(query, criteria, token);
|
|
523
|
+
this.telemetryService.publicLog2('galleryService:additionalQuery', {
|
|
524
|
+
duration: stopWatch.elapsed(),
|
|
525
|
+
count: needAllVersions.size
|
|
526
|
+
});
|
|
527
|
+
for (const extension of extensions) {
|
|
528
|
+
const index = needAllVersions.get(extension.identifier.uuid);
|
|
529
|
+
result.push([index, extension]);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
return { extensions: ( result.sort((a, b) => a[0] - b[0]).map(([, extension]) => extension)), total };
|
|
533
|
+
}
|
|
534
|
+
async toGalleryExtensionWithCriteria(rawGalleryExtension, criteria, queryContext) {
|
|
535
|
+
const extensionIdentifier = { id: getGalleryExtensionId(rawGalleryExtension.publisher.publisherName, rawGalleryExtension.extensionName), uuid: rawGalleryExtension.extensionId };
|
|
536
|
+
const version = criteria.versions?.find(extensionIdentifierWithVersion => areSameExtensions(extensionIdentifierWithVersion, extensionIdentifier))?.version;
|
|
537
|
+
const includePreRelease = isBoolean(criteria.includePreRelease) ? criteria.includePreRelease : !!criteria.includePreRelease.find(extensionIdentifierWithPreRelease => areSameExtensions(extensionIdentifierWithPreRelease, extensionIdentifier))?.includePreRelease;
|
|
538
|
+
const allTargetPlatforms = getAllTargetPlatforms(rawGalleryExtension);
|
|
539
|
+
const rawGalleryExtensionVersions = sortExtensionVersions(rawGalleryExtension.versions, criteria.targetPlatform);
|
|
540
|
+
if (criteria.compatible && isNotWebExtensionInWebTargetPlatform(allTargetPlatforms, criteria.targetPlatform)) {
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
for (let index = 0; index < rawGalleryExtensionVersions.length; index++) {
|
|
544
|
+
const rawGalleryExtensionVersion = rawGalleryExtensionVersions[index];
|
|
545
|
+
if (version && rawGalleryExtensionVersion.version !== version) {
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
if (await this.isValidVersion(rawGalleryExtensionVersion, includePreRelease ? 'any' : 'release', criteria.compatible, allTargetPlatforms, criteria.targetPlatform)) {
|
|
549
|
+
return toExtension(rawGalleryExtension, rawGalleryExtensionVersion, allTargetPlatforms, queryContext);
|
|
550
|
+
}
|
|
551
|
+
if (version && rawGalleryExtensionVersion.version === version) {
|
|
552
|
+
return null;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (version || criteria.compatible) {
|
|
556
|
+
return null;
|
|
557
|
+
}
|
|
558
|
+
return toExtension(rawGalleryExtension, rawGalleryExtension.versions[0], allTargetPlatforms);
|
|
559
|
+
}
|
|
560
|
+
async queryRawGalleryExtensions(query, token) {
|
|
561
|
+
if (!this.isEnabled()) {
|
|
562
|
+
throw new Error('No extension gallery service configured.');
|
|
563
|
+
}
|
|
564
|
+
query = query
|
|
565
|
+
.withFlags(query.flags, Flags.ExcludeNonValidated)
|
|
566
|
+
.withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code')
|
|
567
|
+
.withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished));
|
|
568
|
+
const commonHeaders = await this.commonHeadersPromise;
|
|
569
|
+
const data = JSON.stringify(query.raw);
|
|
570
|
+
const headers = {
|
|
571
|
+
...commonHeaders,
|
|
572
|
+
'Content-Type': 'application/json',
|
|
573
|
+
'Accept': 'application/json;api-version=3.0-preview.1',
|
|
574
|
+
'Accept-Encoding': 'gzip',
|
|
575
|
+
'Content-Length': String(data.length),
|
|
576
|
+
};
|
|
577
|
+
const stopWatch = ( new StopWatch());
|
|
578
|
+
let context, error, total = 0;
|
|
579
|
+
try {
|
|
580
|
+
context = await this.requestService.request({
|
|
581
|
+
type: 'POST',
|
|
582
|
+
url: this.extensionsGallerySearchUrl && ( query.criteria.some(c => c.filterType === FilterType.SearchText)) ? this.extensionsGallerySearchUrl : this.api('/extensionquery'),
|
|
583
|
+
data,
|
|
584
|
+
headers
|
|
585
|
+
}, token);
|
|
586
|
+
if (context.res.statusCode && context.res.statusCode >= 400 && context.res.statusCode < 500) {
|
|
587
|
+
return { galleryExtensions: [], total };
|
|
588
|
+
}
|
|
589
|
+
const result = await asJson(context);
|
|
590
|
+
if (result) {
|
|
591
|
+
const r = result.results[0];
|
|
592
|
+
const galleryExtensions = r.extensions;
|
|
593
|
+
const resultCount = r.resultMetadata && r.resultMetadata.filter(m => m.metadataType === 'ResultCount')[0];
|
|
594
|
+
total = resultCount && resultCount.metadataItems.filter(i => i.name === 'TotalCount')[0].count || 0;
|
|
595
|
+
return {
|
|
596
|
+
galleryExtensions,
|
|
597
|
+
total,
|
|
598
|
+
context: {
|
|
599
|
+
[ACTIVITY_HEADER_NAME]: context.res.headers['activityid']
|
|
600
|
+
}
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
return { galleryExtensions: [], total };
|
|
604
|
+
}
|
|
605
|
+
catch (e) {
|
|
606
|
+
error = e;
|
|
607
|
+
throw e;
|
|
608
|
+
}
|
|
609
|
+
finally {
|
|
610
|
+
this.telemetryService.publicLog2('galleryService:query', {
|
|
611
|
+
...query.telemetryData,
|
|
612
|
+
requestBodySize: String(data.length),
|
|
613
|
+
duration: stopWatch.elapsed(),
|
|
614
|
+
success: !!context && isSuccess(context),
|
|
615
|
+
responseBodySize: context?.res.headers['Content-Length'],
|
|
616
|
+
statusCode: context ? String(context.res.statusCode) : undefined,
|
|
617
|
+
errorCode: error
|
|
618
|
+
? isCancellationError(error) ? 'canceled' : getErrorMessage(error).startsWith('XHR timeout') ? 'timeout' : 'failed'
|
|
619
|
+
: undefined,
|
|
620
|
+
count: String(total)
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
async reportStatistic(publisher, name, version, type) {
|
|
625
|
+
if (!this.isEnabled()) {
|
|
626
|
+
return undefined;
|
|
627
|
+
}
|
|
628
|
+
const url = isWeb ? this.api(`/itemName/${publisher}.${name}/version/${version}/statType/${type === "install" ? '1' : '3'}/vscodewebextension`) : this.api(`/publishers/${publisher}/extensions/${name}/${version}/stats?statType=${type}`);
|
|
629
|
+
const Accept = isWeb ? 'api-version=6.1-preview.1' : '*/*;api-version=4.0-preview.1';
|
|
630
|
+
const commonHeaders = await this.commonHeadersPromise;
|
|
631
|
+
const headers = { ...commonHeaders, Accept };
|
|
632
|
+
try {
|
|
633
|
+
await this.requestService.request({
|
|
634
|
+
type: 'POST',
|
|
635
|
+
url,
|
|
636
|
+
headers
|
|
637
|
+
}, CancellationToken.None);
|
|
638
|
+
}
|
|
639
|
+
catch (error) { }
|
|
640
|
+
}
|
|
641
|
+
async download(extension, location, operation) {
|
|
642
|
+
this.logService.trace('ExtensionGalleryService#download', extension.identifier.id);
|
|
643
|
+
const data = getGalleryExtensionTelemetryData(extension);
|
|
644
|
+
const startTime = ( new Date()).getTime();
|
|
645
|
+
const log = (duration) => this.telemetryService.publicLog('galleryService:downloadVSIX', { ...data, duration });
|
|
646
|
+
const operationParam = operation === 2 ? 'install' : operation === 3 ? 'update' : '';
|
|
647
|
+
const downloadAsset = operationParam ? {
|
|
648
|
+
uri: `${extension.assets.download.uri}${( URI.parse(extension.assets.download.uri)).query ? '&' : '?'}${operationParam}=true`,
|
|
649
|
+
fallbackUri: `${extension.assets.download.fallbackUri}${( URI.parse(extension.assets.download.fallbackUri)).query ? '&' : '?'}${operationParam}=true`
|
|
650
|
+
} : extension.assets.download;
|
|
651
|
+
const headers = extension.queryContext?.[ACTIVITY_HEADER_NAME] ? { [ACTIVITY_HEADER_NAME]: extension.queryContext[ACTIVITY_HEADER_NAME] } : undefined;
|
|
652
|
+
const context = await this.getAsset(downloadAsset, headers ? { headers } : undefined);
|
|
653
|
+
await this.fileService.writeFile(location, context.stream);
|
|
654
|
+
log(( new Date()).getTime() - startTime);
|
|
655
|
+
}
|
|
656
|
+
async downloadSignatureArchive(extension, location) {
|
|
657
|
+
if (!extension.assets.signature) {
|
|
658
|
+
throw new Error('No signature asset found');
|
|
659
|
+
}
|
|
660
|
+
this.logService.trace('ExtensionGalleryService#downloadSignatureArchive', extension.identifier.id);
|
|
661
|
+
const context = await this.getAsset(extension.assets.signature);
|
|
662
|
+
await this.fileService.writeFile(location, context.stream);
|
|
663
|
+
}
|
|
664
|
+
async getReadme(extension, token) {
|
|
665
|
+
if (extension.assets.readme) {
|
|
666
|
+
const context = await this.getAsset(extension.assets.readme, {}, token);
|
|
667
|
+
const content = await asTextOrError(context);
|
|
668
|
+
return content || '';
|
|
669
|
+
}
|
|
670
|
+
return '';
|
|
671
|
+
}
|
|
672
|
+
async getManifest(extension, token) {
|
|
673
|
+
if (extension.assets.manifest) {
|
|
674
|
+
const context = await this.getAsset(extension.assets.manifest, {}, token);
|
|
675
|
+
const text = await asTextOrError(context);
|
|
676
|
+
return text ? JSON.parse(text) : null;
|
|
677
|
+
}
|
|
678
|
+
return null;
|
|
679
|
+
}
|
|
680
|
+
async getManifestFromRawExtensionVersion(rawExtensionVersion, token) {
|
|
681
|
+
const manifestAsset = getVersionAsset(rawExtensionVersion, AssetType.Manifest);
|
|
682
|
+
if (!manifestAsset) {
|
|
683
|
+
throw new Error('Manifest was not found');
|
|
684
|
+
}
|
|
685
|
+
const headers = { 'Accept-Encoding': 'gzip' };
|
|
686
|
+
const context = await this.getAsset(manifestAsset, { headers });
|
|
687
|
+
return await asJson(context);
|
|
688
|
+
}
|
|
689
|
+
async getCoreTranslation(extension, languageId) {
|
|
690
|
+
const asset = extension.assets.coreTranslations.filter(t => t[0] === languageId.toUpperCase())[0];
|
|
691
|
+
if (asset) {
|
|
692
|
+
const context = await this.getAsset(asset[1]);
|
|
693
|
+
const text = await asTextOrError(context);
|
|
694
|
+
return text ? JSON.parse(text) : null;
|
|
695
|
+
}
|
|
696
|
+
return null;
|
|
697
|
+
}
|
|
698
|
+
async getChangelog(extension, token) {
|
|
699
|
+
if (extension.assets.changelog) {
|
|
700
|
+
const context = await this.getAsset(extension.assets.changelog, {}, token);
|
|
701
|
+
const content = await asTextOrError(context);
|
|
702
|
+
return content || '';
|
|
703
|
+
}
|
|
704
|
+
return '';
|
|
705
|
+
}
|
|
706
|
+
async getAllCompatibleVersions(extension, includePreRelease, targetPlatform) {
|
|
707
|
+
let query = ( new Query())
|
|
708
|
+
.withFlags(Flags.IncludeVersions, Flags.IncludeCategoryAndTags, Flags.IncludeFiles, Flags.IncludeVersionProperties)
|
|
709
|
+
.withPage(1, 1);
|
|
710
|
+
if (extension.identifier.uuid) {
|
|
711
|
+
query = query.withFilter(FilterType.ExtensionId, extension.identifier.uuid);
|
|
712
|
+
}
|
|
713
|
+
else {
|
|
714
|
+
query = query.withFilter(FilterType.ExtensionName, extension.identifier.id);
|
|
715
|
+
}
|
|
716
|
+
const { galleryExtensions } = await this.queryRawGalleryExtensions(query, CancellationToken.None);
|
|
717
|
+
if (!galleryExtensions.length) {
|
|
718
|
+
return [];
|
|
719
|
+
}
|
|
720
|
+
const allTargetPlatforms = getAllTargetPlatforms(galleryExtensions[0]);
|
|
721
|
+
if (isNotWebExtensionInWebTargetPlatform(allTargetPlatforms, targetPlatform)) {
|
|
722
|
+
return [];
|
|
723
|
+
}
|
|
724
|
+
const validVersions = [];
|
|
725
|
+
await Promise.all(( galleryExtensions[0].versions.map(async (version) => {
|
|
726
|
+
try {
|
|
727
|
+
if (await this.isValidVersion(version, includePreRelease ? 'any' : 'release', true, allTargetPlatforms, targetPlatform)) {
|
|
728
|
+
validVersions.push(version);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
catch (error) { }
|
|
732
|
+
})));
|
|
733
|
+
const result = [];
|
|
734
|
+
const seen = ( new Set());
|
|
735
|
+
for (const version of sortExtensionVersions(validVersions, targetPlatform)) {
|
|
736
|
+
if (!( seen.has(version.version))) {
|
|
737
|
+
seen.add(version.version);
|
|
738
|
+
result.push({ version: version.version, date: version.lastUpdated, isPreReleaseVersion: isPreReleaseVersion(version) });
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return result;
|
|
742
|
+
}
|
|
743
|
+
async getAsset(asset, options = {}, token = CancellationToken.None) {
|
|
744
|
+
const commonHeaders = await this.commonHeadersPromise;
|
|
745
|
+
const baseOptions = { type: 'GET' };
|
|
746
|
+
const headers = { ...commonHeaders, ...(options.headers || {}) };
|
|
747
|
+
options = { ...options, ...baseOptions, headers };
|
|
748
|
+
const url = asset.uri;
|
|
749
|
+
const fallbackUrl = asset.fallbackUri;
|
|
750
|
+
const firstOptions = { ...options, url };
|
|
751
|
+
try {
|
|
752
|
+
const context = await this.requestService.request(firstOptions, token);
|
|
753
|
+
if (context.res.statusCode === 200) {
|
|
754
|
+
return context;
|
|
755
|
+
}
|
|
756
|
+
const message = await asTextOrError(context);
|
|
757
|
+
throw new Error(`Expected 200, got back ${context.res.statusCode} instead.\n\n${message}`);
|
|
758
|
+
}
|
|
759
|
+
catch (err) {
|
|
760
|
+
if (isCancellationError(err)) {
|
|
761
|
+
throw err;
|
|
762
|
+
}
|
|
763
|
+
const message = getErrorMessage(err);
|
|
764
|
+
this.telemetryService.publicLog2('galleryService:cdnFallback', { url, message });
|
|
765
|
+
const fallbackOptions = { ...options, url: fallbackUrl };
|
|
766
|
+
return this.requestService.request(fallbackOptions, token);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
async getEngine(rawExtensionVersion) {
|
|
770
|
+
let engine = getEngine(rawExtensionVersion);
|
|
771
|
+
if (!engine) {
|
|
772
|
+
const manifest = await this.getManifestFromRawExtensionVersion(rawExtensionVersion, CancellationToken.None);
|
|
773
|
+
if (!manifest) {
|
|
774
|
+
throw new Error('Manifest was not found');
|
|
775
|
+
}
|
|
776
|
+
engine = manifest.engines.vscode;
|
|
777
|
+
}
|
|
778
|
+
return engine;
|
|
779
|
+
}
|
|
780
|
+
async getExtensionsControlManifest() {
|
|
781
|
+
if (!this.isEnabled()) {
|
|
782
|
+
throw new Error('No extension gallery service configured.');
|
|
783
|
+
}
|
|
784
|
+
if (!this.extensionsControlUrl) {
|
|
785
|
+
return { malicious: [], deprecated: {}, search: [] };
|
|
786
|
+
}
|
|
787
|
+
const context = await this.requestService.request({ type: 'GET', url: this.extensionsControlUrl }, CancellationToken.None);
|
|
788
|
+
if (context.res.statusCode !== 200) {
|
|
789
|
+
throw new Error('Could not get extensions report.');
|
|
790
|
+
}
|
|
791
|
+
const result = await asJson(context);
|
|
792
|
+
const malicious = [];
|
|
793
|
+
const deprecated = {};
|
|
794
|
+
const search = [];
|
|
795
|
+
if (result) {
|
|
796
|
+
for (const id of result.malicious) {
|
|
797
|
+
malicious.push({ id });
|
|
798
|
+
}
|
|
799
|
+
if (result.migrateToPreRelease) {
|
|
800
|
+
for (const [unsupportedPreReleaseExtensionId, preReleaseExtensionInfo] of Object.entries(result.migrateToPreRelease)) {
|
|
801
|
+
if (!preReleaseExtensionInfo.engine || isEngineValid(preReleaseExtensionInfo.engine, this.productService.version, this.productService.date)) {
|
|
802
|
+
deprecated[unsupportedPreReleaseExtensionId.toLowerCase()] = {
|
|
803
|
+
disallowInstall: true,
|
|
804
|
+
extension: {
|
|
805
|
+
id: preReleaseExtensionInfo.id,
|
|
806
|
+
displayName: preReleaseExtensionInfo.displayName,
|
|
807
|
+
autoMigrate: { storage: !!preReleaseExtensionInfo.migrateStorage },
|
|
808
|
+
preRelease: true
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
if (result.deprecated) {
|
|
815
|
+
for (const [deprecatedExtensionId, deprecationInfo] of Object.entries(result.deprecated)) {
|
|
816
|
+
if (deprecationInfo) {
|
|
817
|
+
deprecated[deprecatedExtensionId.toLowerCase()] = isBoolean(deprecationInfo) ? {} : deprecationInfo;
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (result.search) {
|
|
822
|
+
for (const s of result.search) {
|
|
823
|
+
search.push(s);
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
return { malicious, deprecated, search };
|
|
828
|
+
}
|
|
829
|
+
};
|
|
830
|
+
AbstractExtensionGalleryService = ( __decorate([
|
|
831
|
+
( __param(1, IRequestService)),
|
|
832
|
+
( __param(2, ILogService)),
|
|
833
|
+
( __param(3, IEnvironmentService)),
|
|
834
|
+
( __param(4, ITelemetryService)),
|
|
835
|
+
( __param(5, IFileService)),
|
|
836
|
+
( __param(6, IProductService)),
|
|
837
|
+
( __param(7, IConfigurationService))
|
|
838
|
+
], AbstractExtensionGalleryService));
|
|
839
|
+
let ExtensionGalleryService = class ExtensionGalleryService extends AbstractExtensionGalleryService {
|
|
840
|
+
constructor(storageService, requestService, logService, environmentService, telemetryService, fileService, productService, configurationService) {
|
|
841
|
+
super(storageService, requestService, logService, environmentService, telemetryService, fileService, productService, configurationService);
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
ExtensionGalleryService = ( __decorate([
|
|
845
|
+
( __param(0, IStorageService)),
|
|
846
|
+
( __param(1, IRequestService)),
|
|
847
|
+
( __param(2, ILogService)),
|
|
848
|
+
( __param(3, IEnvironmentService)),
|
|
849
|
+
( __param(4, ITelemetryService)),
|
|
850
|
+
( __param(5, IFileService)),
|
|
851
|
+
( __param(6, IProductService)),
|
|
852
|
+
( __param(7, IConfigurationService))
|
|
853
|
+
], ExtensionGalleryService));
|
|
854
|
+
|
|
855
|
+
export { ExtensionGalleryService, sortExtensionVersions };
|