Skip to content

Commit 6d84924

Browse files
authored
fix(cli): use dynamic import for @inquirer/prompts in config command (#392)
* fix(cli): use dynamic import for @inquirer/prompts in config command The config command (added in #382) reintroduced the pre-commit hook hang issue that was fixed in #380. The static import of @inquirer/prompts at module load time causes stdin event listeners to be registered even when running non-interactive commands, preventing clean process exit when stdin is piped (as pre-commit does). Convert the static import to a dynamic import that only loads inquirer when the `config reset` command is actually used interactively. Fixes #367 * chore: add ESLint with no-restricted-imports rule for @InQuirer Add ESLint configuration that prevents static imports of @inquirer/* modules. This prevents future regressions of the pre-commit hook hang issue fixed in this PR. The rule shows a helpful error message pointing to issue #367 for context. init.ts is exempted since it's already dynamically imported from the CLI. * ci: add ESLint step to lint job Run `pnpm lint` in CI to enforce the no-restricted-imports rule that prevents static @InQuirer imports.
1 parent 6de04f3 commit 6d84924

File tree

5 files changed

+811
-1
lines changed

5 files changed

+811
-1
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ jobs:
142142
- name: Type check
143143
run: pnpm exec tsc --noEmit
144144

145+
- name: Lint
146+
run: pnpm lint
147+
145148
- name: Check for build artifacts
146149
run: |
147150
if [ ! -d "dist" ]; then

eslint.config.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import tseslint from 'typescript-eslint';
2+
3+
export default tseslint.config(
4+
{
5+
files: ['src/**/*.ts'],
6+
extends: [...tseslint.configs.recommended],
7+
rules: {
8+
// Prevent static imports of @inquirer modules to avoid pre-commit hook hangs.
9+
// These modules have side effects that can keep the Node.js event loop alive
10+
// when stdin is piped. Use dynamic import() instead.
11+
// See: https://github.com/Fission-AI/OpenSpec/issues/367
12+
'no-restricted-imports': [
13+
'error',
14+
{
15+
patterns: [
16+
{
17+
group: ['@inquirer/*'],
18+
message:
19+
'Use dynamic import() for @inquirer modules to prevent pre-commit hook hangs. See #367.',
20+
},
21+
],
22+
},
23+
],
24+
// Disable rules that need broader cleanup - focus on critical issues only
25+
'@typescript-eslint/no-explicit-any': 'off',
26+
'@typescript-eslint/no-unused-vars': 'off',
27+
'no-empty': 'off',
28+
'prefer-const': 'off',
29+
},
30+
},
31+
{
32+
// init.ts is dynamically imported from cli/index.ts, so static @inquirer
33+
// imports there are safe - they won't be loaded at CLI startup
34+
files: ['src/core/init.ts'],
35+
rules: {
36+
'no-restricted-imports': 'off',
37+
},
38+
},
39+
{
40+
ignores: ['dist/**', 'node_modules/**', '*.js', '*.mjs'],
41+
}
42+
);

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"!dist/**/*.map"
3939
],
4040
"scripts": {
41+
"lint": "eslint src/",
4142
"build": "node build.js",
4243
"dev": "tsc --watch",
4344
"dev:cli": "pnpm build && node bin/openspec.js",
@@ -62,7 +63,9 @@
6263
"@changesets/cli": "^2.27.7",
6364
"@types/node": "^24.2.0",
6465
"@vitest/ui": "^3.2.4",
66+
"eslint": "^9.39.2",
6567
"typescript": "^5.9.3",
68+
"typescript-eslint": "^8.50.1",
6669
"vitest": "^3.2.4"
6770
},
6871
"dependencies": {

0 commit comments

Comments
 (0)