Skip to content

Commit e3b7345

Browse files
authored
fix: surface status bar warning when TS plugin bootstrap fails on read-only extension installs (fixes #637) (#720)
2 parents b7f507d + 23200e9 commit e3b7345

2 files changed

Lines changed: 67 additions & 8 deletions

File tree

l10n/bundle.l10n.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@
470470
"DocumentDB Kubernetes Operator (DKO)": "DocumentDB Kubernetes Operator (DKO)",
471471
"DocumentDB Local": "DocumentDB Local",
472472
"DocumentDB Shell: {0}": "DocumentDB Shell: {0}",
473+
"DocumentDB TS Plugin": "DocumentDB TS Plugin",
473474
"DocumentDB: {0}@{1}/{2}": "DocumentDB: {0}@{1}/{2}",
474475
"DocumentDB: {0}/{1}": "DocumentDB: {0}/{1}",
475476
"Documents": "Documents",
@@ -1108,6 +1109,7 @@
11081109
"Results found": "Results found",
11091110
"Retry": "Retry",
11101111
"Retry Error: {error}": "Retry Error: {error}",
1112+
"Retry TS Plugin Setup": "Retry TS Plugin Setup",
11111113
"Returns majority of collection": "Returns majority of collection",
11121114
"Reusing active connection for \"{cluster}\".": "Reusing active connection for \"{cluster}\".",
11131115
"Revisit connection details and try again.": "Revisit connection details and try again.",
@@ -1383,6 +1385,7 @@
13831385
"Try with Decoded Password": "Try with Decoded Password",
13841386
"Type \"help\" for available commands.": "Type \"help\" for available commands.",
13851387
"Type \"it\" for more": "Type \"it\" for more",
1388+
"TypeScript-powered completions are unavailable on this read-only extension install. Click to retry.": "TypeScript-powered completions are unavailable on this read-only extension install. Click to retry.",
13861389
"Unable to connect to the local database instance. Make sure it is started correctly. See {link} for tips.": "Unable to connect to the local database instance. Make sure it is started correctly. See {link} for tips.",
13871390
"Unable to connect to the local instance. Make sure it is started correctly. See {link} for tips.": "Unable to connect to the local instance. Make sure it is started correctly. See {link} for tips.",
13881391
"Unable to retrieve credentials for cluster \"{cluster}\".": "Unable to retrieve credentials for cluster \"{cluster}\".",

src/documentdb/ClustersExtension.ts

Lines changed: 64 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -316,9 +316,15 @@ export class ClustersExtension implements vscode.Disposable {
316316
// extension was discovered, so its TS server might not include our plugin.
317317
// We restart it once when the first query playground file is opened.
318318
let tsRestarted = false;
319+
let tsPluginUnavailable = false;
320+
let tsPluginRetryRegistered = false;
321+
// Shared reference so the retry command always acts on the current
322+
// status bar item. Reusing one item avoids stranding a stale warning
323+
// when a retry fails again on a still-read-only install.
324+
let tsPluginStatusBarItem: vscode.StatusBarItem | undefined;
319325

320326
const ensureTsRestart = async (): Promise<void> => {
321-
if (tsRestarted) {
327+
if (tsRestarted || tsPluginUnavailable) {
322328
return;
323329
}
324330
// Mark attempted up front to prevent concurrent bootstraps from racing.
@@ -391,14 +397,64 @@ export class ClustersExtension implements vscode.Disposable {
391397

392398
stage = 'complete';
393399
} catch (error) {
394-
// Reset so the next playground open retries the bootstrap.
395-
// This matters for read-only extension installs (Snap, system
396-
// package, locked enterprise) where the first attempt fails
397-
// but a later run after a workspace setting change may succeed,
398-
// and for slow-init environments where the TS server was not
399-
// ready in time.
400-
tsRestarted = false;
401400
const message = error instanceof Error ? error.message : String(error);
401+
const errorCode = (error as NodeJS.ErrnoException)?.code;
402+
403+
// EACCES / EROFS signal a read-only extension install
404+
// (Snap, system package, locked enterprise, network share).
405+
// Retrying won't help — surface a status bar warning so users
406+
// understand the limitation instead of silently failing.
407+
if (errorCode === 'EACCES' || errorCode === 'EROFS') {
408+
tsPluginUnavailable = true;
409+
410+
// Create the status bar item once and reuse it. A failed
411+
// retry re-shows the same item instead of leaking a new one.
412+
if (!tsPluginStatusBarItem) {
413+
const TS_PLUGIN_WARNING_PRIORITY = 100;
414+
tsPluginStatusBarItem = vscode.window.createStatusBarItem(
415+
vscode.StatusBarAlignment.Right,
416+
TS_PLUGIN_WARNING_PRIORITY,
417+
);
418+
tsPluginStatusBarItem.command = {
419+
title: vscode.l10n.t('Retry TS Plugin Setup'),
420+
command: 'vscode-documentdb.command.retryTsPluginBootstrap',
421+
};
422+
ext.context.subscriptions.push(tsPluginStatusBarItem);
423+
}
424+
tsPluginStatusBarItem.text = `$(warning) ${vscode.l10n.t('DocumentDB TS Plugin')}`;
425+
tsPluginStatusBarItem.tooltip = vscode.l10n.t(
426+
'TypeScript-powered completions are unavailable on this read-only extension install. Click to retry.',
427+
);
428+
tsPluginStatusBarItem.show();
429+
430+
// Register the retry command once. It always acts on the
431+
// shared status bar item, so retries cannot strand an item
432+
// that an earlier closure captured.
433+
if (!tsPluginRetryRegistered) {
434+
tsPluginRetryRegistered = true;
435+
ext.context.subscriptions.push(
436+
vscode.commands.registerCommand(
437+
'vscode-documentdb.command.retryTsPluginBootstrap',
438+
() => {
439+
tsPluginStatusBarItem?.hide();
440+
tsPluginUnavailable = false;
441+
tsRestarted = false;
442+
void ensureTsRestart();
443+
},
444+
),
445+
);
446+
}
447+
448+
ext.outputChannel.debug(
449+
`[Playground] TS plugin stub unavailable (read-only install): ${message}`,
450+
);
451+
} else {
452+
// Reset so the next playground open retries the bootstrap
453+
// for transient failures (e.g., slow-init environments
454+
// where the TS server was not ready in time).
455+
tsRestarted = false;
456+
}
457+
402458
ext.outputChannel.debug(
403459
`[Playground] TS server bootstrap failed at stage=${stage}: ${message}`,
404460
);

0 commit comments

Comments
 (0)