diff --git a/.github/actions/test/action.yml b/.github/actions/test/action.yml new file mode 100644 index 0000000..608d34b --- /dev/null +++ b/.github/actions/test/action.yml @@ -0,0 +1,38 @@ +name: Test +description: "Run tests, generate coverage reports, and upload coverage badge to GitHub Gist" + +inputs: + version: + required: false + description: "Package version (latest or beta)" + gist_id: + required: false + description: 'The ID of the GitHub Gist where the coverage badge will be uploaded' + gist_token: + required: false + description: 'GitHub personal access token with Gist permissions for authentication' + +runs: + using: "composite" + steps: + - name: Run tests with coverage + shell: bash + run: | + npm run test -- --coverage --coverageReporters lcovonly json-summary + + - name: Generate coverage badge + if: ${{ inputs.gist_id && inputs.gist_token }} + shell: bash + run: | + echo "REPO_NAME=${GITHUB_REPOSITORY#*/}" >> $GITHUB_ENV + + - name: Upload coverage badge to GitHub Gist + if: ${{ (inputs.version == 'latest' || inputs.version == 'beta') && inputs.gist_id && inputs.gist_token }} + uses: exuanbo/actions-deploy-gist@v1 + continue-on-error: true + with: + token: ${{ inputs.gist_token }} + gist_id: ${{ inputs.gist_id }} + gist_file_name: "coverage-${{ env.REPO_NAME }}-${{ inputs.version }}.svg" + file_path: "./coverage/badge.svg" + file_type: "text" diff --git a/.github/workflows/publish-beta.yml b/.github/workflows/publish-beta.yml index 7fb0ff4..8288477 100644 --- a/.github/workflows/publish-beta.yml +++ b/.github/workflows/publish-beta.yml @@ -1,4 +1,4 @@ -name: Publish beta +name: Beta on: pull_request: @@ -17,50 +17,8 @@ on: - submitted jobs: - test: - name: Test - runs-on: ubuntu-latest - environment: test - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Node.js - uses: actions/setup-node@v4 - with: - node-version: 22 - registry-url: 'https://registry.npmjs.org' - - - name: Setup version - run: | - PACKAGE_NAME=$(npm pkg get name | sed -e 's/^"//' -e 's/"$//') - PACKAGE_VERSION=$(npm pkg get version | sed -e 's/^"//' -e 's/"$//') - PUBLISHED_VERSION=$(npm view $PACKAGE_NAME@beta version 2>/dev/null || echo "") - if [[ "$PUBLISHED_VERSION" == "$PACKAGE_VERSION"* ]]; then - INDEX=$(echo $PUBLISHED_VERSION | sed -r -e 's/^[0-9]+\.[0-9]+\.[0-9]+-beta\.//' | awk '{print $0+1}') - else - INDEX=0 - fi - npm pkg set version=$PACKAGE_VERSION-beta.$INDEX - - - name: Cache dependencies - uses: actions/cache@v4 - with: - path: ~/.npm - key: ${{ runner.os }}-npm-${{ hashFiles('**/package.json') }} - restore-keys: | - ${{ runner.os }}-npm- - - - name: Install dependencies - run: npm install - - - name: Test - run: npm run test - publish-beta: name: Publish beta version - if: github.repository_owner == 'kearisp' - needs: test runs-on: ubuntu-latest environment: publish permissions: @@ -68,28 +26,21 @@ jobs: id-token: write steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - - name: Set up Node.js - uses: actions/setup-node@v4 + - name: Setup Node.js + uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 registry-url: 'https://registry.npmjs.org' - name: Setup version - run: | - PACKAGE_NAME=$(npm pkg get name | sed -e 's/^"//' -e 's/"$//') - PACKAGE_VERSION=$(npm pkg get version | sed -e 's/^"//' -e 's/"$//') - PUBLISHED_VERSION=$(npm view $PACKAGE_NAME@beta version 2>/dev/null || echo "") - if [[ "$PUBLISHED_VERSION" == "$PACKAGE_VERSION"* ]]; then - INDEX=$(echo $PUBLISHED_VERSION | sed -r -e 's/^[0-9]+\.[0-9]+\.[0-9]+-beta\.//' | awk '{print $0+1}') - else - INDEX=0 - fi - npm pkg set version=$PACKAGE_VERSION-beta.$INDEX + uses: kearisp/npm-version-action@v0.0.3 + with: + tag: beta - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.npm key: ${{ runner.os }}-npm-${{ hashFiles('**/package.json') }} @@ -97,10 +48,20 @@ jobs: ${{ runner.os }}-npm- - name: Install dependencies + shell: bash run: npm install + - name: Test + uses: ./.github/actions/test + timeout-minutes: 2 + with: + version: "beta" + gist_token: ${{ secrets.GIST_TOKEN }} + gist_id: ${{ secrets.GIST_ID }} + - name: Publish Beta to NPM + if: github.repository_owner == 'kearisp' + shell: bash env: NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} - run: | - npm publish --provenance --tag beta + run: npm publish --provenance --tag beta diff --git a/.github/workflows/publish-latest.yml b/.github/workflows/publish-latest.yml index 03faa6f..6b154f7 100644 --- a/.github/workflows/publish-latest.yml +++ b/.github/workflows/publish-latest.yml @@ -1,4 +1,4 @@ -name: Publish latest +name: Latest on: release: @@ -8,7 +8,6 @@ on: jobs: publish: name: Publish latest version - if: ${{ github.repository_owner == 'kearisp' }} runs-on: ubuntu-latest environment: publish permissions: @@ -16,16 +15,16 @@ jobs: id-token: write steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - - name: Set up Node.js - uses: actions/setup-node@v4 + - name: Setup Node.js + uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 registry-url: 'https://registry.npmjs.org' - name: Cache dependencies - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.npm key: ${{ runner.os }}-npm-${{ hashFiles('**/package.json') }} @@ -33,12 +32,19 @@ jobs: ${{ runner.os }}-npm- - name: Install dependencies + shell: bash run: npm install - - name: Build - run: npm run build + - name: Test + uses: ./.github/actions/test + with: + version: "latest" + gist_token: ${{ secrets.GIST_TOKEN }} + gist_id: ${{ secrets.GIST_ID }} - name: Publish to NPM + if: ${{ github.repository_owner == 'kearisp' }} + shell: bash env: NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} run: npm publish --provenance @@ -51,23 +57,24 @@ jobs: needs: publish steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - - name: Set up Node.js - uses: actions/setup-node@v4 + - name: Setup Node.js + uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 registry-url: 'https://registry.npmjs.org' - name: Unpublish previous beta versions + shell: bash env: NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} run: | PACKAGE_NAME=$(npm pkg get name | sed -e 's/^"//' -e 's/"$//') PACKAGE_VERSION=$(npm pkg get version | sed -e 's/^"//' -e 's/"$//') - BETA_VERSIONS=$(npm view $PACKAGE_NAME versions --json | jq -r '.[]' | grep -E "$PACKAGE_VERSION-beta\.[0-9]+$") + VERSIONS=$(npm view $PACKAGE_NAME versions --json | jq -r '.[]') + BETA_VERSIONS=$(echo $VERSIONS | grep -E "$PACKAGE_VERSION-beta\.[0-9]+$" || echo "") for VERSION in $BETA_VERSIONS; do npm unpublish $PACKAGE_NAME@$VERSION --force 2>/dev/null || npm deprecate $PACKAGE_NAME@$VERSION "This is the beta version. Why can't it be deleted?" done - diff --git a/.github/workflows/unpublish-latest.yml b/.github/workflows/unpublish-latest.yml index 6f826f0..357ed8c 100644 --- a/.github/workflows/unpublish-latest.yml +++ b/.github/workflows/unpublish-latest.yml @@ -13,15 +13,16 @@ jobs: environment: publish steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v6 - - name: Set up Node.js - uses: actions/setup-node@v4 + - name: Setup Node.js + uses: actions/setup-node@v6 with: - node-version: 22 + node-version: 24 registry-url: 'https://registry.npmjs.org' - name: Delete package version + shell: bash env: NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} run: | diff --git a/package.json b/package.json index d6351cd..f3f15a4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kearisp/cli", - "version": "2.0.8", + "version": "2.0.9", "license": "MIT", "author": "Kris Papercut ", "description": "Command line interface for node.js", @@ -28,14 +28,9 @@ "test-watch:command": "jest --colors --watchAll --runTestsByPath ./src/makes/Command.spec.ts", "test-watch:parser": "jest --colors --watchAll --runTestsByPath ./src/makes/Parser.spec.ts" }, - "dependencies": { - "os": "^0.1.2", - "path": "^0.12.7" - }, "devDependencies": { "@types/jest": "^29.5.14", "@types/node": "^22.13.0", - "fs": "^0.0.1-security", "jest": "^29.7.0", "ts-jest": "^29.2.5", "ts-node": "^10.9.2", diff --git a/src/makes/Cli.spec.ts b/src/makes/Cli.spec.ts index d50d699..250f4ea 100644 --- a/src/makes/Cli.spec.ts +++ b/src/makes/Cli.spec.ts @@ -116,4 +116,24 @@ describe("Cli.run", () => { expect(res).toContain("--name"); expect(res).toContain("--option"); }); + + it("Should handle empty command with options", async (): Promise => { + const cli = new Cli(); + + cli.command("") + .option("version", { + alias: "v", + type: "boolean" + }) + .action((input) => { + if(input.option("version")) { + return "v1.0.0"; + } + + return "Some result"; + }); + + expect(await cli.run(["node", "cli"]).catch((err) => err)).toBe("Some result"); + expect(await cli.run(["node", "cli", "-v"]).catch((err) => err)).toBe("v1.0.0"); + }); }); diff --git a/src/makes/Command.ts b/src/makes/Command.ts index 7248daa..08dbf5f 100644 --- a/src/makes/Command.ts +++ b/src/makes/Command.ts @@ -128,16 +128,19 @@ export class Command { } public parse(parts: string[]): CommandInput { - const commands = this._command - ? this._command.split(/\s+/g) - : []; + const commands = [ + "command", + ...this._command + ? this._command.trim().split(/\s+/g) + : [] + ]; const args: { [name: string]: string | boolean | number | string[]; } = {}; const optionValues: OptionValue[] = []; - const parser = new Parser(parts); + const parser = new Parser(["command", ...parts]); for(let i = 0; i < commands.length; i++) { const command = commands[i];