Fix tsdk relative path overwrite and unnecessary prompt on workspace open#4072
Fix tsdk relative path overwrite and unnecessary prompt on workspace open#4072Copilot wants to merge 9 commits into
Conversation
- Add relativeTsdkPath to DetectedVersion to store portable relative path - promptUseWorkspaceVersion: skip prompt when existing tsdk already resolves to a workspace install (auto opt-in without modifying settings) - promptUseWorkspaceVersion: write relative path when user clicks Allow - promptSelectVersion: use relative path and compare against exePath for active version indicator Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
| if (workspaceVersions.length === 0) return; | ||
|
|
||
| // If the existing tsdk setting already resolves to a workspace install, | ||
| // treat it as already opted in — don't prompt and don't overwrite the setting. |
There was a problem hiding this comment.
| // treat it as already opted in — don't prompt and don't overwrite the setting. | |
| // treat it as already opted in - don't prompt and don't overwrite the setting. |
There was a problem hiding this comment.
Pull request overview
This PR updates the VS Code extension’s workspace TypeScript Native Preview version selection so committed relative tsdk settings are preserved instead of being overwritten with absolute machine-specific paths.
Changes:
- Adds a stored relative
tsdkpath for detected workspace native-preview packages. - Uses executable paths for active-version comparison in the version picker.
- Skips the workspace-version prompt when the existing
tsdkalready resolves to a detected workspace install.
Show a summary per file
| File | Description |
|---|---|
_extension/src/session.ts |
Updates workspace package detection, version picker display/update behavior, and prompt short-circuit logic for existing tsdk settings. |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 2
| if (currentTsdk) { | ||
| const resolvedCurrent = await resolveTsdkPathToExe(currentTsdk); | ||
| if (resolvedCurrent && workspaceVersions.some(ws => ws.exePath === resolvedCurrent.path)) { | ||
| await context.workspaceState.update(useWorkspaceTsdkStorageKey, true); |
| label: folder.name, | ||
| version: resolved?.version ?? "unknown", | ||
| tsdkPath: path.normalize(packagePath.fsPath), | ||
| relativeTsdkPath: "./node_modules/@typescript/native-preview", |
Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
Fixed in 0f8de0c. |
|
@copilot more feedback. Also, what is the current behavior in the built-in TS extension if a user has an explicit tsdk? Do we ask if they really want to use it, even if the user has already granted workspace trust? |
…tive paths Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
Addressed both reviewer points:
Regarding your question about the built-in TS extension: yes, it has a similar pattern. When |
andrewbranch
left a comment
There was a problem hiding this comment.
Regarding your question about the built-in TS extension: yes, it has a similar pattern. When typescript.tsdk points to a workspace-level path, the extension shows a "Use Workspace Version" prompt even if the workspace is trusted. Once the user clicks "Allow", it stores an opt-in flag in workspace state and doesn't ask again. Workspace trust alone is not sufficient — the user must also explicitly allow the workspace tsdk through the prompt or version picker. Our behavior here mirrors that pattern.
Skip prompt when tsdk already resolves to workspace install: Before showing the prompt, resolve the current tsdk setting and compare against detected workspace packages. If it matches, silently set useWorkspaceTsdkStorageKey and restart the server so the workspace tsdk takes effect immediately—without modifying the setting or prompting.
@copilot It seems like these two claims contradict each other, or am I misunderstanding? There should be no possible scenario where a user does a fresh repo clone and install and gets opted into using a workspace version of TS unprompted. If useWorkspaceTsdkStorageKey is about trust, not preference, then it's never appropriate to set it without explicit user interaction.
… tsdk on Allow Co-authored-by: andrewbranch <3277153+andrewbranch@users.noreply.github.com>
You're right — |
|
@copilot what happens when the user changes their tsdk version away from the workspace version to the built-in one? In the old TypeScript extension, this doesn't persist a JSON settings change. |
…e trust flag Co-authored-by: andrewbranch <3277153+andrewbranch@users.noreply.github.com>
Previously it was calling |
|
@copilot setting useWorkspaceTsdkStorageKey to false will re-trigger the prompt... |
…picker Co-authored-by: andrewbranch <3277153+andrewbranch@users.noreply.github.com>
Right. Now when the user explicitly chooses bundled via the version picker, we also set |
DanielRosenwasser
left a comment
There was a problem hiding this comment.
@copilot consider and address
| label: folder.name, | ||
| version: resolved?.version ?? "unknown", | ||
| tsdkPath: path.normalize(packagePath.fsPath), | ||
| relativeTsdkPath: "./node_modules/@typescript/native-preview", |
There was a problem hiding this comment.
Extract this out above and use it as the argument for vscode.Uri.joinPath.
| // workspaceResolve anchors relative paths there. For other folders, | ||
| // fall back to the absolute path so the setting resolves correctly. | ||
| const relativeTsdkPath = i === 0 | ||
| ? "./node_modules/@typescript/native-preview" |
There was a problem hiding this comment.
Extract this out to a relative location above, then use it in joinPath.
| // Use a relative path only for the first workspace folder since | ||
| // workspaceResolve anchors relative paths there. For other folders, | ||
| // fall back to the absolute path so the setting resolves correctly. |
There was a problem hiding this comment.
This logic seems to be hacks on hacks. Why not just funnel along the workspace path and calculate the relative path from that?
There was a problem hiding this comment.
Extracted relativeWorkspacePath as a constant above the loop. It's now used both as the argument to joinPath (split on /) and to construct the relative tsdk path (prepending ./). This eliminates the duplication and makes the relationship clear.
…tivePreviewPackages Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
Addressed in the latest commit — extracted |
Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com>
Committed relative
tsdkpaths (e.g."./node_modules/@typescript/native-preview") get overwritten with machine-specific absolute paths when accepting the workspace version prompt, dirtying source-controlled.vscode/settings.json. The prompt also re-fires every session because the extension never recognizes an existing relative path as "already opted in."Changes
tsdksetting already resolves to the workspace install. If so, it sets the trust flag and restarts without overwriting the setting, preserving committed relative paths.promptUseWorkspaceVersionandpromptSelectVersionnow write./node_modules/@typescript/native-previewinstead of the absolutefsPathwhen the tsdk needs to be written.promptSelectVersioncompares againstexePath(the resolved executable) rather than the absolutetsdkPathfor the "active" dot.workspaceResolveanchors to). For packages detected in other workspace folders, the absolute path is written so the setting resolves correctly.useWorkspaceTsdkStorageKeytrust flag is never set without explicit user interaction (clicking "Allow" on the prompt or using the version picker). A committedtsdkalone does not bypass the trust prompt.tsdkfrom.vscode/settings.json. SincegetExealready ignores workspace-leveltsdkwhen the trust flag is false, this avoids dirtying committed settings files. This matches the behavior of the built-in TypeScript extension.