diff --git a/.eslintrc.json b/.eslintrc.json index 9bf34f8..52d6d00 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -13,6 +13,7 @@ }, "rules": { "no-console": "error", + "n/no-process-exit": "off", "n/shebang": [ "error", { diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6fa26eb..dc6c4a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,15 +14,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4.1.1 - name: Setup Node - uses: actions/setup-node@v3.6.0 + uses: actions/setup-node@v4.0.1 with: - node-version: '20.10.0' + node-version: '20.11.0' - name: Install Dependencies run: npm ci - name: Save error log - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4.2.0 if: ${{ failure() }} with: name: npm-debug-log-${{ hashFiles('package-lock.json') }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 8fc9233..a620496 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -10,15 +10,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v4.1.1 - name: Setup Node - uses: actions/setup-node@v3.6.0 + uses: actions/setup-node@v4.0.1 with: - node-version: '20.10.0' + node-version: '20.11.0' - name: Install Dependencies run: npm ci - name: Save error log - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4.2.0 if: ${{ failure() }} with: name: npm-debug-log-${{ hashFiles('package-lock.json') }} @@ -30,7 +30,7 @@ jobs: - name: Pack run: npm pack - name: Push to NPM registry - uses: JS-DevTools/npm-publish@v2.1.0 + uses: JS-DevTools/npm-publish@v3.0.1 with: token: ${{ secrets.NPM_AUTH_TOKEN }} tag: ${{ contains(github.ref, '-') && 'next' || 'latest' }} diff --git a/babel.config.json b/babel.config.json deleted file mode 100644 index 576abc1..0000000 --- a/babel.config.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "targets": "node >= 16.19", - "presets": [ - ["@babel/preset-env", { - "modules": false - }] - ] -} diff --git a/package-lock.json b/package-lock.json index 36f70fc..f57b5f4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@knighted/duel", - "version": "1.0.5", + "version": "1.0.6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@knighted/duel", - "version": "1.0.5", + "version": "1.0.6", "license": "MIT", "dependencies": { "@knighted/specifier": "^1.0.1", diff --git a/package.json b/package.json index ae19b67..6e5df9e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@knighted/duel", - "version": "1.0.5", + "version": "1.0.6", "description": "TypeScript dual packages.", "type": "module", "main": "dist", diff --git a/src/duel.js b/src/duel.js index 8135c22..7347d8c 100755 --- a/src/duel.js +++ b/src/duel.js @@ -30,19 +30,26 @@ const runBuild = (project, outDir) => { reject(new Error(`Failed to compile: ${err.message}`)) }) - build.on('close', code => { - if (code === null) { - return reject(new Error('Failed to compile.')) - } - + build.on('exit', code => { if (code > 0) { - return reject(new Error('Compilation errors found.')) + return reject(new Error(code)) } resolve(code) }) }) } +const handleErrorAndExit = message => { + const exitCode = Number(message) + + if (isNaN(exitCode)) { + logError(message) + process.exit(1) + } else { + logError('Compilation errors found.') + process.exit(exitCode) + } +} const duel = async args => { const ctx = await init(args) @@ -175,7 +182,7 @@ const duel = async args => { ]) success = true } catch ({ message }) { - logError(message) + handleErrorAndExit(message) } if (success) { @@ -202,7 +209,7 @@ const duel = async args => { await runPrimaryBuild() success = true } catch ({ message }) { - logError(message) + handleErrorAndExit(message) } if (success) { @@ -213,6 +220,7 @@ const duel = async args => { ) const tsconfigDual = getOverrideTsConfig() const pkgRename = 'package.json.bak' + let errorMsg = '' /** * Create a new package.json with updated `type` field. @@ -236,14 +244,18 @@ const duel = async args => { await runBuild(dualConfigPath, absoluteDualOutDir) } catch ({ message }) { success = false - logError(message) + errorMsg = message + } finally { + // Cleanup and restore + await rm(dualConfigPath, { force: true }) + await rm(pkg.path, { force: true }) + await rename(join(pkgDir, pkgRename), pkg.path) + + if (errorMsg) { + handleErrorAndExit(errorMsg) + } } - // Cleanup and restore - await rm(dualConfigPath, { force: true }) - await rm(pkg.path, { force: true }) - await rename(join(pkgDir, pkgRename), pkg.path) - if (success) { const filenames = await glob(`${absoluteDualOutDir}/**/*{.js,.d.ts}`, { ignore: 'node_modules/**', diff --git a/test/integration.js b/test/integration.js index ce183b1..ba7eb10 100644 --- a/test/integration.js +++ b/test/integration.js @@ -216,11 +216,22 @@ describe('duel', () => { it('reports compilation errors during a build', async t => { const spy = t.mock.method(global.console, 'log') + const spyExit = t.mock.method(process, 'exit') t.after(async () => { await rmDist(errDist) }) - await duel(['-p', 'test/__fixtures__/compileErrors/tsconfig.json']) + spyExit.mock.mockImplementation(number => { + throw new Error(`Mocked process.exit: ${number}`) + }) + await assert.rejects( + async () => { + await duel(['-p', 'test/__fixtures__/compileErrors/tsconfig.json']) + }, + { message: /Mocked process\.exit/ }, + ) + + assert.ok(spyExit.mock.calls[0].arguments > 0) assert.equal(spy.mock.calls[1].arguments[1], 'Compilation errors found.') })