diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index c657571..b07039d 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -9,6 +9,9 @@ on: jobs: build: + strategy: + matrix: + node-version: ['22', '24'] runs-on: ubuntu-latest permissions: contents: read @@ -19,8 +22,9 @@ jobs: - uses: oven-sh/setup-bun@v2 - uses: actions/setup-node@v4 with: - node-version: '25' - - uses: wgtechlabs/package-build-flow-action@v2.0.1 + node-version: ${{ matrix.node-version }} + - if: ${{ matrix.node-version == '22' }} + uses: wgtechlabs/package-build-flow-action@v2.0.1 with: npm-token: ${{ secrets.NPM_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ef96a5e..fe77ba3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ Thanks for your interest in contributing to **GitHub Labels Template**! Here's h ## Prerequisites -- [Node.js](https://nodejs.org) (v25+) +- [Node.js](https://nodejs.org) (v22+; LTS recommended: v22 or v24) - [Bun](https://bun.sh) (v1.0+) - [GitHub CLI](https://cli.github.com) (`gh`) installed and authenticated diff --git a/README.md b/README.md index a0415f1..8248120 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ A CLI tool to apply a curated set of GitHub labels to any repository using `gh` - 🚫 **Apply with Exclusions**: Skip specific labels or entire categories with `--exclude` / `--exclude-category` - ✅ **Pre-Flight Checks**: Validates `gh` CLI is installed and authenticated before doing anything - 📊 **Clear Output**: Structured logging powered by [@wgtechlabs/log-engine](https://github.com/wgtechlabs/log-engine) with color-coded levels and emoji -- 🎨 **ASCII Banner**: Beautiful ANSI Shadow figlet banner with version and author info +- 🎨 **ASCII Banner**: Styled Slant text logo with version and author info - 🤖 **AI Label Generator**: Generate custom labels using GitHub Copilot — interactive pick, refine, and apply - 🌐 **Node Runtime + Bun Toolchain**: Runs on Node.js, built and tested with Bun @@ -50,6 +50,8 @@ ghlt apply ## Prerequisites +- [Node.js](https://nodejs.org) (v22+; LTS recommended: v22 or v24) +- [Bun](https://bun.sh) (v1.0+) - [GitHub CLI](https://cli.github.com) (`gh`) installed and authenticated - [GitHub Copilot](https://github.com/features/copilot) subscription (required for `generate` command only) @@ -326,7 +328,7 @@ OPTIONS (preview) This project uses the [Bun test framework](https://bun.sh/docs/cli/test) for testing. -Runtime execution uses Node.js (latest recommended). +Runtime execution uses Node.js v22+ (LTS recommended: v22 or v24). ```bash # Run all tests diff --git a/bun.lock b/bun.lock index 6286f02..616a4b7 100644 --- a/bun.lock +++ b/bun.lock @@ -9,12 +9,10 @@ "@inquirer/prompts": "^8.2.1", "@wgtechlabs/log-engine": "^2.3.1", "citty": "^0.1.6", - "figlet": "^1.10.0", "picocolors": "^1.1.1", }, "devDependencies": { "@types/bun": "latest", - "@types/figlet": "^1.7.0", "@types/node": "^25.7.0", }, }, @@ -70,8 +68,6 @@ "@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="], - "@types/figlet": ["@types/figlet@1.7.0", "", {}, "sha512-KwrT7p/8Eo3Op/HBSIwGXOsTZKYiM9NpWRBJ5sVjWP/SmlS+oxxRvJht/FNAtliJvja44N3ul1yATgohnVBV0Q=="], - "@types/node": ["@types/node@25.7.0", "", { "dependencies": { "undici-types": "~7.21.0" } }, "sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg=="], "@wgtechlabs/log-engine": ["@wgtechlabs/log-engine@2.3.1", "", {}, "sha512-qYwGef4KjcWpFvfC/e6uum/Q2ICTJbaXBZf+qCDmho1rNZ/umqyeDH3Cvk86e2Jy5TkDFPA+rOcTkmrM1rGKkw=="], @@ -84,8 +80,6 @@ "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="], - "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], - "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], "fast-string-truncated-width": ["fast-string-truncated-width@3.0.3", "", {}, "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g=="], @@ -94,8 +88,6 @@ "fast-wrap-ansi": ["fast-wrap-ansi@0.2.0", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-rLV8JHxTyhVmFYhBJuMujcrHqOT2cnO5Zxj37qROj23CP39GXubJRBUFF0z8KFK77Uc0SukZUf7JZhsVEQ6n8w=="], - "figlet": ["figlet@1.10.0", "", { "dependencies": { "commander": "^14.0.0" }, "bin": { "figlet": "bin/index.js" } }, "sha512-aktIwEZZ6Gp9AWdMXW4YCi0J2Ahuxo67fNJRUIWD81w8pQ0t9TS8FFpbl27ChlTLF06VkwjDesZSzEVzN75rzA=="], - "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], "mute-stream": ["mute-stream@3.0.0", "", {}, "sha512-dkEJPVvun4FryqBmZ5KhDo0K9iDXAwn08tMLDinNdRBNPcYEDiWYysLcc6k3mjTMlbP9KyylvRpd4wFtwrT9rw=="], diff --git a/package.json b/package.json index 25f582f..b66181f 100644 --- a/package.json +++ b/package.json @@ -10,14 +10,15 @@ "dist" ], "scripts": { - "build": "bun build src/index.ts --outfile dist/index.js --target node --packages external", + "build": "bun build src/index.ts --outfile dist/index.js --target node", "dev": "bun run build && node dist/index.js", "preview": "bun run build && node dist/index.js preview", "start": "bun run build && node dist/index.js", - "test": "bun test" + "test": "bun test", + "prepack": "bun run build" }, "engines": { - "node": ">=25", + "node": ">=22", "bun": ">=1.0" }, "keywords": [ @@ -38,12 +39,10 @@ "@inquirer/prompts": "^8.2.1", "@wgtechlabs/log-engine": "^2.3.1", "citty": "^0.1.6", - "figlet": "^1.10.0", "picocolors": "^1.1.1" }, "devDependencies": { "@types/node": "^25.7.0", - "@types/bun": "latest", - "@types/figlet": "^1.7.0" + "@types/bun": "latest" } } diff --git a/src/index.ts b/src/index.ts index 9c1d064..c0cf645 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,13 +11,22 @@ import { showBanner, showUpdateBanner, getVersion } from "./ui/banner"; import { checkForUpdate } from "./utils/updater"; const isHelp = process.argv.includes("--help") || process.argv.includes("-h"); +const isVersion = process.argv.includes("--version") || process.argv.includes("-v"); const isUpdateCommand = process.argv.includes("update"); -showBanner(isHelp); -if (!isUpdateCommand) { - const availableUpdate = checkForUpdate(); - if (availableUpdate) { - showUpdateBanner(availableUpdate); +if (isVersion) { + console.log(`ghlt version v${getVersion()}`); + process.exit(0); +} + +if (!isVersion) { + showBanner(isHelp); + + if (!isUpdateCommand) { + const availableUpdate = checkForUpdate(); + if (availableUpdate) { + showUpdateBanner(availableUpdate); + } } } @@ -45,7 +54,7 @@ const main = defineCommand({ }, run({ args }) { if (args.version) { - console.log(`ghlt v${getVersion()}`); + console.log(`v${getVersion()}`); } }, }); diff --git a/src/ui/banner.ts b/src/ui/banner.ts index a2b255b..2dc7026 100644 --- a/src/ui/banner.ts +++ b/src/ui/banner.ts @@ -2,28 +2,18 @@ * CLI Banner * * ASCII art logo and version display for GHLT CLI. - * Uses figlet with ANSI Shadow font for a modern look. + * Uses a pre-rendered Slant logo for stable output across environments. * Displayed at the top of CLI output. */ -import figlet from "figlet"; import pc from "picocolors"; import pkg from "../../package.json"; -// Generate the logo at module load time (synchronous, fast) -let LOGO: string; -try { - LOGO = figlet.textSync("GHLT", { font: "ANSI Shadow" }); -} catch { - // Fallback if figlet font not available - LOGO = - ` ██████╗ ██╗ ██╗██╗ ████████╗\n` + - `██╔════╝ ██║ ██║██║ ╚══██╔══╝\n` + - `██║ ███╗███████║██║ ██║ \n` + - `██║ ██║██╔══██║██║ ██║ \n` + - `╚██████╔╝██║ ██║███████╗ ██║ \n` + - ` ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ `; -} +const LOGO = String.raw` ________ ____ ______ + / ____/ / / / / /_ __/ + / / __/ /_/ / / / / +/ /_/ / __ / /___/ / +\____/_/ /_/_____/_/`; /** * Get the version string from package.json @@ -66,25 +56,24 @@ export function showUpdateBanner(latestVersion: string): void { */ export function showBanner(minimal = false): void { console.log(pc.cyan("\n" + LOGO)); + console.log(); console.log( - ` ${pc.dim("v" + getVersion())} ${pc.dim("—")} ${pc.dim("Built by " + getAuthor())}` + ` ${pc.white(`v${getVersion()}`)} ${pc.white("—")} ${pc.white(`Built by ${getAuthor()}`)} ${pc.white("(")}${pc.white(linkify("with Him", "https://youtu.be/VOZbswniA-g?si=pdVHNSAfZW0vQLJ7"))}${pc.white(")")}` ); if (!minimal) { - console.log( - ` ${pc.dim(pkg.description)}` - ); console.log(); console.log( - ` ${pc.yellow("Star")} ${pc.cyan("https://gh.waren.build/github-labels-template")}` + ` 🤝 ${pc.white("Contribute:")} ${pc.dim(linkify("gh.waren.build/github-labels-template", "https://gh.waren.build/github-labels-template"))}` ); console.log( - ` ${pc.green("Contribute")} ${pc.cyan("https://gh.waren.build/github-labels-template/blob/main/CONTRIBUTING.md")}` - ); - console.log( - ` ${pc.magenta("Sponsor")} ${pc.cyan("https://warengonzaga.com/sponsor")}` + ` 🙏 ${pc.white("Sponsor:")} ${pc.dim(linkify("warengonzaga.com/sponsor", "https://warengonzaga.com/sponsor"))}` ); } console.log(); } + +function linkify(label: string, url: string): string { + return `\u001B]8;;${url}\u0007${label}\u001B]8;;\u0007`; +}