From 7883da658b4300150760cf662a98e360a25640c9 Mon Sep 17 00:00:00 2001 From: bymle Date: Sun, 7 Jun 2026 13:25:39 +0800 Subject: [PATCH] fix(dev-server-block): stop blocking dev- scripts (#2179) `DEV_PATTERN`'s trailing `\b` treats a hyphen as a word boundary, so `dev\b` matched the `dev` prefix of distinct npm scripts like `dev-setup` / `dev-docs` / `dev-build` and blocked them with exit 2. Replace the trailing `\b` with `(?![\w-])` so the dev server still matches (`dev`, `dev;`, `dev:ssr`) but `dev-` scripts pass. Adds regression tests for dev-setup/dev-docs/dev-build (allowed) and dev:ssr (still blocked). Co-authored-by: bymle <229636660+bymle@users.noreply.github.com> --- scripts/hooks/pre-bash-dev-server-block.js | 6 ++++- tests/hooks/pre-bash-dev-server-block.test.js | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/scripts/hooks/pre-bash-dev-server-block.js b/scripts/hooks/pre-bash-dev-server-block.js index cd663fa7..06eb6402 100755 --- a/scripts/hooks/pre-bash-dev-server-block.js +++ b/scripts/hooks/pre-bash-dev-server-block.js @@ -161,7 +161,11 @@ process.stdin.on('data', chunk => { }); const TMUX_LAUNCHER = /^\s*tmux\s+(new|new-session|new-window|split-window)\b/; -const DEV_PATTERN = /\b(npm\s+run\s+dev|pnpm(?:\s+run)?\s+dev|yarn(?:\s+run)?\s+dev|bun(?:\s+run)?\s+dev)\b/; +// Trailing (?![\w-]) rather than \b: \b treats a hyphen as a word boundary, so +// `dev\b` matches the `dev` prefix of distinct scripts like `dev-setup` / +// `dev-docs` / `dev-build` and wrongly blocks them. The lookahead still matches +// the dev server (`dev`, `dev;`, `dev:ssr`, ...) but not a `dev-` script. +const DEV_PATTERN = /\b(npm\s+run\s+dev|pnpm(?:\s+run)?\s+dev|yarn(?:\s+run)?\s+dev|bun(?:\s+run)?\s+dev)(?![\w-])/; /** * Collect every command-line segment we should evaluate. Returns the top-level diff --git a/tests/hooks/pre-bash-dev-server-block.test.js b/tests/hooks/pre-bash-dev-server-block.test.js index 4f075ddb..89524b1e 100644 --- a/tests/hooks/pre-bash-dev-server-block.test.js +++ b/tests/hooks/pre-bash-dev-server-block.test.js @@ -63,6 +63,11 @@ function runTests() { const result = runScript('bun run dev'); assert.strictEqual(result.code, 2, `Expected exit code 2, got ${result.code}`); }) ? passed++ : failed++); + + (test('still blocks npm run dev:ssr — colon variant is a dev server (exit 2)', () => { + const result = runScript('npm run dev:ssr'); + assert.strictEqual(result.code, 2, `Expected exit code 2, got ${result.code}`); + }) ? passed++ : failed++); } else { console.log(' (skipping blocking tests on Windows)\n'); } @@ -89,6 +94,23 @@ function runTests() { assert.strictEqual(result.code, 0, `Expected exit code 0, got ${result.code}`); }) ? passed++ : failed++); + // --- dev- scripts are distinct from the dev server, must not be blocked --- + + (test('allows npm run dev-setup — distinct script, not the dev server (exit 0)', () => { + const result = runScript('npm run dev-setup'); + assert.strictEqual(result.code, 0, `Expected exit code 0, got ${result.code}`); + }) ? passed++ : failed++); + + (test('allows pnpm run dev-docs — distinct script (exit 0)', () => { + const result = runScript('pnpm run dev-docs'); + assert.strictEqual(result.code, 0, `Expected exit code 0, got ${result.code}`); + }) ? passed++ : failed++); + + (test('allows yarn dev-build — distinct script (exit 0)', () => { + const result = runScript('yarn dev-build'); + assert.strictEqual(result.code, 0, `Expected exit code 0, got ${result.code}`); + }) ? passed++ : failed++); + // --- Subshell bypass regression (issue: dev server slipped past via $(), ``, ()) --- if (!isWindows) {