Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
name: Node ${{ matrix.node-version }}
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
node-version: [20, 22]

steps:
- uses: actions/checkout@v4

- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Type check
run: npm run typecheck

- name: Lint
run: npm run lint

- name: Format check
run: npm run format

- name: Run unit tests
run: npm run test:cov

- name: Build
run: npm run build:ci

- name: Run integration tests
run: npm run test:integration:ci

- name: Upload coverage
if: matrix.node-version == 22
uses: codecov/codecov-action@v4
with:
files: ./coverage/coverage-final.json
fail_ci_if_error: false
70 changes: 19 additions & 51 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,80 +2,48 @@

All notable changes to this project will be documented in this file.

## [0.3.1] - 2025-12-09
## [0.3.2] - 2025-12-10

### Changed

- **Build Process Simplification**: Removed wrapper script complexity in favor of direct SWC compilation
- **Postbuild Script**: Replaced `insert-shebang.sh` with lightweight `add-shebang.js` Node script
- **CJS Package Generation**: Now generated inline in build script instead of via wrapper
- **README**: Updated "How It Works" section to reflect simplified build architecture

### Technical Details

**Build Process (Simplified):**
- **CI**: Main-only triggers, concurrency cancellation, Node 20/22 matrix, unit tests run with coverage
- **Tests**: Unit and integration suites split into separate Vitest configs
- **Build**: CI builds once (`build:ci`) before running integration tests; Codecov upload is best-effort

1. Prebuild: format:fix → lint → typecheck → clean
2. Compile: SWC compiles source to both `build/esm/src/` and `build/cjs/src/`
3. Path Resolution: `tsc-alias` transforms `@/` imports to relative paths
4. Executables: `add-shebang.js` adds shebangs and sets executable permissions
5. CJS Marker: `package.json` with `"type":"commonjs"` created in `build/cjs/`
## [0.3.1] - 2025-12-09

**Entry Points:**
### Changed

- ESM: `build/esm/src/cli.js` (executable)
- CJS: `build/cjs/src/cli.js` (executable)
- **Build**: Simplified to direct SWC outputs plus a lightweight `add-shebang.js` script
- **Docs**: README "How It Works" refreshed for the new build shape
- **CI**: Added GitHub Actions on Node 20/22

## [0.3.0] - 2025-12-09

### Added

- **Dual Build System**: Project compiles to both ESM (`build/esm/`) and CommonJS (`build/cjs/`) with proper module format markers
- **Path Aliases**: TypeScript path aliases (`@/*`) work throughout codebase and resolve to relative paths in output
- **Build Validation**: Code quality checks (format, lint, typecheck) run automatically in prebuild step
- **Source Maps**: Both ESM and CJS builds include source maps for debugging
- **ESM dirname Utility**: New `getDirname()` utility for ES module-compatible directory resolution
- **Comprehensive Tests**: 27 total tests (9 unit + 18 integration) with 100% code coverage
- **Integration Test Suite**: Dedicated `tests/integration/` with build output and module format validation
- **JSDoc Comments**: All functions documented for IDE support and clarity
- **Improved README**: Comprehensive documentation with features, usage, and architecture explanation
- **Dual Outputs**: ESM and CJS builds with source maps and path alias resolution
- **Tests**: 27 total (unit + integration) plus coverage; integration suite validates build outputs
- **Docs**: README expanded; JSDoc coverage improved

### Changed

- **Tooling Migration**: Replaced ESLint + Prettier with Biome for unified linting/formatting
- **Node Version**: Updated from 16+ to 20+ for stable ESM support without flags
- **Build Scripts**: Restructured with separate SWC configurations for ESM and CJS
- **CLI Implementation**: Enhanced with better error handling and version management
- **Testing Framework**: Upgraded from Vite test to dedicated Vitest with coverage
- **Project Structure**: Added utilities folder and proper test file organization
- **Tooling**: ESLint/Prettier replaced by Biome; Vitest adopted with coverage
- **Runtime**: Node requirement raised to 20+ for stable ESM; build scripts split per format

### Removed

- ESLint configuration and plugins
- Prettier configuration
- Old single build configuration (`.swcrc`)
- Unreachable Node version check code
- Legacy lint/format configs and the single `.swcrc`
- Unreachable Node version guard

