@theia/vsx-registry 1.75.0-next.21 → 1.75.0-next.28
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/lib/browser/vsx-extensions-source.d.ts +5 -1
- package/lib/browser/vsx-extensions-source.d.ts.map +1 -1
- package/lib/browser/vsx-extensions-source.js +30 -3
- package/lib/browser/vsx-extensions-source.js.map +1 -1
- package/lib/browser/vsx-extensions-source.spec.js +58 -2
- package/lib/browser/vsx-extensions-source.spec.js.map +1 -1
- package/lib/browser/vsx-extensions-widget.d.ts +2 -1
- package/lib/browser/vsx-extensions-widget.d.ts.map +1 -1
- package/lib/browser/vsx-extensions-widget.js +21 -8
- package/lib/browser/vsx-extensions-widget.js.map +1 -1
- package/lib/browser/vsx-extensions-widget.spec.d.ts +2 -0
- package/lib/browser/vsx-extensions-widget.spec.d.ts.map +1 -0
- package/lib/browser/vsx-extensions-widget.spec.js +128 -0
- package/lib/browser/vsx-extensions-widget.spec.js.map +1 -0
- package/package.json +10 -10
- package/src/browser/vsx-extensions-source.spec.ts +74 -3
- package/src/browser/vsx-extensions-source.ts +29 -4
- package/src/browser/vsx-extensions-widget.spec.ts +137 -0
- package/src/browser/vsx-extensions-widget.tsx +22 -9
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { ILogger } from '@theia/core/lib/common/logger';
|
|
1
2
|
import { TreeElement, TreeSource } from '@theia/core/lib/browser/source-tree';
|
|
2
3
|
import { ContributionProvider } from '@theia/core/lib/common/contribution-provider';
|
|
3
4
|
import { PreferenceService } from '@theia/core/lib/common/preferences/preference-service';
|
|
4
5
|
import { FuzzySearch } from '@theia/core/lib/common/fuzzy-search';
|
|
5
6
|
import { VSXExtensionsModel } from './vsx-extensions-model';
|
|
6
|
-
import { ExtensionsSourceContribution } from './extensions-source-contribution';
|
|
7
|
+
import { ExtensionsSourceContribution, SearchContext, SearchResult } from './extensions-source-contribution';
|
|
7
8
|
import { VSXExtensionsSearchModel } from './vsx-extensions-search-model';
|
|
8
9
|
export declare class VSXExtensionsSourceOptions {
|
|
9
10
|
static INSTALLED: string;
|
|
@@ -19,6 +20,7 @@ export declare class VSXExtensionsSource extends TreeSource {
|
|
|
19
20
|
protected readonly searchModel: VSXExtensionsSearchModel;
|
|
20
21
|
protected readonly preferenceService: PreferenceService;
|
|
21
22
|
protected readonly fuzzySearch: FuzzySearch;
|
|
23
|
+
protected readonly logger: ILogger;
|
|
22
24
|
protected init(): void;
|
|
23
25
|
protected scheduleFireDidChange: import("lodash").DebouncedFunc<() => void>;
|
|
24
26
|
getModel(): VSXExtensionsModel;
|
|
@@ -28,6 +30,8 @@ export declare class VSXExtensionsSource extends TreeSource {
|
|
|
28
30
|
* regardless of which contribution produced them.
|
|
29
31
|
*/
|
|
30
32
|
protected collectSearchResults(contributions: ExtensionsSourceContribution[]): Promise<IterableIterator<TreeElement>>;
|
|
33
|
+
protected safeResolveForSection(contribution: ExtensionsSourceContribution): Promise<Iterable<TreeElement> | undefined>;
|
|
34
|
+
protected safeResolveSearchResults(contribution: ExtensionsSourceContribution, query: string, context: SearchContext): Promise<Iterable<SearchResult>>;
|
|
31
35
|
protected resolveForSection(contribution: ExtensionsSourceContribution): Promise<Iterable<TreeElement> | undefined>;
|
|
32
36
|
}
|
|
33
37
|
//# sourceMappingURL=vsx-extensions-source.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vsx-extensions-source.d.ts","sourceRoot":"","sources":["../../src/browser/vsx-extensions-source.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,4BAA4B,
|
|
1
|
+
{"version":3,"file":"vsx-extensions-source.d.ts","sourceRoot":"","sources":["../../src/browser/vsx-extensions-source.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,OAAO,EAAE,MAAM,+BAA+B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qCAAqC,CAAC;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,uDAAuD,CAAC;AAC1F,OAAO,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,4BAA4B,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AAC7G,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AAGzE,qBACa,0BAA0B;IACnC,MAAM,CAAC,SAAS,SAAe;IAC/B,MAAM,CAAC,QAAQ,SAAa;IAC5B,MAAM,CAAC,aAAa,SAAkB;IACtC,MAAM,CAAC,WAAW,SAAiB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;CACvB;AAED,qBACa,mBAAoB,SAAQ,UAAU;IAG/C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,0BAA0B,CAAC;IAGvD,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IAG7C,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,oBAAoB,CAAC,4BAA4B,CAAC,CAAC;IAGrF,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,wBAAwB,CAAC;IAGzD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;IAGxD,SAAS,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAG5C,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAGnC,SAAS,CAAC,IAAI,IAAI,IAAI;IAUtB,SAAS,CAAC,qBAAqB,6CAAiF;IAEhH,QAAQ,IAAI,kBAAkB;IAIxB,WAAW,IAAI,OAAO,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IA2B3D;;;OAGG;cACa,oBAAoB,CAAC,aAAa,EAAE,4BAA4B,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;cAsB3G,qBAAqB,CAAC,YAAY,EAAE,4BAA4B,GAAG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;cAS7G,wBAAwB,CAAC,YAAY,EAAE,4BAA4B,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;cAS5I,iBAAiB,CAAC,YAAY,EAAE,4BAA4B,GAAG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;CAW5H"}
|
|
@@ -18,6 +18,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
18
18
|
exports.VSXExtensionsSource = exports.VSXExtensionsSourceOptions = void 0;
|
|
19
19
|
const tslib_1 = require("tslib");
|
|
20
20
|
const inversify_1 = require("@theia/core/shared/inversify");
|
|
21
|
+
const logger_1 = require("@theia/core/lib/common/logger");
|
|
21
22
|
const source_tree_1 = require("@theia/core/lib/browser/source-tree");
|
|
22
23
|
const contribution_provider_1 = require("@theia/core/lib/common/contribution-provider");
|
|
23
24
|
const preference_service_1 = require("@theia/core/lib/common/preferences/preference-service");
|
|
@@ -62,9 +63,12 @@ let VSXExtensionsSource = class VSXExtensionsSource extends source_tree_1.TreeSo
|
|
|
62
63
|
if (this.options.id === VSXExtensionsSourceOptions.SEARCH_RESULT) {
|
|
63
64
|
return this.collectSearchResults(enabled);
|
|
64
65
|
}
|
|
66
|
+
// Resolve concurrently and isolate each contribution: a section is shared between all of
|
|
67
|
+
// them, so one that is slow (e.g. waiting on a remote registry) must not hold up the
|
|
68
|
+
// others, and one that rejects must not empty the whole section.
|
|
69
|
+
const resolved = await Promise.all(enabled.map(contribution => this.safeResolveForSection(contribution)));
|
|
65
70
|
const entries = [];
|
|
66
|
-
for (const
|
|
67
|
-
const iter = await this.resolveForSection(contribution);
|
|
71
|
+
for (const iter of resolved) {
|
|
68
72
|
if (!iter) {
|
|
69
73
|
continue;
|
|
70
74
|
}
|
|
@@ -86,7 +90,7 @@ let VSXExtensionsSource = class VSXExtensionsSource extends source_tree_1.TreeSo
|
|
|
86
90
|
const ctx = {
|
|
87
91
|
verifiedOnly: this.preferenceService.get('extensions.onlyShowVerifiedExtensions', false)
|
|
88
92
|
};
|
|
89
|
-
const results = await Promise.all(contributions.map(c =>
|
|
93
|
+
const results = await Promise.all(contributions.map(c => this.safeResolveSearchResults(c, freeText, ctx)));
|
|
90
94
|
const all = results.flatMap(r => [...r]);
|
|
91
95
|
const trimmed = freeText.trim();
|
|
92
96
|
if (!trimmed || all.length <= 1) {
|
|
@@ -99,6 +103,24 @@ let VSXExtensionsSource = class VSXExtensionsSource extends source_tree_1.TreeSo
|
|
|
99
103
|
});
|
|
100
104
|
return matches.map(m => m.item.element).values();
|
|
101
105
|
}
|
|
106
|
+
async safeResolveForSection(contribution) {
|
|
107
|
+
try {
|
|
108
|
+
return await this.resolveForSection(contribution);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
this.logger.warn(`Failed to resolve '${this.options.id}' entries of contribution '${contribution.type}'.`, error);
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
async safeResolveSearchResults(contribution, query, context) {
|
|
116
|
+
try {
|
|
117
|
+
return await (contribution.resolveSearchResults?.(query, context) ?? []);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
this.logger.warn(`Failed to resolve search results of contribution '${contribution.type}'.`, error);
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
102
124
|
async resolveForSection(contribution) {
|
|
103
125
|
switch (this.options.id) {
|
|
104
126
|
case VSXExtensionsSourceOptions.INSTALLED:
|
|
@@ -137,6 +159,11 @@ tslib_1.__decorate([
|
|
|
137
159
|
(0, inversify_1.inject)(fuzzy_search_1.FuzzySearch),
|
|
138
160
|
tslib_1.__metadata("design:type", fuzzy_search_1.FuzzySearch)
|
|
139
161
|
], VSXExtensionsSource.prototype, "fuzzySearch", void 0);
|
|
162
|
+
tslib_1.__decorate([
|
|
163
|
+
(0, inversify_1.inject)(logger_1.ILogger),
|
|
164
|
+
(0, inversify_1.named)('vsx-registry:VSXExtensionsSource'),
|
|
165
|
+
tslib_1.__metadata("design:type", Object)
|
|
166
|
+
], VSXExtensionsSource.prototype, "logger", void 0);
|
|
140
167
|
tslib_1.__decorate([
|
|
141
168
|
(0, inversify_1.postConstruct)(),
|
|
142
169
|
tslib_1.__metadata("design:type", Function),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vsx-extensions-source.js","sourceRoot":"","sources":["../../src/browser/vsx-extensions-source.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAEhF,4DAAwF;AACxF,qEAA8E;AAC9E,wFAAoF;AACpF,8FAA0F;AAC1F,sEAAkE;AAClE,iEAA4D;AAC5D,
|
|
1
|
+
{"version":3,"file":"vsx-extensions-source.js","sourceRoot":"","sources":["../../src/browser/vsx-extensions-source.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,6 +33,7 @@ catch { /* already set by a sibling spec */ }
|
|
|
33
33
|
const chai_1 = require("chai");
|
|
34
34
|
const inversify_1 = require("@theia/core/shared/inversify");
|
|
35
35
|
const core_1 = require("@theia/core");
|
|
36
|
+
const mock_logger_1 = require("@theia/core/lib/common/test/mock-logger");
|
|
36
37
|
const preference_service_1 = require("@theia/core/lib/common/preferences/preference-service");
|
|
37
38
|
const fuzzy_search_1 = require("@theia/core/lib/common/fuzzy-search");
|
|
38
39
|
const contribution_provider_1 = require("@theia/core/lib/common/contribution-provider");
|
|
@@ -59,6 +60,24 @@ class StubContribution {
|
|
|
59
60
|
return this.results;
|
|
60
61
|
}
|
|
61
62
|
}
|
|
63
|
+
/** Minimal contribution stub for the section modes (installed / built-in / recommended). */
|
|
64
|
+
class StubSectionContribution {
|
|
65
|
+
constructor(type, displayName, searchToken, installed, priority = 0) {
|
|
66
|
+
this.type = type;
|
|
67
|
+
this.displayName = displayName;
|
|
68
|
+
this.searchToken = searchToken;
|
|
69
|
+
this.installed = installed;
|
|
70
|
+
this.priority = priority;
|
|
71
|
+
this.onDidChangeEmitter = new core_1.Emitter();
|
|
72
|
+
this.onDidChange = this.onDidChangeEmitter.event;
|
|
73
|
+
}
|
|
74
|
+
resolveInstalled() {
|
|
75
|
+
return this.installed();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function makeElement(id) {
|
|
79
|
+
return { id, render: () => undefined };
|
|
80
|
+
}
|
|
62
81
|
function makeResult(id, searchableText) {
|
|
63
82
|
const element = { id, render: () => undefined };
|
|
64
83
|
return { element, searchableText };
|
|
@@ -74,9 +93,10 @@ class StubPreferenceService {
|
|
|
74
93
|
return defaultValue;
|
|
75
94
|
}
|
|
76
95
|
}
|
|
77
|
-
function buildSource(contributions, query) {
|
|
96
|
+
function buildSource(contributions, query, sectionId = vsx_extensions_source_1.VSXExtensionsSourceOptions.SEARCH_RESULT) {
|
|
78
97
|
const container = new inversify_1.Container();
|
|
79
|
-
container.bind(
|
|
98
|
+
container.bind(core_1.ILogger).toConstantValue(new mock_logger_1.MockLogger());
|
|
99
|
+
container.bind(vsx_extensions_source_1.VSXExtensionsSourceOptions).toConstantValue({ id: sectionId });
|
|
80
100
|
container.bind(vsx_extensions_model_1.VSXExtensionsModel).toConstantValue({
|
|
81
101
|
onDidChange: new core_1.Emitter().event
|
|
82
102
|
});
|
|
@@ -143,6 +163,16 @@ describe('VSXExtensionsSource.collectSearchResults', () => {
|
|
|
143
163
|
const elements = [...(await source.getElements())];
|
|
144
164
|
(0, chai_1.expect)(elements.map(e => e.id)).to.deep.equal(['mcp-1']);
|
|
145
165
|
});
|
|
166
|
+
it('keeps the hits of the other contributions when one rejects', async () => {
|
|
167
|
+
const failing = new StubContribution('extension', 'Extensions', '@extensions', []);
|
|
168
|
+
failing.resolveSearchResults = () => { throw new Error('registry unreachable'); };
|
|
169
|
+
const working = new StubContribution('mcp-server', 'MCP Servers', '@mcp', [
|
|
170
|
+
makeResult('mcp-1', 'alpha')
|
|
171
|
+
], 100);
|
|
172
|
+
const source = buildSource([failing, working], '');
|
|
173
|
+
const elements = [...(await source.getElements())];
|
|
174
|
+
(0, chai_1.expect)(elements.map(e => e.id)).to.deep.equal(['mcp-1']);
|
|
175
|
+
});
|
|
146
176
|
it('composes @-tokens, including multiple type tokens', async () => {
|
|
147
177
|
const extensions = new StubContribution('extension', 'Extensions', '@extensions', [
|
|
148
178
|
makeResult('ext-1', 'ext alpha')
|
|
@@ -158,4 +188,30 @@ describe('VSXExtensionsSource.collectSearchResults', () => {
|
|
|
158
188
|
(0, chai_1.expect)(elements.map(e => e.id).sort()).to.deep.equal(['mcp-1', 'skill-1']);
|
|
159
189
|
});
|
|
160
190
|
});
|
|
191
|
+
describe('VSXExtensionsSource section entries', () => {
|
|
192
|
+
it('keeps the entries of the other contributions when one rejects', async () => {
|
|
193
|
+
const failing = new StubSectionContribution('extension', 'Extensions', '@extensions', () => Promise.reject(new Error('registry unreachable')));
|
|
194
|
+
const working = new StubSectionContribution('mcp-server', 'MCP Servers', '@mcp', async () => [makeElement('mcp-1')], 100);
|
|
195
|
+
const source = buildSource([failing, working], '', vsx_extensions_source_1.VSXExtensionsSourceOptions.INSTALLED);
|
|
196
|
+
const elements = [...(await source.getElements())];
|
|
197
|
+
(0, chai_1.expect)(elements.map(e => e.id)).to.deep.equal(['mcp-1']);
|
|
198
|
+
});
|
|
199
|
+
it('resolves the contributions concurrently, in priority order', async () => {
|
|
200
|
+
let markSecondStarted = () => { };
|
|
201
|
+
const secondStarted = new Promise(resolve => { markSecondStarted = resolve; });
|
|
202
|
+
// The first contribution only completes once the second one has started, so this test times
|
|
203
|
+
// out if the section resolves its contributions one after the other.
|
|
204
|
+
const first = new StubSectionContribution('extension', 'Extensions', '@extensions', async () => {
|
|
205
|
+
await secondStarted;
|
|
206
|
+
return [makeElement('first')];
|
|
207
|
+
});
|
|
208
|
+
const second = new StubSectionContribution('mcp-server', 'MCP Servers', '@mcp', async () => {
|
|
209
|
+
markSecondStarted();
|
|
210
|
+
return [makeElement('second')];
|
|
211
|
+
}, 100);
|
|
212
|
+
const source = buildSource([first, second], '', vsx_extensions_source_1.VSXExtensionsSourceOptions.INSTALLED);
|
|
213
|
+
const elements = [...(await source.getElements())];
|
|
214
|
+
(0, chai_1.expect)(elements.map(e => e.id)).to.deep.equal(['first', 'second']);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
161
217
|
//# sourceMappingURL=vsx-extensions-source.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vsx-extensions-source.spec.js","sourceRoot":"","sources":["../../src/browser/vsx-extensions-source.spec.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;AAEhF,uHAAiH;AACjH,8DAAiE;AACjE,MAAM,YAAY,GAAG,IAAA,mBAAW,GAAE,CAAC;AACnC,iFAAiF;AACjF,mFAAmF;AACnF,oFAAoF;AACpF,kFAAkF;AAClF,MAAM,WAAW,GAAI,UAA8E,CAAC,iBAAiB,EAAE,SAAS,CAAC;AACjI,IAAI,WAAW,EAAE,CAAC;IACd,WAAW,CAAC,UAAU,GAAG,GAAG,EAAE,CAAC,SAAS,CAAC;AAC7C,CAAC;AACD,IAAI,CAAC;IAAC,wEAAiC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAAC,CAAC;AAAC,MAAM,CAAC,CAAC,mCAAmC,CAAC,CAAC;AAEhG,+BAA8B;AAC9B,4DAAyD;AACzD,
|
|
1
|
+
{"version":3,"file":"vsx-extensions-source.spec.js","sourceRoot":"","sources":["../../src/browser/vsx-extensions-source.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,7 +26,8 @@ export declare class VSXExtensionsWidget extends SourceTreeWidget implements Bad
|
|
|
26
26
|
get badgeTooltip(): string | undefined;
|
|
27
27
|
set badgeTooltip(tooltip: string | undefined);
|
|
28
28
|
protected computeTitle(): string;
|
|
29
|
-
protected
|
|
29
|
+
protected updateBadge(): void;
|
|
30
|
+
protected resolveCount(): number | undefined;
|
|
30
31
|
protected tapNode(node?: TreeNode): void;
|
|
31
32
|
protected handleDblClickEvent(): void;
|
|
32
33
|
protected renderTree(model: TreeModel): React.ReactNode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vsx-extensions-widget.d.ts","sourceRoot":"","sources":["../../src/browser/vsx-extensions-widget.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAc,UAAU,EAAyB,MAAM,8BAA8B,CAAC;AAC7F,OAAO,
|
|
1
|
+
{"version":3,"file":"vsx-extensions-widget.d.ts","sourceRoot":"","sources":["../../src/browser/vsx-extensions-widget.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAc,UAAU,EAAyB,MAAM,8BAA8B,CAAC;AAC7F,OAAO,EAAqB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAE1F,OAAO,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAExD,OAAO,KAAK,KAAK,MAAM,0BAA0B,CAAC;AAElD,qBACa,0BAA2B,SAAQ,0BAA0B;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,yBAAyB,GAAI,UAAU,MAAM,KAAG,MAAiD,CAAC;AAE/G,qBACa,mBAAoB,SAAQ,gBAAiB,YAAW,WAAW;IAE5E,MAAM,CAAC,EAAE,SAAoB;IAE7B,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,SAAS,EAAE,OAAO,EAAE,0BAA0B,GAAG,mBAAmB;IAa3G,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,uBAAuB,gBAAuB;IAExD,SAAS,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IACjC,SAAS,CAAC,8BAA8B,gBAAuB;IAG/D,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,0BAA0B,CAAC;IAGvD,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,mBAAmB,CAAC;cAGtC,IAAI,IAAI,IAAI;IAwB/B,IAAI,gBAAgB,IAAI,KAAK,CAAC,IAAI,CAAC,CAElC;IAED,IAAI,KAAK,IAAI,MAAM,GAAG,SAAS,CAE9B;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAGlC;IAED,IAAI,uBAAuB,IAAI,KAAK,CAAC,IAAI,CAAC,CAEzC;IAED,IAAI,YAAY,IAAI,MAAM,GAAG,SAAS,CAErC;IAED,IAAI,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAG3C;IAED,SAAS,CAAC,YAAY,IAAI,MAAM;IAehC,SAAS,CAAC,WAAW,IAAI,IAAI;IAO7B,SAAS,CAAC,YAAY,IAAI,MAAM,GAAG,SAAS;cAQzB,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,GAAG,IAAI;cAK9B,mBAAmB,IAAI,IAAI;cAI3B,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,CAAC,SAAS;cAgB7C,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI;CAQrD"}
|
|
@@ -19,6 +19,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
19
19
|
exports.VSXExtensionsWidget = exports.generateExtensionWidgetId = exports.VSXExtensionsWidgetOptions = void 0;
|
|
20
20
|
const tslib_1 = require("tslib");
|
|
21
21
|
const inversify_1 = require("@theia/core/shared/inversify");
|
|
22
|
+
const browser_1 = require("@theia/core/lib/browser");
|
|
22
23
|
const source_tree_1 = require("@theia/core/lib/browser/source-tree");
|
|
23
24
|
const vsx_extensions_source_1 = require("./vsx-extensions-source");
|
|
24
25
|
const nls_1 = require("@theia/core/lib/common/nls");
|
|
@@ -62,9 +63,15 @@ let VSXExtensionsWidget = class VSXExtensionsWidget extends source_tree_1.Source
|
|
|
62
63
|
const title = this.options.title ?? this.computeTitle();
|
|
63
64
|
this.title.label = title;
|
|
64
65
|
this.title.caption = title;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
// The badge is derived from the tree, not from a source change event: the source fires its
|
|
67
|
+
// initial change while this widget is still being constructed, so a section whose
|
|
68
|
+
// contributions never change again afterwards - e.g. when the application starts offline and
|
|
69
|
+
// the registry fetch backing some of them fails without ever firing - would keep an unset
|
|
70
|
+
// badge. `TreeModel.onChanged` covers both the initial resolution of the root's children
|
|
71
|
+
// (triggered by assigning `this.source` above) and every later refresh, and counting the
|
|
72
|
+
// resolved nodes avoids resolving the same elements a second time just to count them.
|
|
73
|
+
this.toDispose.push(this.model.onChanged(() => this.updateBadge()));
|
|
74
|
+
this.updateBadge();
|
|
68
75
|
}
|
|
69
76
|
get onDidChangeBadge() {
|
|
70
77
|
return this.onDidChangeBadgeEmitter.event;
|
|
@@ -100,12 +107,18 @@ let VSXExtensionsWidget = class VSXExtensionsWidget extends source_tree_1.Source
|
|
|
100
107
|
return '';
|
|
101
108
|
}
|
|
102
109
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
110
|
+
updateBadge() {
|
|
111
|
+
const count = this.resolveCount();
|
|
112
|
+
if (count !== this.badge) {
|
|
113
|
+
this.badge = count;
|
|
107
114
|
}
|
|
108
|
-
|
|
115
|
+
}
|
|
116
|
+
resolveCount() {
|
|
117
|
+
if (this.options.id === vsx_extensions_source_1.VSXExtensionsSourceOptions.SEARCH_RESULT) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
const root = this.model.root;
|
|
121
|
+
return browser_1.CompositeTreeNode.is(root) ? root.children.length : undefined;
|
|
109
122
|
}
|
|
110
123
|
tapNode(node) {
|
|
111
124
|
super.tapNode(node);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vsx-extensions-widget.js","sourceRoot":"","sources":["../../src/browser/vsx-extensions-widget.tsx"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yCAAyC;AACzC,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;;AAEhF,4DAA6F;
|
|
1
|
+
{"version":3,"file":"vsx-extensions-widget.js","sourceRoot":"","sources":["../../src/browser/vsx-extensions-widget.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vsx-extensions-widget.spec.d.ts","sourceRoot":"","sources":["../../src/browser/vsx-extensions-widget.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2026 EclipseSource GmbH.
|
|
4
|
+
//
|
|
5
|
+
// This program and the accompanying materials are made available under the
|
|
6
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
+
//
|
|
9
|
+
// This Source Code may also be made available under the following Secondary
|
|
10
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
+
// with the GNU Classpath Exception which is available at
|
|
13
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const frontend_application_config_provider_1 = require("@theia/core/lib/browser/frontend-application-config-provider");
|
|
19
|
+
const jsdom_1 = require("@theia/core/lib/browser/test/jsdom");
|
|
20
|
+
const disableJSDOM = (0, jsdom_1.enableJSDOM)();
|
|
21
|
+
// xterm.js (pulled in transitively via plugin-ext from VSXExtensionsModel) calls
|
|
22
|
+
// HTMLCanvasElement.prototype.getContext at module-load time. JSDOM's default impl
|
|
23
|
+
// throws 'Not implemented' without the optional `canvas` package; replace it with a
|
|
24
|
+
// no-op so the module graph evaluates. The tests below never render xterm itself.
|
|
25
|
+
const canvasProto = globalThis.HTMLCanvasElement?.prototype;
|
|
26
|
+
if (canvasProto) {
|
|
27
|
+
canvasProto.getContext = () => undefined;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
frontend_application_config_provider_1.FrontendApplicationConfigProvider.set({});
|
|
31
|
+
}
|
|
32
|
+
catch { /* already set by a sibling spec */ }
|
|
33
|
+
const chai_1 = require("chai");
|
|
34
|
+
const inversify_1 = require("@theia/core/shared/inversify");
|
|
35
|
+
const core_1 = require("@theia/core");
|
|
36
|
+
const mock_logger_1 = require("@theia/core/lib/common/test/mock-logger");
|
|
37
|
+
const browser_1 = require("@theia/core/lib/browser");
|
|
38
|
+
const core_preferences_1 = require("@theia/core/lib/common/core-preferences");
|
|
39
|
+
const preference_service_1 = require("@theia/core/lib/common/preferences/preference-service");
|
|
40
|
+
const source_tree_1 = require("@theia/core/lib/browser/source-tree");
|
|
41
|
+
const vsx_extensions_source_1 = require("./vsx-extensions-source");
|
|
42
|
+
const vsx_extensions_widget_1 = require("./vsx-extensions-widget");
|
|
43
|
+
after(() => disableJSDOM());
|
|
44
|
+
/**
|
|
45
|
+
* Stands in for `VSXExtensionsSource`: yields a controllable set of elements and never fires a
|
|
46
|
+
* change event of its own unless a test asks for one.
|
|
47
|
+
*/
|
|
48
|
+
class StubSource extends source_tree_1.TreeSource {
|
|
49
|
+
constructor() {
|
|
50
|
+
super(...arguments);
|
|
51
|
+
this.elements = [];
|
|
52
|
+
}
|
|
53
|
+
async getElements() {
|
|
54
|
+
return this.elements.values();
|
|
55
|
+
}
|
|
56
|
+
change() {
|
|
57
|
+
this.fireDidChange();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function makeElement(id) {
|
|
61
|
+
return { id, render: () => undefined };
|
|
62
|
+
}
|
|
63
|
+
function createWidget(source, id) {
|
|
64
|
+
const parent = new inversify_1.Container();
|
|
65
|
+
parent.bind(core_1.ILogger).to(mock_logger_1.MockLogger).inSingletonScope();
|
|
66
|
+
parent.bind(core_1.SelectionService).toSelf().inSingletonScope();
|
|
67
|
+
parent.bind(preference_service_1.PreferenceService).toConstantValue({
|
|
68
|
+
get: (_preferenceName, defaultValue) => defaultValue,
|
|
69
|
+
onPreferenceChanged: () => core_1.Disposable.NULL
|
|
70
|
+
});
|
|
71
|
+
parent.bind(core_preferences_1.CorePreferences).toConstantValue({
|
|
72
|
+
onPreferenceChanged: () => core_1.Disposable.NULL
|
|
73
|
+
});
|
|
74
|
+
parent.bind(browser_1.LabelProvider).toConstantValue({ onDidChange: core_1.Event.None });
|
|
75
|
+
parent.bind(browser_1.ContextMenuRenderer).toConstantValue({});
|
|
76
|
+
// Mirrors `VSXExtensionsWidget.createWidget`, with the source replaced by the stub.
|
|
77
|
+
const child = source_tree_1.SourceTreeWidget.createContainer(parent, {
|
|
78
|
+
virtualized: false,
|
|
79
|
+
scrollIfActive: true
|
|
80
|
+
});
|
|
81
|
+
const options = { id };
|
|
82
|
+
child.bind(vsx_extensions_source_1.VSXExtensionsSourceOptions).toConstantValue(options);
|
|
83
|
+
child.bind(vsx_extensions_source_1.VSXExtensionsSource).toConstantValue(source);
|
|
84
|
+
child.unbind(source_tree_1.SourceTreeWidget);
|
|
85
|
+
child.bind(vsx_extensions_widget_1.VSXExtensionsWidgetOptions).toConstantValue(options);
|
|
86
|
+
child.bind(vsx_extensions_widget_1.VSXExtensionsWidget).toSelf();
|
|
87
|
+
return child.get(vsx_extensions_widget_1.VSXExtensionsWidget);
|
|
88
|
+
}
|
|
89
|
+
/** Waits for the tree to resolve, i.e. until `condition` holds or the attempts run out. */
|
|
90
|
+
async function waitFor(condition, attempts = 100) {
|
|
91
|
+
for (let i = 0; i < attempts && !condition(); i++) {
|
|
92
|
+
await new Promise(resolve => setTimeout(resolve, 1));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
describe('VSXExtensionsWidget badge', () => {
|
|
96
|
+
it('counts the entries without waiting for a source change event', async () => {
|
|
97
|
+
// Regression test: the source fires its initial change while the widget is still being
|
|
98
|
+
// constructed, so a badge that is only assigned from that event stays unset for sections
|
|
99
|
+
// whose contributions never change again - which is what happens when the application
|
|
100
|
+
// starts offline and the registry-backed contributions fail without firing.
|
|
101
|
+
const source = new StubSource();
|
|
102
|
+
source.elements = [makeElement('a'), makeElement('b')];
|
|
103
|
+
const widget = createWidget(source, vsx_extensions_source_1.VSXExtensionsSourceOptions.INSTALLED);
|
|
104
|
+
await waitFor(() => widget.badge === 2);
|
|
105
|
+
(0, chai_1.expect)(widget.badge).to.equal(2);
|
|
106
|
+
widget.dispose();
|
|
107
|
+
});
|
|
108
|
+
it('updates the count when the source changes', async () => {
|
|
109
|
+
const source = new StubSource();
|
|
110
|
+
source.elements = [makeElement('a')];
|
|
111
|
+
const widget = createWidget(source, vsx_extensions_source_1.VSXExtensionsSourceOptions.BUILT_IN);
|
|
112
|
+
await waitFor(() => widget.badge === 1);
|
|
113
|
+
source.elements = [makeElement('a'), makeElement('b'), makeElement('c')];
|
|
114
|
+
source.change();
|
|
115
|
+
await waitFor(() => widget.badge === 3);
|
|
116
|
+
(0, chai_1.expect)(widget.badge).to.equal(3);
|
|
117
|
+
widget.dispose();
|
|
118
|
+
});
|
|
119
|
+
it('leaves the badge unset for the search result section', async () => {
|
|
120
|
+
const source = new StubSource();
|
|
121
|
+
source.elements = [makeElement('a'), makeElement('b')];
|
|
122
|
+
const widget = createWidget(source, vsx_extensions_source_1.VSXExtensionsSourceOptions.SEARCH_RESULT);
|
|
123
|
+
await waitFor(() => false, 10);
|
|
124
|
+
(0, chai_1.expect)(widget.badge).to.equal(undefined);
|
|
125
|
+
widget.dispose();
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
//# sourceMappingURL=vsx-extensions-widget.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vsx-extensions-widget.spec.js","sourceRoot":"","sources":["../../src/browser/vsx-extensions-widget.spec.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/vsx-registry",
|
|
3
|
-
"version": "1.75.0-next.
|
|
3
|
+
"version": "1.75.0-next.28+ba1005c0bf8",
|
|
4
4
|
"description": "Theia - VSX Registry",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@theia/core": "1.75.0-next.
|
|
7
|
-
"@theia/filesystem": "1.75.0-next.
|
|
8
|
-
"@theia/navigator": "1.75.0-next.
|
|
9
|
-
"@theia/ovsx-client": "1.75.0-next.
|
|
10
|
-
"@theia/plugin-ext": "1.75.0-next.
|
|
11
|
-
"@theia/plugin-ext-vscode": "1.75.0-next.
|
|
12
|
-
"@theia/preferences": "1.75.0-next.
|
|
13
|
-
"@theia/workspace": "1.75.0-next.
|
|
6
|
+
"@theia/core": "1.75.0-next.28+ba1005c0bf8",
|
|
7
|
+
"@theia/filesystem": "1.75.0-next.28+ba1005c0bf8",
|
|
8
|
+
"@theia/navigator": "1.75.0-next.28+ba1005c0bf8",
|
|
9
|
+
"@theia/ovsx-client": "1.75.0-next.28+ba1005c0bf8",
|
|
10
|
+
"@theia/plugin-ext": "1.75.0-next.28+ba1005c0bf8",
|
|
11
|
+
"@theia/plugin-ext-vscode": "1.75.0-next.28+ba1005c0bf8",
|
|
12
|
+
"@theia/preferences": "1.75.0-next.28+ba1005c0bf8",
|
|
13
|
+
"@theia/workspace": "1.75.0-next.28+ba1005c0bf8",
|
|
14
14
|
"limiter": "^2.1.0",
|
|
15
15
|
"luxon": "^2.5.2",
|
|
16
16
|
"p-debounce": "^2.1.0",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"nyc": {
|
|
62
62
|
"extends": "../../configs/nyc.json"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "ba1005c0bf87bd848c6ec51ce1b4e6bb06748e3c"
|
|
65
65
|
}
|
|
@@ -29,7 +29,8 @@ try { FrontendApplicationConfigProvider.set({}); } catch { /* already set by a s
|
|
|
29
29
|
|
|
30
30
|
import { expect } from 'chai';
|
|
31
31
|
import { Container } from '@theia/core/shared/inversify';
|
|
32
|
-
import { Emitter } from '@theia/core';
|
|
32
|
+
import { Emitter, ILogger } from '@theia/core';
|
|
33
|
+
import { MockLogger } from '@theia/core/lib/common/test/mock-logger';
|
|
33
34
|
import { PreferenceService } from '@theia/core/lib/common/preferences/preference-service';
|
|
34
35
|
import { FuzzySearch } from '@theia/core/lib/common/fuzzy-search';
|
|
35
36
|
import { ContributionProvider } from '@theia/core/lib/common/contribution-provider';
|
|
@@ -60,10 +61,30 @@ class StubContribution implements ExtensionsSourceContribution {
|
|
|
60
61
|
}
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
/** Minimal contribution stub for the section modes (installed / built-in / recommended). */
|
|
65
|
+
class StubSectionContribution implements ExtensionsSourceContribution {
|
|
66
|
+
readonly onDidChangeEmitter = new Emitter<void>();
|
|
67
|
+
readonly onDidChange = this.onDidChangeEmitter.event;
|
|
68
|
+
constructor(
|
|
69
|
+
readonly type: string,
|
|
70
|
+
readonly displayName: string,
|
|
71
|
+
readonly searchToken: string,
|
|
72
|
+
private readonly installed: () => Promise<Iterable<TreeElement>>,
|
|
73
|
+
readonly priority = 0
|
|
74
|
+
) { }
|
|
75
|
+
resolveInstalled(): Promise<Iterable<TreeElement>> {
|
|
76
|
+
return this.installed();
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
63
80
|
interface TaggedElement extends TreeElement {
|
|
64
81
|
readonly id: string;
|
|
65
82
|
}
|
|
66
83
|
|
|
84
|
+
function makeElement(id: string): TaggedElement {
|
|
85
|
+
return { id, render: () => undefined };
|
|
86
|
+
}
|
|
87
|
+
|
|
67
88
|
function makeResult(id: string, searchableText: string): SearchResult {
|
|
68
89
|
const element: TaggedElement = { id, render: () => undefined };
|
|
69
90
|
return { element, searchableText };
|
|
@@ -79,9 +100,10 @@ class StubPreferenceService {
|
|
|
79
100
|
}
|
|
80
101
|
}
|
|
81
102
|
|
|
82
|
-
function buildSource(contributions: ExtensionsSourceContribution[], query: string): VSXExtensionsSource {
|
|
103
|
+
function buildSource(contributions: ExtensionsSourceContribution[], query: string, sectionId = VSXExtensionsSourceOptions.SEARCH_RESULT): VSXExtensionsSource {
|
|
83
104
|
const container = new Container();
|
|
84
|
-
container.bind(
|
|
105
|
+
container.bind(ILogger).toConstantValue(new MockLogger());
|
|
106
|
+
container.bind(VSXExtensionsSourceOptions).toConstantValue({ id: sectionId });
|
|
85
107
|
container.bind(VSXExtensionsModel).toConstantValue({
|
|
86
108
|
onDidChange: new Emitter<void>().event
|
|
87
109
|
} as unknown as VSXExtensionsModel);
|
|
@@ -166,6 +188,20 @@ describe('VSXExtensionsSource.collectSearchResults', () => {
|
|
|
166
188
|
expect(elements.map(e => e.id)).to.deep.equal(['mcp-1']);
|
|
167
189
|
});
|
|
168
190
|
|
|
191
|
+
it('keeps the hits of the other contributions when one rejects', async () => {
|
|
192
|
+
const failing = new StubContribution('extension', 'Extensions', '@extensions', []);
|
|
193
|
+
failing.resolveSearchResults = () => { throw new Error('registry unreachable'); };
|
|
194
|
+
const working = new StubContribution('mcp-server', 'MCP Servers', '@mcp', [
|
|
195
|
+
makeResult('mcp-1', 'alpha')
|
|
196
|
+
], 100);
|
|
197
|
+
|
|
198
|
+
const source = buildSource([failing, working], '');
|
|
199
|
+
|
|
200
|
+
const elements = [...(await source.getElements())] as TaggedElement[];
|
|
201
|
+
|
|
202
|
+
expect(elements.map(e => e.id)).to.deep.equal(['mcp-1']);
|
|
203
|
+
});
|
|
204
|
+
|
|
169
205
|
it('composes @-tokens, including multiple type tokens', async () => {
|
|
170
206
|
const extensions = new StubContribution('extension', 'Extensions', '@extensions', [
|
|
171
207
|
makeResult('ext-1', 'ext alpha')
|
|
@@ -184,3 +220,38 @@ describe('VSXExtensionsSource.collectSearchResults', () => {
|
|
|
184
220
|
expect(elements.map(e => e.id).sort()).to.deep.equal(['mcp-1', 'skill-1']);
|
|
185
221
|
});
|
|
186
222
|
});
|
|
223
|
+
|
|
224
|
+
describe('VSXExtensionsSource section entries', () => {
|
|
225
|
+
|
|
226
|
+
it('keeps the entries of the other contributions when one rejects', async () => {
|
|
227
|
+
const failing = new StubSectionContribution('extension', 'Extensions', '@extensions', () => Promise.reject(new Error('registry unreachable')));
|
|
228
|
+
const working = new StubSectionContribution('mcp-server', 'MCP Servers', '@mcp', async () => [makeElement('mcp-1')], 100);
|
|
229
|
+
|
|
230
|
+
const source = buildSource([failing, working], '', VSXExtensionsSourceOptions.INSTALLED);
|
|
231
|
+
|
|
232
|
+
const elements = [...(await source.getElements())] as TaggedElement[];
|
|
233
|
+
|
|
234
|
+
expect(elements.map(e => e.id)).to.deep.equal(['mcp-1']);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('resolves the contributions concurrently, in priority order', async () => {
|
|
238
|
+
let markSecondStarted: () => void = () => { };
|
|
239
|
+
const secondStarted = new Promise<void>(resolve => { markSecondStarted = resolve; });
|
|
240
|
+
// The first contribution only completes once the second one has started, so this test times
|
|
241
|
+
// out if the section resolves its contributions one after the other.
|
|
242
|
+
const first = new StubSectionContribution('extension', 'Extensions', '@extensions', async () => {
|
|
243
|
+
await secondStarted;
|
|
244
|
+
return [makeElement('first')];
|
|
245
|
+
});
|
|
246
|
+
const second = new StubSectionContribution('mcp-server', 'MCP Servers', '@mcp', async () => {
|
|
247
|
+
markSecondStarted();
|
|
248
|
+
return [makeElement('second')];
|
|
249
|
+
}, 100);
|
|
250
|
+
|
|
251
|
+
const source = buildSource([first, second], '', VSXExtensionsSourceOptions.INSTALLED);
|
|
252
|
+
|
|
253
|
+
const elements = [...(await source.getElements())] as TaggedElement[];
|
|
254
|
+
|
|
255
|
+
expect(elements.map(e => e.id)).to.deep.equal(['first', 'second']);
|
|
256
|
+
});
|
|
257
|
+
});
|
|
@@ -15,12 +15,13 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { injectable, inject, postConstruct, named } from '@theia/core/shared/inversify';
|
|
18
|
+
import { ILogger } from '@theia/core/lib/common/logger';
|
|
18
19
|
import { TreeElement, TreeSource } from '@theia/core/lib/browser/source-tree';
|
|
19
20
|
import { ContributionProvider } from '@theia/core/lib/common/contribution-provider';
|
|
20
21
|
import { PreferenceService } from '@theia/core/lib/common/preferences/preference-service';
|
|
21
22
|
import { FuzzySearch } from '@theia/core/lib/common/fuzzy-search';
|
|
22
23
|
import { VSXExtensionsModel } from './vsx-extensions-model';
|
|
23
|
-
import { ExtensionsSourceContribution, SearchContext } from './extensions-source-contribution';
|
|
24
|
+
import { ExtensionsSourceContribution, SearchContext, SearchResult } from './extensions-source-contribution';
|
|
24
25
|
import { VSXExtensionsSearchModel } from './vsx-extensions-search-model';
|
|
25
26
|
import debounce = require('@theia/core/shared/lodash.debounce');
|
|
26
27
|
|
|
@@ -54,6 +55,9 @@ export class VSXExtensionsSource extends TreeSource {
|
|
|
54
55
|
@inject(FuzzySearch)
|
|
55
56
|
protected readonly fuzzySearch: FuzzySearch;
|
|
56
57
|
|
|
58
|
+
@inject(ILogger) @named('vsx-registry:VSXExtensionsSource')
|
|
59
|
+
protected readonly logger: ILogger;
|
|
60
|
+
|
|
57
61
|
@postConstruct()
|
|
58
62
|
protected init(): void {
|
|
59
63
|
this.fireDidChange();
|
|
@@ -82,9 +86,12 @@ export class VSXExtensionsSource extends TreeSource {
|
|
|
82
86
|
return this.collectSearchResults(enabled);
|
|
83
87
|
}
|
|
84
88
|
|
|
89
|
+
// Resolve concurrently and isolate each contribution: a section is shared between all of
|
|
90
|
+
// them, so one that is slow (e.g. waiting on a remote registry) must not hold up the
|
|
91
|
+
// others, and one that rejects must not empty the whole section.
|
|
92
|
+
const resolved = await Promise.all(enabled.map(contribution => this.safeResolveForSection(contribution)));
|
|
85
93
|
const entries: TreeElement[] = [];
|
|
86
|
-
for (const
|
|
87
|
-
const iter = await this.resolveForSection(contribution);
|
|
94
|
+
for (const iter of resolved) {
|
|
88
95
|
if (!iter) {
|
|
89
96
|
continue;
|
|
90
97
|
}
|
|
@@ -107,7 +114,7 @@ export class VSXExtensionsSource extends TreeSource {
|
|
|
107
114
|
const ctx: SearchContext = {
|
|
108
115
|
verifiedOnly: this.preferenceService.get<boolean>('extensions.onlyShowVerifiedExtensions', false)
|
|
109
116
|
};
|
|
110
|
-
const results = await Promise.all(contributions.map(c =>
|
|
117
|
+
const results = await Promise.all(contributions.map(c => this.safeResolveSearchResults(c, freeText, ctx)));
|
|
111
118
|
const all = results.flatMap(r => [...r]);
|
|
112
119
|
const trimmed = freeText.trim();
|
|
113
120
|
if (!trimmed || all.length <= 1) {
|
|
@@ -121,6 +128,24 @@ export class VSXExtensionsSource extends TreeSource {
|
|
|
121
128
|
return matches.map(m => m.item.element).values();
|
|
122
129
|
}
|
|
123
130
|
|
|
131
|
+
protected async safeResolveForSection(contribution: ExtensionsSourceContribution): Promise<Iterable<TreeElement> | undefined> {
|
|
132
|
+
try {
|
|
133
|
+
return await this.resolveForSection(contribution);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
this.logger.warn(`Failed to resolve '${this.options.id}' entries of contribution '${contribution.type}'.`, error);
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
protected async safeResolveSearchResults(contribution: ExtensionsSourceContribution, query: string, context: SearchContext): Promise<Iterable<SearchResult>> {
|
|
141
|
+
try {
|
|
142
|
+
return await (contribution.resolveSearchResults?.(query, context) ?? []);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
this.logger.warn(`Failed to resolve search results of contribution '${contribution.type}'.`, error);
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
124
149
|
protected async resolveForSection(contribution: ExtensionsSourceContribution): Promise<Iterable<TreeElement> | undefined> {
|
|
125
150
|
switch (this.options.id) {
|
|
126
151
|
case VSXExtensionsSourceOptions.INSTALLED:
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 EclipseSource GmbH.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { FrontendApplicationConfigProvider } from '@theia/core/lib/browser/frontend-application-config-provider';
|
|
18
|
+
import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom';
|
|
19
|
+
const disableJSDOM = enableJSDOM();
|
|
20
|
+
// xterm.js (pulled in transitively via plugin-ext from VSXExtensionsModel) calls
|
|
21
|
+
// HTMLCanvasElement.prototype.getContext at module-load time. JSDOM's default impl
|
|
22
|
+
// throws 'Not implemented' without the optional `canvas` package; replace it with a
|
|
23
|
+
// no-op so the module graph evaluates. The tests below never render xterm itself.
|
|
24
|
+
const canvasProto = (globalThis as { HTMLCanvasElement?: { prototype: { getContext?: unknown } } }).HTMLCanvasElement?.prototype;
|
|
25
|
+
if (canvasProto) {
|
|
26
|
+
canvasProto.getContext = () => undefined;
|
|
27
|
+
}
|
|
28
|
+
try { FrontendApplicationConfigProvider.set({}); } catch { /* already set by a sibling spec */ }
|
|
29
|
+
|
|
30
|
+
import { expect } from 'chai';
|
|
31
|
+
import { Container } from '@theia/core/shared/inversify';
|
|
32
|
+
import { Disposable, Event, ILogger, SelectionService } from '@theia/core';
|
|
33
|
+
import { MockLogger } from '@theia/core/lib/common/test/mock-logger';
|
|
34
|
+
import { ContextMenuRenderer, LabelProvider } from '@theia/core/lib/browser';
|
|
35
|
+
import { CorePreferences } from '@theia/core/lib/common/core-preferences';
|
|
36
|
+
import { PreferenceService } from '@theia/core/lib/common/preferences/preference-service';
|
|
37
|
+
import { SourceTreeWidget, TreeElement, TreeSource } from '@theia/core/lib/browser/source-tree';
|
|
38
|
+
import { VSXExtensionsSource, VSXExtensionsSourceOptions } from './vsx-extensions-source';
|
|
39
|
+
import { VSXExtensionsWidget, VSXExtensionsWidgetOptions } from './vsx-extensions-widget';
|
|
40
|
+
|
|
41
|
+
after(() => disableJSDOM());
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Stands in for `VSXExtensionsSource`: yields a controllable set of elements and never fires a
|
|
45
|
+
* change event of its own unless a test asks for one.
|
|
46
|
+
*/
|
|
47
|
+
class StubSource extends TreeSource {
|
|
48
|
+
elements: TreeElement[] = [];
|
|
49
|
+
override async getElements(): Promise<IterableIterator<TreeElement>> {
|
|
50
|
+
return this.elements.values();
|
|
51
|
+
}
|
|
52
|
+
change(): void {
|
|
53
|
+
this.fireDidChange();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function makeElement(id: string): TreeElement {
|
|
58
|
+
return { id, render: () => undefined };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function createWidget(source: TreeSource, id: string): VSXExtensionsWidget {
|
|
62
|
+
const parent = new Container();
|
|
63
|
+
parent.bind(ILogger).to(MockLogger).inSingletonScope();
|
|
64
|
+
parent.bind(SelectionService).toSelf().inSingletonScope();
|
|
65
|
+
parent.bind(PreferenceService).toConstantValue({
|
|
66
|
+
get: <T>(_preferenceName: string, defaultValue?: T) => defaultValue,
|
|
67
|
+
onPreferenceChanged: () => Disposable.NULL
|
|
68
|
+
} as unknown as PreferenceService);
|
|
69
|
+
parent.bind(CorePreferences).toConstantValue({
|
|
70
|
+
onPreferenceChanged: () => Disposable.NULL
|
|
71
|
+
} as unknown as CorePreferences);
|
|
72
|
+
parent.bind(LabelProvider).toConstantValue({ onDidChange: Event.None } as unknown as LabelProvider);
|
|
73
|
+
parent.bind(ContextMenuRenderer).toConstantValue({} as ContextMenuRenderer);
|
|
74
|
+
|
|
75
|
+
// Mirrors `VSXExtensionsWidget.createWidget`, with the source replaced by the stub.
|
|
76
|
+
const child = SourceTreeWidget.createContainer(parent, {
|
|
77
|
+
virtualized: false,
|
|
78
|
+
scrollIfActive: true
|
|
79
|
+
});
|
|
80
|
+
const options = { id };
|
|
81
|
+
child.bind(VSXExtensionsSourceOptions).toConstantValue(options);
|
|
82
|
+
child.bind(VSXExtensionsSource).toConstantValue(source as VSXExtensionsSource);
|
|
83
|
+
child.unbind(SourceTreeWidget);
|
|
84
|
+
child.bind(VSXExtensionsWidgetOptions).toConstantValue(options);
|
|
85
|
+
child.bind(VSXExtensionsWidget).toSelf();
|
|
86
|
+
return child.get(VSXExtensionsWidget);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Waits for the tree to resolve, i.e. until `condition` holds or the attempts run out. */
|
|
90
|
+
async function waitFor(condition: () => boolean, attempts = 100): Promise<void> {
|
|
91
|
+
for (let i = 0; i < attempts && !condition(); i++) {
|
|
92
|
+
await new Promise<void>(resolve => setTimeout(resolve, 1));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
describe('VSXExtensionsWidget badge', () => {
|
|
97
|
+
|
|
98
|
+
it('counts the entries without waiting for a source change event', async () => {
|
|
99
|
+
// Regression test: the source fires its initial change while the widget is still being
|
|
100
|
+
// constructed, so a badge that is only assigned from that event stays unset for sections
|
|
101
|
+
// whose contributions never change again - which is what happens when the application
|
|
102
|
+
// starts offline and the registry-backed contributions fail without firing.
|
|
103
|
+
const source = new StubSource();
|
|
104
|
+
source.elements = [makeElement('a'), makeElement('b')];
|
|
105
|
+
|
|
106
|
+
const widget = createWidget(source, VSXExtensionsSourceOptions.INSTALLED);
|
|
107
|
+
await waitFor(() => widget.badge === 2);
|
|
108
|
+
|
|
109
|
+
expect(widget.badge).to.equal(2);
|
|
110
|
+
widget.dispose();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('updates the count when the source changes', async () => {
|
|
114
|
+
const source = new StubSource();
|
|
115
|
+
source.elements = [makeElement('a')];
|
|
116
|
+
const widget = createWidget(source, VSXExtensionsSourceOptions.BUILT_IN);
|
|
117
|
+
await waitFor(() => widget.badge === 1);
|
|
118
|
+
|
|
119
|
+
source.elements = [makeElement('a'), makeElement('b'), makeElement('c')];
|
|
120
|
+
source.change();
|
|
121
|
+
await waitFor(() => widget.badge === 3);
|
|
122
|
+
|
|
123
|
+
expect(widget.badge).to.equal(3);
|
|
124
|
+
widget.dispose();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('leaves the badge unset for the search result section', async () => {
|
|
128
|
+
const source = new StubSource();
|
|
129
|
+
source.elements = [makeElement('a'), makeElement('b')];
|
|
130
|
+
|
|
131
|
+
const widget = createWidget(source, VSXExtensionsSourceOptions.SEARCH_RESULT);
|
|
132
|
+
await waitFor(() => false, 10);
|
|
133
|
+
|
|
134
|
+
expect(widget.badge).to.equal(undefined);
|
|
135
|
+
widget.dispose();
|
|
136
|
+
});
|
|
137
|
+
});
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { injectable, interfaces, postConstruct, inject } from '@theia/core/shared/inversify';
|
|
18
|
-
import { Message, TreeModel, TreeNode } from '@theia/core/lib/browser';
|
|
18
|
+
import { CompositeTreeNode, Message, TreeModel, TreeNode } from '@theia/core/lib/browser';
|
|
19
19
|
import { SourceTreeWidget } from '@theia/core/lib/browser/source-tree';
|
|
20
20
|
import { VSXExtensionsSource, VSXExtensionsSourceOptions } from './vsx-extensions-source';
|
|
21
21
|
import { nls } from '@theia/core/lib/common/nls';
|
|
@@ -75,9 +75,15 @@ export class VSXExtensionsWidget extends SourceTreeWidget implements BadgeWidget
|
|
|
75
75
|
this.title.label = title;
|
|
76
76
|
this.title.caption = title;
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
// The badge is derived from the tree, not from a source change event: the source fires its
|
|
79
|
+
// initial change while this widget is still being constructed, so a section whose
|
|
80
|
+
// contributions never change again afterwards - e.g. when the application starts offline and
|
|
81
|
+
// the registry fetch backing some of them fails without ever firing - would keep an unset
|
|
82
|
+
// badge. `TreeModel.onChanged` covers both the initial resolution of the root's children
|
|
83
|
+
// (triggered by assigning `this.source` above) and every later refresh, and counting the
|
|
84
|
+
// resolved nodes avoids resolving the same elements a second time just to count them.
|
|
85
|
+
this.toDispose.push(this.model.onChanged(() => this.updateBadge()));
|
|
86
|
+
this.updateBadge();
|
|
81
87
|
}
|
|
82
88
|
|
|
83
89
|
get onDidChangeBadge(): Event<void> {
|
|
@@ -121,12 +127,19 @@ export class VSXExtensionsWidget extends SourceTreeWidget implements BadgeWidget
|
|
|
121
127
|
}
|
|
122
128
|
}
|
|
123
129
|
|
|
124
|
-
protected
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
130
|
+
protected updateBadge(): void {
|
|
131
|
+
const count = this.resolveCount();
|
|
132
|
+
if (count !== this.badge) {
|
|
133
|
+
this.badge = count;
|
|
128
134
|
}
|
|
129
|
-
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
protected resolveCount(): number | undefined {
|
|
138
|
+
if (this.options.id === VSXExtensionsSourceOptions.SEARCH_RESULT) {
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
const root = this.model.root;
|
|
142
|
+
return CompositeTreeNode.is(root) ? root.children.length : undefined;
|
|
130
143
|
}
|
|
131
144
|
|
|
132
145
|
protected override tapNode(node?: TreeNode): void {
|