Skip to content

Commit

Permalink
Add node as npm script runner (2nd) (#240527)
Browse files Browse the repository at this point in the history
* refactor: Separate `createScriptRunnerTask` and `createInstallationTask` from `createTask`

* feat: Add `npm.scriptRunner`

* feat: Add Node.js as script runner

* refactor: Refactor `isPrePostScript`

* refactor: Extract `get*Command`

* fix: Typo

* style: Remove no-op `catch`es

* fix: `node --run` doesn't support `--silent`

* refactor: Use `.map` in `escapeCommandLine`

* chore: Remove TODO

Upstream reviewer is ok with current state

* fix: Fix error the resolved task definition differs from the original
  • Loading branch information
xymopen authored Feb 17, 2025
1 parent 46fddb4 commit e20adc3
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 154 deletions.
3 changes: 2 additions & 1 deletion extensions/npm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ The extension fetches data from <https://registry.npmjs.org> and <https://regist

- `npm.autoDetect` - Enable detecting scripts as tasks, the default is `on`.
- `npm.runSilent` - Run npm script with the `--silent` option, the default is `false`.
- `npm.packageManager` - The package manager used to run the scripts: `auto`, `npm`, `yarn`, `pnpm` or `bun`. The default is `auto`, which detects your package manager based on files in your workspace.
- `npm.packageManager` - The package manager used to install dependencies: `auto`, `npm`, `yarn`, `pnpm` or `bun`. The default is `auto`, which detects your package manager based on files in your workspace.
- `npm.scriptRunner` - The script runner used to run the scripts: `auto`, `npm`, `yarn`, `pnpm`, `bun` or `node`. The default is `auto`, which detects your script runner based on files in your workspace.
- `npm.exclude` - Glob patterns for folders that should be excluded from automatic script detection. The pattern is matched against the **absolute path** of the package.json. For example, to exclude all test folders use '&ast;&ast;/test/&ast;&ast;'.
- `npm.enableScriptExplorer` - Enable an explorer view for npm scripts.
- `npm.scriptExplorerAction` - The default click action: `open` or `run`, the default is `open`.
Expand Down
44 changes: 33 additions & 11 deletions extensions/npm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,28 @@
"default": "auto",
"description": "%config.npm.packageManager%"
},
"npm.scriptRunner": {
"scope": "resource",
"type": "string",
"enum": [
"auto",
"npm",
"yarn",
"pnpm",
"bun",
"node"
],
"enumDescriptions": [
"%config.npm.scriptRunner.auto%",
"%config.npm.scriptRunner.npm%",
"%config.npm.scriptRunner.yarn%",
"%config.npm.scriptRunner.pnpm%",
"%config.npm.scriptRunner.bun%",
"%config.npm.scriptRunner.node%"
],
"default": "auto",
"description": "%config.npm.scriptRunner%"
},
"npm.exclude": {
"type": [
"string",
Expand Down Expand Up @@ -341,18 +363,18 @@
}
],
"terminalQuickFixes": [
{
"id": "ms-vscode.npm-command",
"commandLineMatcher": "npm",
"commandExitResult": "error",
"outputMatcher": {
"anchor": "bottom",
"length": 8,
"lineMatcher": "Did you mean (?:this|one of these)\\?((?:\\n.+?npm .+ #.+)+)",
"offset": 2
}
{
"id": "ms-vscode.npm-command",
"commandLineMatcher": "npm",
"commandExitResult": "error",
"outputMatcher": {
"anchor": "bottom",
"length": 8,
"lineMatcher": "Did you mean (?:this|one of these)\\?((?:\\n.+?npm .+ #.+)+)",
"offset": 2
}
]
}
]
},
"repository": {
"type": "git",
Expand Down
19 changes: 13 additions & 6 deletions extensions/npm/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,19 @@
"virtualWorkspaces": "Functionality that requires running the 'npm' command is not available in virtual workspaces.",
"config.npm.autoDetect": "Controls whether npm scripts should be automatically detected.",
"config.npm.runSilent": "Run npm commands with the `--silent` option.",
"config.npm.packageManager": "The package manager used to run scripts.",
"config.npm.packageManager.npm": "Use npm as the package manager for running scripts.",
"config.npm.packageManager.yarn": "Use yarn as the package manager for running scripts.",
"config.npm.packageManager.pnpm": "Use pnpm as the package manager for running scripts.",
"config.npm.packageManager.bun": "Use bun as the package manager for running scripts.",
"config.npm.packageManager.auto": "Auto-detect which package manager to use for running scripts based on lock files and installed package managers.",
"config.npm.packageManager": "The package manager used to install dependencies.",
"config.npm.packageManager.npm": "Use npm as the package manager.",
"config.npm.packageManager.yarn": "Use yarn as the package manager.",
"config.npm.packageManager.pnpm": "Use pnpm as the package manager.",
"config.npm.packageManager.bun": "Use bun as the package manager.",
"config.npm.packageManager.auto": "Auto-detect which package manager to use based on lock files and installed package managers.",
"config.npm.scriptRunner": "The script runner used to run scripts.",
"config.npm.scriptRunner.npm": "Use npm as the script runner.",
"config.npm.scriptRunner.yarn": "Use yarn as the script runner.",
"config.npm.scriptRunner.pnpm": "Use pnpm as the script runner.",
"config.npm.scriptRunner.bun": "Use bun as the script runner.",
"config.npm.scriptRunner.node": "Use Node.js as the script runner.",
"config.npm.scriptRunner.auto": "Auto-detect which script runner to use based on lock files and installed package managers.",
"config.npm.exclude": "Configure glob patterns for folders that should be excluded from automatic script detection.",
"config.npm.enableScriptExplorer": "Enable an explorer view for npm scripts when there is no top-level 'package.json' file.",
"config.npm.scriptExplorerAction": "The default click action used in the NPM Scripts Explorer: `open` or `run`, the default is `open`.",
Expand Down
10 changes: 8 additions & 2 deletions extensions/npm/src/npmMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as vscode from 'vscode';
import { addJSONProviders } from './features/jsonContributions';
import { runSelectedScript, selectAndRunScriptFromFolder } from './commands';
import { NpmScriptsTreeDataProvider } from './npmView';
import { getPackageManager, invalidateTasksCache, NpmTaskProvider, hasPackageJson } from './tasks';
import { getScriptRunner, getPackageManager, invalidateTasksCache, NpmTaskProvider, hasPackageJson } from './tasks';
import { invalidateHoverScriptsCache, NpmScriptHoverProvider } from './scriptHover';
import { NpmScriptLensProvider } from './npmScriptLens';
import which from 'which';
Expand Down Expand Up @@ -63,9 +63,15 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
context.subscriptions.push(vscode.commands.registerCommand('npm.refresh', () => {
invalidateScriptCaches();
}));
context.subscriptions.push(vscode.commands.registerCommand('npm.scriptRunner', (args) => {
if (args instanceof vscode.Uri) {
return getScriptRunner(args, context, true);
}
return '';
}));
context.subscriptions.push(vscode.commands.registerCommand('npm.packageManager', (args) => {
if (args instanceof vscode.Uri) {
return getPackageManager(context, args);
return getPackageManager(args, context, true);
}
return '';
}));
Expand Down
18 changes: 10 additions & 8 deletions extensions/npm/src/npmScriptLens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import {
workspace,
l10n
} from 'vscode';
import { findPreferredPM } from './preferred-pm';
import { readScripts } from './readScripts';
import { getRunScriptCommand } from './tasks';


const enum Constants {
Expand Down Expand Up @@ -87,18 +87,20 @@ export class NpmScriptLensProvider implements CodeLensProvider, Disposable {
}

if (this.lensLocation === 'all') {
const packageManager = await findPreferredPM(Uri.joinPath(document.uri, '..').fsPath);
return tokens.scripts.map(
({ name, nameRange }) =>
new CodeLens(
const folder = Uri.joinPath(document.uri, '..');
return Promise.all(tokens.scripts.map(
async ({ name, nameRange }) => {
const runScriptCommand = await getRunScriptCommand(name, folder);
return new CodeLens(
nameRange,
{
title,
command: 'extension.js-debug.createDebuggerTerminal',
arguments: [`${packageManager.name} run ${name}`, workspace.getWorkspaceFolder(document.uri), { cwd }],
arguments: [runScriptCommand.join(' '), workspace.getWorkspaceFolder(document.uri), { cwd }],
},
),
);
);
},
));
}

return [];
Expand Down
9 changes: 5 additions & 4 deletions extensions/npm/src/npmView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import {
} from 'vscode';
import { readScripts } from './readScripts';
import {
createTask, getPackageManager, getTaskName, isAutoDetectionEnabled, isWorkspaceFolder, INpmTaskDefinition,
createInstallationTask, getTaskName, isAutoDetectionEnabled, isWorkspaceFolder, INpmTaskDefinition,
NpmTaskProvider,
startDebugging,
detectPackageManager,
ITaskWithLocation,
INSTALL_SCRIPT
} from './tasks';
Expand Down Expand Up @@ -150,8 +151,8 @@ export class NpmScriptsTreeDataProvider implements TreeDataProvider<TreeItem> {
}

private async runScript(script: NpmScript) {
// Call getPackageManager to trigger the multiple lock files warning.
await getPackageManager(this.context, script.getFolder().uri);
// Call detectPackageManager to trigger the multiple lock files warning.
await detectPackageManager(script.getFolder().uri, this.context, true);
tasks.executeTask(script.task);
}

Expand Down Expand Up @@ -181,7 +182,7 @@ export class NpmScriptsTreeDataProvider implements TreeDataProvider<TreeItem> {
if (!uri) {
return;
}
const task = await createTask(await getPackageManager(this.context, selection.folder.workspaceFolder.uri, true), 'install', ['install'], selection.folder.workspaceFolder, uri, undefined, []);
const task = await createInstallationTask(this.context, selection.folder.workspaceFolder, uri);
tasks.executeTask(task);
}

Expand Down
6 changes: 3 additions & 3 deletions extensions/npm/src/scriptHover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import {
} from 'vscode';
import { INpmScriptInfo, readScripts } from './readScripts';
import {
createTask,
getPackageManager, startDebugging
createScriptRunnerTask,
startDebugging
} from './tasks';


Expand Down Expand Up @@ -114,7 +114,7 @@ export class NpmScriptHoverProvider implements HoverProvider {
const documentUri = args.documentUri;
const folder = workspace.getWorkspaceFolder(documentUri);
if (folder) {
const task = await createTask(await getPackageManager(this.context, folder.uri), script, ['run', script], folder, documentUri);
const task = await createScriptRunnerTask(this.context, script, folder, documentUri);
await tasks.executeTask(task);
}
}
Expand Down
Loading

0 comments on commit e20adc3

Please sign in to comment.