### Fixed

- Test file exclusion from production builds
- Path alias transformation for both module formats
- Vitest configuration to prevent test discovery in build directory
- CJS module format declaration
- Test files excluded from builds; aliases resolved correctly; build dir no longer scanned by tests

### Dependencies Updated

- TypeScript: 4.9.5 → 5.9.3
- SWC: 1.3.35 → 1.15.3
- Commander: 10.0.0 → 14.0.2
- Vitest: 0.28.5 → 4.0.15
- Biome: 2.3.8 (new)
- tsc-alias: 1.8.16 (new)
- @vitest/coverage-v8: 4.0.15 (new)
- TypeScript, SWC, Commander, Vitest, Biome, tsc-alias, @vitest/coverage-v8

### Breaking Changes

- Requires Node.js 20+ (was 16+)
- Dual ESM/CJS structure replaces single build output
- Package exports field specifies import/require conditions
- CLI now uses Biome instead of ESLint/Prettier
- Requires Node 20+ and dual ESM/CJS outputs; exports now specify import/require conditions
23 changes: 4 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hello-cli",
"version": "0.3.1",
"version": "0.3.2",
"description": "A basic CLI written in TypeScript meant to be used as an example or project starter",
"type": "module",
"bin": "./build/esm/src/cli.js",
Expand Down Expand Up @@ -31,9 +31,10 @@
},
"scripts": {
"prebuild": "npm run format:fix && npm run lint && npm run typecheck && rm -rf ./build",
"build:esm": "swc src --config-file .swcrc-esm -d build/esm --ignore '**/*.test.ts' && tsc-alias -p tsconfig.json --outDir build/esm --resolve-full-paths",
"build:cjs": "swc src --config-file .swcrc-cjs -d build/cjs --ignore '**/*.test.ts' && tsc-alias -p tsconfig.json --outDir build/cjs --resolve-full-paths && echo '{\"type\":\"commonjs\"}' > build/cjs/package.json",
"build:esm": "swc src --config-file .swcrc-esm -d build/esm --ignore '**/*.test.ts' && tsc-alias -p tsconfig.json --outDir build/esm --resolve-full-paths || exit 1",
"build:cjs": "swc src --config-file .swcrc-cjs -d build/cjs --ignore '**/*.test.ts' && tsc-alias -p tsconfig.json --outDir build/cjs --resolve-full-paths && echo '{\"type\":\"commonjs\"}' > build/cjs/package.json || exit 1",
"build": "npm run build:esm && npm run build:cjs && node ./add-shebang.js",
"build:ci": "rm -rf ./build && npm run build:esm && npm run build:cjs && node ./add-shebang.js",
"build:debug": "swc --config-file .swcrc-esm -s true -D src -d build/esm",
"typecheck": "tsc --noEmit",
"prepublishOnly": "npm run typecheck && npm run lint && npm test && npm run build",
Expand All @@ -43,7 +44,8 @@
"lint": "biome lint ./src",
"lint:fix": "biome lint --write ./src",
"test": "vitest run",
"test:integration": "npm run build && vitest run tests/integration",
"test:integration": "npm run build && vitest run --config vitest.config.integration.ts",
"test:integration:ci": "vitest run --config vitest.config.integration.ts",
"test:all": "npm test && npm run test:integration",
"test:cov": "vitest run --coverage"
},
Expand Down
17 changes: 17 additions & 0 deletions vitest.config.integration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { fileURLToPath } from "node:url";
import { dirname, resolve } from "node:path";
import { defineConfig } from "vitest/config";

const __dirname = dirname(fileURLToPath(import.meta.url));

export default defineConfig({
test: {
exclude: ["**/node_modules/**", "**/build/**"],
include: ["tests/integration/**/*.{test,spec}.{js,ts}"],
},
resolve: {
alias: {
"@": resolve(__dirname, "./src"),
},
},
});
1 change: 1 addition & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
export default defineConfig({
test: {
exclude: ["**/node_modules/**", "**/build/**"],
include: ["src/**/*.{test,spec}.{js,ts}"],
coverage: {
reporter: ["text", "json", "html"],
},
Expand Down