Skip to content

refactor: migrate from qqjs to execa with custom wrapper#3678

Merged
eablack merged 5 commits intomainfrom
eb/migrate-qqjs-to-execa
Apr 22, 2026
Merged

refactor: migrate from qqjs to execa with custom wrapper#3678
eablack merged 5 commits intomainfrom
eb/migrate-qqjs-to-execa

Conversation

@eablack
Copy link
Copy Markdown
Contributor

@eablack eablack commented Apr 22, 2026

Summary

This PR replaces the qqjs dependency with execa v9 and introduces a lightweight wrapper (scripts/utils/exec.ts) that preserves qqjs behavior while modernizing our command execution infrastructure.

Key changes:

  • Created scripts/utils/exec.ts wrapper with x(), shell(), stdout(), and run() helpers that maintain qqjs defaults (stdio inheritance, command logging, error handling)
  • Migrated all qqjs usage across 4 files to use the new exec wrapper
  • Fixed breaking changes from execa v5→v9 in 2 additional files (homebrew.js, plugin tests)
  • Removed qqjs dependency (63 packages removed from node_modules)

Benefits:

  • Modern execa v9 with better TypeScript support and active maintenance
  • Simplified codebase with consistent command execution API
  • Net reduction of 539 lines of code
  • No behavior changes - all existing functionality preserved

Type of Change

Patch Updates (patch semver update)

  • refactor: Refactoring existing code without changing behavior

Testing

Notes:
All existing scripts and tests continue to work unchanged. The exec.ts wrapper preserves exact qqjs behavior:

  • stdio inheritance by default
  • Command logging ($ command output)
  • Error handling with process.exitCode
  • Trailing newline trimming in stdout capture

Steps:

  1. Passing CI suffices - all existing functionality is preserved with no behavior changes
  2. Scripts that were tested: install-scripts.js, homebrew.js, version.js, smoke tests, plugin tests

@eablack eablack requested a review from a team as a code owner April 22, 2026 14:55
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:16 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:16 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:16 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:16 — with GitHub Actions Inactive
eablack added 3 commits April 22, 2026 11:17
Replaces qqjs dependency with execa v9 and introduces a lightweight
exec.ts wrapper that preserves qqjs behavior (stdio inheritance,
command logging, error handling).

Changes:
- Created scripts/utils/exec.ts wrapper with x(), shell(), stdout(), and run() helpers
- Migrated all qqjs usage to exec.ts (install-scripts.js, version.js, smoke tests)
- Fixed execa v8→v9 breaking changes in homebrew.js and plugin tests
  - Updated import syntax: import execa from 'execa' → import {execa} from 'execa'
  - Replaced execa.command() with shell() helper (removed in v9)
  - Updated stdio array syntax to named properties
- Removed qqjs dependency (63 packages removed)

The exec.ts wrapper provides a consistent API across all scripts:
- x(cmd, args, opts): Execute with args array (stdio: 'inherit' default)
- shell(cmd, opts): Execute shell commands (strings with pipes, etc.)
- stdout(cmd, args, opts): Capture stdout as string (trims trailing newline)
- run(fn): Async error handler (logs errors, sets process.exitCode)
- config.silent: Toggle command logging

All existing functionality preserved, no behavior changes.
Simplifications:
- Removed unused config.silent feature (only ever set to false)
- Inlined console.log calls (removed log() helper)
- Removed intermediate defaultOptions variables
- Reduced from 75 lines to 60 lines (20% reduction)

Renamed exec.ts → script-exec.ts to clarify purpose:
- script-exec.ts provides wrappers for shell scripts (stdio: 'inherit')
- Tests that need to capture output use execa directly

Changes:
- scripts/utils/exec.ts → scripts/utils/script-exec.ts
- Updated all imports across 5 files
- smoke.acceptance.test.ts: uses execa directly (needs output capture)
- plugin.acceptance.test.ts: uses script-exec.ts (no capture needed)
- Fixed TypeScript syntax in install-scripts.js (removed 'as const')

All tests pass with proper type checking.
@eablack eablack force-pushed the eb/migrate-qqjs-to-execa branch from d66ed82 to b8f82a7 Compare April 22, 2026 15:17
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:17 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:17 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:17 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:17 — with GitHub Actions Inactive
Converted script-exec from TypeScript to plain JavaScript to eliminate
the build step dependency. Scripts can now run directly without requiring
'npm run build' first, which is more reliable for CI/CD pipelines.

Changes:
- src/lib/scripts/script-exec.ts → scripts/utils/script-exec.js
- Removed all TypeScript type annotations
- Reverted all imports back to ../utils/script-exec.js paths
- No build step required

Benefits:
- Scripts work immediately without compilation
- Simpler CI/CD - no build step before running scripts
- Fewer failure points in release automation
- 60 lines of clean, dependency-minimal JavaScript

Validation:
- All scripts pass syntax check
- install-scripts.js executes correctly
- version.js executes and returns version
- All tests type check correctly
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:31 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:31 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:31 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:31 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:34 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:34 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:34 — with GitHub Actions Inactive
@eablack eablack temporarily deployed to AcceptanceTests April 22, 2026 15:34 — with GitHub Actions Inactive
Copy link
Copy Markdown
Contributor

@tlowrimore-heroku tlowrimore-heroku left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@eablack eablack merged commit ad81615 into main Apr 22, 2026
17 checks passed
@eablack eablack deleted the eb/migrate-qqjs-to-execa branch April 22, 2026 16:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants