diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9046d24..d8ecf42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,6 +9,18 @@ permissions: contents: read jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + + - run: npm ci + - run: npm run lint + build: strategy: fail-fast: false diff --git a/biome.json b/biome.json new file mode 100644 index 0000000..a3f544f --- /dev/null +++ b/biome.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.5.9/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "includes": ["**", "!!**/dist", "!!tsconfig.json", "!!package-lock.json"] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2 + }, + "linter": { + "enabled": true, + "rules": { + "preset": "recommended" + } + }, + "javascript": { + "formatter": { + "quoteStyle": "single" + } + }, + "assist": { + "enabled": true, + "actions": { + "source": { + "organizeImports": "on" + } + } + } +} diff --git a/build-bundle.js b/build-bundle.js index c51cfa3..3012bb5 100644 --- a/build-bundle.js +++ b/build-bundle.js @@ -1,12 +1,14 @@ const esbuild = require('esbuild'); -esbuild.build({ - entryPoints: ['hello.ts'], - bundle: true, - outfile: 'dist/bundled/bundle.js', - platform: 'node', - target: 'node24', - format: 'cjs', - sourcemap: true, - minify: true, -}).catch(() => process.exit(1)); \ No newline at end of file +esbuild + .build({ + entryPoints: ['hello.ts'], + bundle: true, + outfile: 'dist/bundled/bundle.js', + platform: 'node', + target: 'node24', + format: 'cjs', + sourcemap: true, + minify: true, + }) + .catch(() => process.exit(1)); diff --git a/build-sea.js b/build-sea.js index 176cf47..5d5cf8a 100644 --- a/build-sea.js +++ b/build-sea.js @@ -1,5 +1,5 @@ -const { execSync } = require('child_process'); -const fs = require('fs'); +const { execSync } = require('node:child_process'); +const fs = require('node:fs'); // Ensure the bundle exists if (!fs.existsSync('./dist/bundled/bundle.js')) { @@ -14,10 +14,14 @@ fs.mkdirSync('dist', { recursive: true }); console.log('Building SEA binary (node --build-sea)...'); try { execSync('node --build-sea sea-config.json', { stdio: 'inherit' }); -} catch (error) { +} catch { console.error('\nFailed to build the SEA binary.'); - console.error(`node --build-sea requires Node.js 25.5+ — you are running ${process.version}.`); - console.error('As of this writing it only ships on the Node 26 "Current" release line (not yet backported to the 24 LTS line). Switch with: nvm install 26 && nvm use 26'); + console.error( + `node --build-sea requires Node.js 25.5+ — you are running ${process.version}.`, + ); + console.error( + 'As of this writing it only ships on the Node 26 "Current" release line (not yet backported to the 24 LTS line). Switch with: nvm install 26 && nvm use 26', + ); process.exit(1); } @@ -43,8 +47,12 @@ if (process.platform === 'darwin') { process.exit(1); } } else if (process.platform === 'win32') { - console.log(`On Windows, sign ${outputPath} yourself if you need a trusted binary:`); + console.log( + `On Windows, sign ${outputPath} yourself if you need a trusted binary:`, + ); console.log(` signtool sign /fd SHA256 ${outputPath}`); } -console.log(`SEA binary creation complete! The executable is ready: ./${outputPath}`); +console.log( + `SEA binary creation complete! The executable is ready: ./${outputPath}`, +); diff --git a/hello.ts b/hello.ts index c5153c7..2e11ebb 100644 --- a/hello.ts +++ b/hello.ts @@ -1,5 +1,5 @@ import { Command } from 'commander'; -import { Greeter } from './lib/greeter'; +import { sayHello } from './lib/greeter'; const program = new Command(); @@ -8,7 +8,7 @@ program .description('A simple greeting command') .argument('', 'name to greet') .action((name: string) => { - Greeter.sayHello(name); + sayHello(name); }); -program.parse(); \ No newline at end of file +program.parse(); diff --git a/lib/greeter.test.ts b/lib/greeter.test.ts index 978eafb..cd912a3 100644 --- a/lib/greeter.test.ts +++ b/lib/greeter.test.ts @@ -1,6 +1,6 @@ -import { test } from 'node:test'; import assert from 'node:assert/strict'; -import { Greeter } from './greeter'; +import { test } from 'node:test'; +import { sayHello } from './greeter'; test('sayHello prints a greeting with the given name', () => { const lines: string[] = []; @@ -8,7 +8,7 @@ test('sayHello prints a greeting with the given name', () => { console.log = (line: string) => lines.push(line); try { - Greeter.sayHello('World'); + sayHello('World'); } finally { console.log = originalLog; } @@ -23,7 +23,7 @@ test('sayHello reflects the name back verbatim', () => { console.log = (line: string) => lines.push(line); try { - Greeter.sayHello('Node 26'); + sayHello('Node 26'); } finally { console.log = originalLog; } diff --git a/lib/greeter.ts b/lib/greeter.ts index 8b46483..58d48ee 100644 --- a/lib/greeter.ts +++ b/lib/greeter.ts @@ -1,6 +1,3 @@ -// Utility class for greeting functionality -export class Greeter { - static sayHello(name: string): void { - console.log(`Hello, ${name}!`); - } -} \ No newline at end of file +export function sayHello(name: string): void { + console.log(`Hello, ${name}!`); +} diff --git a/package-lock.json b/package-lock.json index ebd943f..88a66dd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "ISC", "devDependencies": { + "@biomejs/biome": "^2.5.9", "@types/node": "^24.13.3", "commander": "^15.0.0", "esbuild": "^0.28.2", @@ -19,6 +20,181 @@ "node": ">=26.0.0" } }, + "node_modules/@biomejs/biome": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.5.9.tgz", + "integrity": "sha512-KkgCvdHB4IhtpHpF564plA9jo6fDOwWGQ/3jvreLzgOtRLEDoPqr7QO9qejNA8jKwDsSkAKr77hqBHnyUbIw4g==", + "dev": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "2.5.9", + "@biomejs/cli-darwin-x64": "2.5.9", + "@biomejs/cli-linux-arm64": "2.5.9", + "@biomejs/cli-linux-arm64-musl": "2.5.9", + "@biomejs/cli-linux-x64": "2.5.9", + "@biomejs/cli-linux-x64-musl": "2.5.9", + "@biomejs/cli-win32-arm64": "2.5.9", + "@biomejs/cli-win32-x64": "2.5.9" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.5.9.tgz", + "integrity": "sha512-am22pX2aBqznqq1eMyIj/bZ++riF3Lk6ct7cbv+gQK0csFhr+d8O0RkOi2FF2qSgFgANbqNkIZ0/PxlnW2pLFg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.5.9.tgz", + "integrity": "sha512-l44KWDHLDvEnD0N/XcrVs7VXb3A18xL7QS3WB0eL93wbmk529ffIG55vleGCqaunpRUjLrdnjK05Qki1dsjylg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.5.9.tgz", + "integrity": "sha512-ICaK+IYaVZvKbBxX2rwrPT0DdUDMnE9Vm3nQGe+mltQPmUg19pONzkPWGdY4FCsoreDETWDynvdt4ysCbF5gNQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.5.9.tgz", + "integrity": "sha512-7ImVPwBLCtkmpR5esd8RHhTqW94f0JLJQum6AneYcy94jRm18TaPPm7slaigGzFhfgt3QiD1Vj52LKmBAnKizA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.5.9.tgz", + "integrity": "sha512-z22Q/zFYSvbIJfW1CbfZPu4X8PddS6Qd2ORbc6h+aT6EcwAxUF3m6fA4HjNvA3TU4X0dTJRwNPB165ES3PJXzg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.5.9.tgz", + "integrity": "sha512-RXGaD0o1/pTTguYw1aeDJh9ad6Lfrui0fI7mBderTyGr7WuUJkBIttgLkR3XJyoxOkkgfBDspaUT8wXArTqLZw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.5.9.tgz", + "integrity": "sha512-nHK+/HHC+D0ogAHUxomgoSTdjImb6fmNNVTKmf0tyu4eDL1DqPKIHc+i+UL8+b0RnAu8224qo8F2tCVnaT0A3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.5.9", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.5.9.tgz", + "integrity": "sha512-Yiq0H56LjXSSw/hd9YkXgSLQfzyDJzbzU2TezozxyNw+uKWAqOtqGVvBfzKRRDiaFF5avGAhHdWKx7LtDOShUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", diff --git a/package.json b/package.json index f225871..ec46e80 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,17 @@ "build:js": "tsc", "build:bundle": "node build-bundle.js", "build:sea": "node build-sea.js", - "build:all": "npm run clean && npm run build:js && npm run build:bundle && npm run build:sea" + "build:all": "npm run clean && npm run build:js && npm run build:bundle && npm run build:sea", + "lint": "biome check .", + "format": "biome check --write ." }, - "keywords": ["node", "sea", "single-executable-application", "typescript", "esbuild"], + "keywords": [ + "node", + "sea", + "single-executable-application", + "typescript", + "esbuild" + ], "author": "Hamdi LAADHARI", "license": "ISC", "type": "commonjs", @@ -28,6 +36,7 @@ "node": ">=26.0.0" }, "devDependencies": { + "@biomejs/biome": "^2.5.9", "@types/node": "^24.13.3", "commander": "^15.0.0", "esbuild": "^0.28.2",