From e868c91c7899fb8d1b253b46e6e284f26a973711 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Mon, 9 Dec 2024 21:20:32 +0800 Subject: [PATCH 1/4] feat: support cjs and esm both by tshy BREAKING CHANGE: drop Node.js < 14.0.0 support part of https://github.com/eggjs/egg/issues/3644 --- .eslintcache | 1 + .eslintrc | 5 +- .github/workflows/codeql.yml | 39 ------ .github/workflows/nodejs-14.yml | 22 ++++ .github/workflows/nodejs.yml | 3 +- .gitignore | 2 + README.md | 19 +-- index.d.ts | 26 ---- package.json | 69 +++++++--- index.js => src/index.ts | 124 +++++++++++++----- ... => child-process-with-unclosed-stdio.cjs} | 6 +- test/fixtures/ts/check.ts | 19 --- test/fixtures/ts/checkExtraOptions.ts | 19 --- test/fixtures/ts/tsconfig.json | 8 -- test/helper.ts | 9 ++ test/index.d.ts.test.js | 45 ------- test/{runscript.test.js => runscript.test.ts} | 66 +++++----- tsconfig.json | 10 ++ 18 files changed, 226 insertions(+), 266 deletions(-) create mode 100644 .eslintcache delete mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/nodejs-14.yml delete mode 100644 index.d.ts rename index.js => src/index.ts (54%) rename test/fixtures/{child-process-with-unclosed-stdio.js => child-process-with-unclosed-stdio.cjs} (86%) delete mode 100644 test/fixtures/ts/check.ts delete mode 100644 test/fixtures/ts/checkExtraOptions.ts delete mode 100644 test/fixtures/ts/tsconfig.json create mode 100644 test/helper.ts delete mode 100644 test/index.d.ts.test.js rename test/{runscript.test.js => runscript.test.ts} (72%) create mode 100644 tsconfig.json diff --git a/.eslintcache b/.eslintcache new file mode 100644 index 0000000..c4568fb --- /dev/null +++ b/.eslintcache @@ -0,0 +1 @@ +[{"/Users/fengmk2/git/github.com/node-modules/runscript/src/index.ts":"1","/Users/fengmk2/git/github.com/node-modules/runscript/test/runscript.test.ts":"2","/Users/fengmk2/git/github.com/node-modules/runscript/test/helper.ts":"3"},{"size":5849,"mtime":1733749261946,"results":"4","hashOfConfig":"5"},{"size":6845,"mtime":1733750267254,"results":"6","hashOfConfig":"5"},{"size":272,"mtime":1733749690101,"results":"7","hashOfConfig":"5"},{"filePath":"8","messages":"9","suppressedMessages":"10","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1l9emcs",{"filePath":"11","messages":"12","suppressedMessages":"13","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"14","messages":"15","suppressedMessages":"16","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/fengmk2/git/github.com/node-modules/runscript/src/index.ts",[],[],"/Users/fengmk2/git/github.com/node-modules/runscript/test/runscript.test.ts",[],[],"/Users/fengmk2/git/github.com/node-modules/runscript/test/helper.ts",[],[]] \ No newline at end of file diff --git a/.eslintrc b/.eslintrc index c799fe5..9bcdb46 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,3 +1,6 @@ { - "extends": "eslint-config-egg" + "extends": [ + "eslint-config-egg/typescript", + "eslint-config-egg/lib/rules/enforce-node-prefix" + ] } diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 028b997..0000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: "CodeQL" - -on: - push: - branches: [ "master" ] - pull_request: - branches: [ "master" ] - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ javascript ] - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - queries: +security-and-quality - - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{ matrix.language }}" diff --git a/.github/workflows/nodejs-14.yml b/.github/workflows/nodejs-14.yml new file mode 100644 index 0000000..256a58f --- /dev/null +++ b/.github/workflows/nodejs-14.yml @@ -0,0 +1,22 @@ +name: Node.js 14 CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js + uses: irby/setup-node-nvm@master + with: + node-version: '16.x' + - run: npm install + - run: npm run prepublishOnly + - run: node -v + - run: . /home/runner/mynvm/nvm.sh && nvm install 14 && nvm use 14 && node -v && npm run test:node14 diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index da8d197..d3bc12d 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -3,7 +3,6 @@ name: CI on: push: branches: [ master ] - pull_request: branches: [ master ] @@ -13,4 +12,4 @@ jobs: uses: node-modules/github-actions/.github/workflows/node-test.yml@master with: os: 'ubuntu-latest, macos-latest, windows-latest' - version: '8, 10, 12, 14, 16, 18, 20' + version: '16, 18, 20, 22' diff --git a/.gitignore b/.gitignore index c6897ad..5bc5989 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,5 @@ coverage/ test/fixtures/ts/**/*.js .DS_Store package-lock.json +.tshy +dist diff --git a/README.md b/README.md index 9f1828d..97e384f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -runscript -======= +# runscript 📢📢📢📢📢 You should use [execa](https://github.com/sindresorhus/execa) instead. 📢📢📢📢 @@ -22,13 +21,13 @@ Run script easy! ## Installation ```bash -$ npm install runscript +npm install runscript ``` ## Quick start ```js -const runScript = require('runscript'); +const { runScript } = require('runscript'); runScript('node -v', { stdio: 'pipe' }) .then(stdio => { @@ -44,7 +43,7 @@ runScript('node -v', { stdio: 'pipe' }) Run user script for a maximum of 10 seconds. ```js -const runScript = require('runscript'); +const { runScript } = require('runscript'); runScript('node user-script.js', { stdio: 'pipe' }, { timeout: 10000 }) .then(stdio => { @@ -59,14 +58,8 @@ runScript('node user-script.js', { stdio: 'pipe' }, { timeout: 10000 }) [MIT](LICENSE.txt) - - ## Contributors -|[
fengmk2](https://github.com/fengmk2)
|[
lusyn](https://github.com/lusyn)
|[
walkthunder](https://github.com/walkthunder)
|[
popomore](https://github.com/popomore)
|[
ottomao](https://github.com/ottomao)
|[
atian25](https://github.com/atian25)
| -| :---: | :---: | :---: | :---: | :---: | :---: | -[
akitaSummer](https://github.com/akitaSummer)
|[
lgtm-com[bot]](https://github.com/apps/lgtm-com)
|[
semantic-release-bot](https://github.com/semantic-release-bot)
|[
whxaxes](https://github.com/whxaxes)
- -This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Thu Jan 11 2024 16:25:27 GMT+0800`. +[![Contributors](https://contrib.rocks/image?repo=node-modules/runscript)](https://github.com/node-modules/runscript/graphs/contributors) - +Made with [contributors-img](https://contrib.rocks). diff --git a/index.d.ts b/index.d.ts deleted file mode 100644 index 0204245..0000000 --- a/index.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { SpawnOptions } from 'child_process'; -import { Writable } from 'stream'; - -declare namespace RunScript { - export interface Options extends SpawnOptions { - stdout?: Writable; - stderr?: Writable; - } - - export interface ExtraOptions { - timeout?: number; - } - - export interface Stdio { - stdout: Buffer | null; - stderr: Buffer | null; - } - - export interface StdError extends Error { - stdio: Stdio; - } -} - -declare function RunScript(cmd: string, opts?: RunScript.Options, extraOpts?: RunScript.ExtraOptions): Promise; - -export = RunScript; diff --git a/package.json b/package.json index 0c77bf7..ca8e632 100644 --- a/package.json +++ b/package.json @@ -2,35 +2,35 @@ "name": "runscript", "version": "1.6.0", "description": "Run script easy!", - "main": "index.js", - "files": [ - "index.js", - "index.d.ts" - ], "scripts": { - "test": "npm run lint && egg-bin test", - "test-cov": "egg-bin cov", - "lint": "eslint index.js test --fix", - "ci": "npm run lint && npm run test-cov", - "contributor": "git-contributor" + "lint": "eslint --cache src test --ext .ts", + "pretest": "npm run prepublishOnly", + "test": "npm run lint -- --fix && egg-bin test", + "test:node14": "egg-bin test", + "preci": "npm run prepublishOnly", + "ci": "npm run lint && egg-bin cov && attw --pack", + "prepublishOnly": "tshy && tshy-after" }, "dependencies": { - "is-type-of": "^1.1.0" + "is-type-of": "^2.2.0" }, "devDependencies": { - "@types/node": "^12.0.8", + "@arethetypeswrong/cli": "^0.15.3", + "@eggjs/tsconfig": "1", + "@types/mocha": "10", + "@types/node": "22", "autod": "^3.1.2", - "egg-bin": "^1.11.1", - "eslint": "^4.19.1", - "eslint-config-egg": "^6.0.0", - "git-contributor": "^2.1.5", - "typescript": "^3.9.3" + "egg-bin": "6", + "eslint": "8", + "eslint-config-egg": "14", + "tshy": "2", + "tshy-after": "1", + "typescript": "5" }, "homepage": "https://github.com/node-modules/runscript", "repository": { "type": "git", - "url": "git://github.com/node-modules/runscript.git", - "web": "https://github.com/node-modules/runscript" + "url": "git://github.com/node-modules/runscript.git" }, "bugs": { "url": "https://github.com/node-modules/runscript/issues" @@ -41,8 +41,35 @@ "npm run" ], "engines": { - "node": ">=4.2.3" + "node": ">=16.0.0" }, "author": "fengmk2 (https://github.com/fengmk2)", - "license": "MIT" + "license": "MIT", + "type": "module", + "tshy": { + "exports": { + ".": "./src/index.ts", + "./package.json": "./package.json" + } + }, + "exports": { + ".": { + "import": { + "types": "./dist/esm/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/commonjs/index.d.ts", + "default": "./dist/commonjs/index.js" + } + }, + "./package.json": "./package.json" + }, + "files": [ + "dist", + "src" + ], + "types": "./dist/commonjs/index.d.ts", + "main": "./dist/commonjs/index.js", + "module": "./dist/esm/index.js" } diff --git a/index.js b/src/index.ts similarity index 54% rename from index.js rename to src/index.ts index 014e2f8..c7bc0cc 100644 --- a/index.js +++ b/src/index.ts @@ -1,25 +1,69 @@ -'use strict'; +import { debuglog } from 'node:util'; +import assert from 'node:assert'; +import path from 'node:path'; +import { spawn, spawnSync, type SpawnOptions } from 'node:child_process'; +import { type Writable } from 'node:stream'; +import { isWritable } from 'is-type-of'; -const debug = require('util').debuglog('runscript'); -const is = require('is-type-of'); -const assert = require('assert'); -const path = require('path'); -const spawn = require('child_process').spawn; -const spawnSync = require('child_process').spawnSync; +const debug = debuglog('runscript'); function isCmd() { if (process.platform !== 'win32') { - return false + return false; } try { - const result = spawnSync(`ls`, { + const result = spawnSync('ls', { stdio: 'pipe', - }) + }); - return result.error !== undefined + return result.error !== undefined; } catch (err) { - return true + return true; + } +} + +export interface Options extends SpawnOptions { + stdout?: Writable; + stderr?: Writable; +} + +export interface ExtraOptions { + timeout?: number; +} + +export interface Stdio { + stdout: Buffer | null; + stderr: Buffer | null; +} + +export interface StdError extends Error { + stdio: Stdio; +} + +export class RunScriptError extends Error { + stdio: Stdio; + exitcode: number | null; + + constructor(message: string, stdio: Stdio, exitcode: number | null, options?: ErrorOptions) { + super(message, options); + this.name = this.constructor.name; + this.stdio = stdio; + this.exitcode = exitcode; + Error.captureStackTrace(this, this.constructor); + } +} + +export class RunScriptTimeoutError extends Error { + stdio: Stdio; + timeout: number; + + constructor(message: string, stdio: Stdio, timeout: number, options?: ErrorOptions) { + super(message, options); + this.name = this.constructor.name; + this.stdio = stdio; + this.timeout = timeout; + Error.captureStackTrace(this, this.constructor); } } @@ -33,15 +77,21 @@ function isCmd() { * - {Number} [extraOptions.timeout] - child process running timeout * @return {Object} stdio object, will contains stdio.stdout and stdio.stderr buffer. */ -module.exports = function runScript(script, options, extraOptions) { +export function runScript(script: string, options: Options = {}, extraOptions: ExtraOptions = {}): Promise { return new Promise((resolve, reject) => { - extraOptions = extraOptions || {}; - options = options || {}; options.env = options.env || Object.assign({}, process.env); options.cwd = options.cwd || process.cwd(); + if (typeof options.cwd === 'object') { + // convert URL object to string + options.cwd = String(options.cwd); + } options.stdio = options.stdio || 'inherit'; - if (options.stdout) assert(is.writableStream(options.stdout), 'options.stdout should be writable stream'); - if (options.stderr) assert(is.writableStream(options.stderr), 'options.stderr should be writable stream'); + if (options.stdout) { + assert(isWritable(options.stdout), 'options.stdout should be writable stream'); + } + if (options.stderr) { + assert(isWritable(options.stderr), 'options.stderr should be writable stream'); + } let sh = 'sh'; let shFlag = '-c'; @@ -61,13 +111,13 @@ module.exports = function runScript(script, options, extraOptions) { debug('%s %s %s, %j, %j', sh, shFlag, script, options, extraOptions); const proc = spawn(sh, [ shFlag, script ], options); - const stdout = []; - const stderr = []; + const stdout: Buffer[] = []; + const stderr: Buffer[] = []; let isEnd = false; - let timeoutTimer; + let timeoutTimer: NodeJS.Timeout; if (proc.stdout) { - proc.stdout.on('data', buf => { + proc.stdout.on('data', (buf: Buffer) => { debug('stdout %d bytes', buf.length); stdout.push(buf); }); @@ -76,7 +126,7 @@ module.exports = function runScript(script, options, extraOptions) { } } if (proc.stderr) { - proc.stderr.on('data', buf => { + proc.stderr.on('data', (buf: Buffer) => { debug('stderr %d bytes', buf.length); stderr.push(buf); }); @@ -87,7 +137,9 @@ module.exports = function runScript(script, options, extraOptions) { proc.on('error', err => { debug('proc emit error: %s', err); - if (isEnd) return; + if (isEnd) { + return; + } isEnd = true; clearTimeout(timeoutTimer); @@ -96,11 +148,13 @@ module.exports = function runScript(script, options, extraOptions) { proc.on('exit', code => { debug('proc emit exit: %s', code); - if (isEnd) return; + if (isEnd) { + return; + } isEnd = true; clearTimeout(timeoutTimer); - const stdio = { + const stdio: Stdio = { stdout: null, stderr: null, }; @@ -111,10 +165,8 @@ module.exports = function runScript(script, options, extraOptions) { stdio.stderr = Buffer.concat(stderr); } if (code !== 0) { - const err = new Error(`Run "${sh} ${shFlag} ${script}" error, exit code ${code}`); - err.name = 'RunScriptError'; - err.stdio = stdio; - err.exitcode = code; + const err = new RunScriptError( + `Run "${sh} ${shFlag} ${script}" error, exit code ${code}`, stdio, code); return reject(err); } return resolve(stdio); @@ -125,16 +177,15 @@ module.exports = function runScript(script, options, extraOptions) { }); if (typeof extraOptions.timeout === 'number' && extraOptions.timeout > 0) { + const timeout = extraOptions.timeout; // start timer timeoutTimer = setTimeout(() => { - debug('proc run timeout: %dms', extraOptions.timeout); + debug('proc run timeout: %dms', timeout); isEnd = true; debug('kill child process %s', proc.pid); proc.kill(); - const err = new Error(`Run "${sh} ${shFlag} ${script}" timeout in ${extraOptions.timeout}ms`); - err.name = 'RunScriptTimeoutError'; - const stdio = { + const stdio: Stdio = { stdout: null, stderr: null, }; @@ -144,9 +195,10 @@ module.exports = function runScript(script, options, extraOptions) { if (stderr.length > 0) { stdio.stderr = Buffer.concat(stderr); } - err.stdio = stdio; + const err = new RunScriptTimeoutError( + `Run "${sh} ${shFlag} ${script}" timeout in ${extraOptions.timeout}ms`, stdio, timeout); return reject(err); - }, extraOptions.timeout); + }, timeout); } }); -}; +} diff --git a/test/fixtures/child-process-with-unclosed-stdio.js b/test/fixtures/child-process-with-unclosed-stdio.cjs similarity index 86% rename from test/fixtures/child-process-with-unclosed-stdio.js rename to test/fixtures/child-process-with-unclosed-stdio.cjs index 2dd9beb..2e61ec0 100644 --- a/test/fixtures/child-process-with-unclosed-stdio.js +++ b/test/fixtures/child-process-with-unclosed-stdio.cjs @@ -1,12 +1,10 @@ -'use strict'; - const path = require('path'); -const runScript = require('../../'); +const { runScript } = require('../../'); const argv = process.argv.slice(2); (async () => { if (argv[0] === undefined) { - runScript(`node ${path.join(__dirname, './child-process-with-unclosed-stdio.js')} child`); + runScript(`node ${path.join(__dirname, './child-process-with-unclosed-stdio.cjs')} child`); await new Promise(resolve => { setTimeout(resolve, 1000); }); diff --git a/test/fixtures/ts/check.ts b/test/fixtures/ts/check.ts deleted file mode 100644 index 607dbca..0000000 --- a/test/fixtures/ts/check.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as runscript from '../../../'; -import assert = require('assert'); - -runscript('node -v', { stdio: 'pipe' }) - .then(result => { - assert(!result.stderr); - assert(!!result.stdout!.toString()); - console.info(result.stdout!.toString()); - - return runscript('node -h', { - stdio: 'pipe', - stdout: process.stdout, - stderr: process.stderr, - }); - }) - .catch((err: runscript.StdError) => { - assert(err.stdio); - throw new Error('should not throw'); - }); diff --git a/test/fixtures/ts/checkExtraOptions.ts b/test/fixtures/ts/checkExtraOptions.ts deleted file mode 100644 index f7d6412..0000000 --- a/test/fixtures/ts/checkExtraOptions.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as runscript from '../../../'; -import assert = require('assert'); - -runscript('node -v', { stdio: 'pipe' }, { timeout: 30000 }) - .then(result => { - assert(!result.stderr); - assert(!!result.stdout!.toString()); - console.info(result.stdout!.toString()); - - return runscript('node -h', { - stdio: 'pipe', - stdout: process.stdout, - stderr: process.stderr, - }, {}); - }) - .catch((err: runscript.StdError) => { - assert(err.stdio); - throw new Error('should not throw'); - }); diff --git a/test/fixtures/ts/tsconfig.json b/test/fixtures/ts/tsconfig.json deleted file mode 100644 index 5db5b0c..0000000 --- a/test/fixtures/ts/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "target": "es2017", - "module": "commonjs", - "moduleResolution": "node" - } -} \ No newline at end of file diff --git a/test/helper.ts b/test/helper.ts new file mode 100644 index 0000000..6c5c063 --- /dev/null +++ b/test/helper.ts @@ -0,0 +1,9 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export function getFixtures(filename: string) { + return path.join(__dirname, 'fixtures', filename); +} diff --git a/test/index.d.ts.test.js b/test/index.d.ts.test.js deleted file mode 100644 index f7e2a11..0000000 --- a/test/index.d.ts.test.js +++ /dev/null @@ -1,45 +0,0 @@ -'use strict'; - -const path = require('path'); -const assert = require('assert'); -const runScript = require('..'); - -describe('index.d.ts.test.js', () => { - before(async () => { - try { - const stdio = await runScript('tsc -p ./ts/tsconfig.json', { - stdio: 'pipe', - cwd: path.join(__dirname, 'fixtures'), - debug: true, - }); - assert(!stdio.stderr); - } catch (err) { - console.error('should not throw error:', err.stdio.stdout.toString()); - throw err; - } - }); - - it('should compile ts without error', async () => { - const stdio = await runScript('node ./ts/check.js', { - stdio: 'pipe', - cwd: path.join(__dirname, 'fixtures'), - }); - assert(!stdio.stderr); - const stdout = stdio.stdout.toString(); - assert(stdout); - assert(stdout.match(/v\d+\.\d+\.\d+/)); - assert(stdout.match(/Options:/)); - }); - - it('should tsd support ExtraOptions', async () => { - const stdio = await runScript('node ./ts/checkExtraOptions.js', { - stdio: 'pipe', - cwd: path.join(__dirname, 'fixtures'), - }); - assert(!stdio.stderr); - const stdout = stdio.stdout.toString(); - assert(stdout); - assert(stdout.match(/v\d+\.\d+\.\d+/)); - assert(stdout.match(/Options:/)); - }); -}); diff --git a/test/runscript.test.js b/test/runscript.test.ts similarity index 72% rename from test/runscript.test.js rename to test/runscript.test.ts index 6fe663d..a4c8e39 100644 --- a/test/runscript.test.js +++ b/test/runscript.test.ts @@ -1,11 +1,9 @@ -'use strict'; +import fs from 'node:fs'; +import { strict as assert } from 'node:assert'; +import { runScript, RunScriptTimeoutError } from '../src/index.js'; +import { getFixtures } from './helper.js'; -const fs = require('fs'); -const path = require('path'); -const assert = require('assert'); -const runScript = require('..'); - -describe('runscript.test.js', () => { +describe('test/runscript.test.ts', () => { it('should run `$ node -v`', () => { return runScript('node -v'); }); @@ -49,33 +47,35 @@ describe('runscript.test.js', () => { }); it('should reject on timeout (stdout)', () => { - return runScript(`node ${path.join(__dirname, 'fixtures/timeout.js')}`, { + return runScript(`node ${getFixtures('timeout.js')}`, { stdio: 'pipe', }, { timeout: 1200 }) - .catch(err => { - console.log(err); - assert(err.name === 'RunScriptTimeoutError'); - assert(err.stdio.stdout.toString() === 'timer start\necho every 500ms\necho every 500ms\n'); + .catch((err: unknown) => { + // console.log(err); + assert(err instanceof RunScriptTimeoutError); + assert.equal(err.name, 'RunScriptTimeoutError'); + assert.equal(err.timeout, 1200); + assert.match(err.stdio.stdout!.toString(), /timer start\necho every 500ms\n/); }); }); it('should reject on timeout (stderr)', () => { - return runScript(`node ${path.join(__dirname, 'fixtures/timeout-stderr.js')}`, { + return runScript(`node ${getFixtures('timeout-stderr.js')}`, { stdio: 'pipe', }, { timeout: 1500 }) .catch(err => { console.log(err); assert(err.name === 'RunScriptTimeoutError'); - assert(err.stdio.stderr.toString() === 'timer start\necho every 600ms\necho every 600ms\n'); + assert.equal(err.stdio.stderr.toString(), 'timer start\necho every 600ms\necho every 600ms\n'); }); }); it('should normal exit before timeout', () => { - return runScript(`node ${path.join(__dirname, 'fixtures/timeout-and-exit.js')}`, { + return runScript(`node ${getFixtures('timeout-and-exit.js')}`, { stdio: 'pipe', - }, { timeout: 1800 }) + }, { timeout: 2000 }) .then(stdio => { - assert(stdio.stderr.toString() === 'timer start\necho every 600ms\necho every 600ms\nexit\n'); + assert.equal(stdio.stderr!.toString(), 'timer start\necho every 600ms\necho every 600ms\nexit\n'); }); }); @@ -83,7 +83,7 @@ describe('runscript.test.js', () => { return runScript('node -v', { stdio: 'pipe', }).then(stdio => { - console.log(stdio.stdout.toString()); + console.log(stdio.stdout!.toString()); assert(Buffer.isBuffer(stdio.stdout)); assert(/^v\d+\.\d+\.\d+$/.test(stdio.stdout.toString().trim()), JSON.stringify(stdio.stdout.toString())); assert.equal(stdio.stderr, null); @@ -115,15 +115,15 @@ describe('runscript.test.js', () => { }); it('should pipe and send to stdout and stderr stream', () => { - const stdoutPath = path.join(__dirname, 'stdout.log'); - const stderrPath = path.join(__dirname, 'stderr.log'); - return runScript(`node ${path.join(__dirname, 'fixtures/console.js')}`, { + const stdoutPath = getFixtures('stdout.log'); + const stderrPath = getFixtures('stderr.log'); + return runScript(`node ${getFixtures('console.js')}`, { stdio: 'pipe', stdout: fs.createWriteStream(stdoutPath), stderr: fs.createWriteStream(stderrPath), }).then(stdio => { - assert(stdio.stdout.toString() === 'stdout'); - assert(stdio.stderr.toString() === 'stderr'); + assert(stdio.stdout!.toString() === 'stdout'); + assert(stdio.stderr!.toString() === 'stderr'); assert(fs.readFileSync(stdoutPath, 'utf8') === 'stdout'); assert(fs.readFileSync(stderrPath, 'utf8') === 'stderr'); }); @@ -131,7 +131,7 @@ describe('runscript.test.js', () => { it('should throw when options.stdout is not writable stream', () => { return runScript('node -v', { - stdout: fs.createReadStream(__filename), + stdout: fs.createReadStream(getFixtures('console.js')) as any, }).then(() => { throw new Error('should not run'); }).catch(err => { @@ -141,7 +141,7 @@ describe('runscript.test.js', () => { it('should throw when options.stderr is not writable stream', () => { return runScript('node -v', { - stderr: fs.createReadStream(__filename), + stderr: fs.createReadStream(getFixtures('console.js')) as any, }).then(() => { throw new Error('should not run'); }).catch(err => { @@ -154,7 +154,7 @@ describe('runscript.test.js', () => { stdio: 'pipe', }).then(stdio => { // console.log(stdio.stdout.toString()); - assert(/^\d+\.\d+\.\d+$/.test(stdio.stdout.toString().trim())); + assert(/^\d+\.\d+\.\d+$/.test(stdio.stdout!.toString().trim())); assert.equal(stdio.stderr, null); }); }); @@ -162,19 +162,19 @@ describe('runscript.test.js', () => { it('should run relative path ../../node_modules/.bin/autod', () => { return runScript('../../node_modules/.bin/autod -V', { stdio: 'pipe', - cwd: path.join(__dirname, 'fixtures'), + cwd: getFixtures(''), }).then(stdio => { // console.log(stdio.stdout.toString()); - assert(/^\d+\.\d+\.\d+$/.test(stdio.stdout.toString().trim())); + assert(/^\d+\.\d+\.\d+$/.test(stdio.stdout!.toString().trim())); assert.equal(stdio.stderr, null); }); }); it('should exit when child process has not closed stdio streams', () => { - return runScript(`node ${path.join(__dirname, 'fixtures/child-process-with-unclosed-stdio.js')}`, { + return runScript(`node ${getFixtures('child-process-with-unclosed-stdio.cjs')}`, { stdio: 'pipe', }).then(stdio => { - assert(/child finish/.test(stdio.stdout.toString().trim())); + assert(/child finish/.test(stdio.stdout!.toString().trim())); }); }); @@ -184,7 +184,7 @@ describe('runscript.test.js', () => { stdio: 'pipe', }).then(stdio => { // console.log(stdio.stdout.toString()); - assert(/^\d+\.\d+\.\d+$/.test(stdio.stdout.toString().trim())); + assert(/^\d+\.\d+\.\d+$/.test(stdio.stdout!.toString().trim())); assert.equal(stdio.stderr, null); }); }); @@ -192,10 +192,10 @@ describe('runscript.test.js', () => { it('should run relative path ..\\..\\node_modules\\.bin\\autod', () => { return runScript('..\\..\\node_modules\\.bin\\autod -V', { stdio: 'pipe', - cwd: path.join(__dirname, 'fixtures'), + cwd: getFixtures(''), }).then(stdio => { // console.log(stdio.stdout.toString()); - assert(/^\d+\.\d+\.\d+$/.test(stdio.stdout.toString().trim())); + assert(/^\d+\.\d+\.\d+$/.test(stdio.stdout!.toString().trim())); assert.equal(stdio.stderr, null); }); }); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..ff41b73 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@eggjs/tsconfig", + "compilerOptions": { + "strict": true, + "noImplicitAny": true, + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext" + } +} From 4907d7757ccdeb5699ed27224e326ba2becc6c95 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Mon, 9 Dec 2024 21:24:56 +0800 Subject: [PATCH 2/4] f --- .eslintcache | 1 - test/runscript.test.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 .eslintcache diff --git a/.eslintcache b/.eslintcache deleted file mode 100644 index c4568fb..0000000 --- a/.eslintcache +++ /dev/null @@ -1 +0,0 @@ -[{"/Users/fengmk2/git/github.com/node-modules/runscript/src/index.ts":"1","/Users/fengmk2/git/github.com/node-modules/runscript/test/runscript.test.ts":"2","/Users/fengmk2/git/github.com/node-modules/runscript/test/helper.ts":"3"},{"size":5849,"mtime":1733749261946,"results":"4","hashOfConfig":"5"},{"size":6845,"mtime":1733750267254,"results":"6","hashOfConfig":"5"},{"size":272,"mtime":1733749690101,"results":"7","hashOfConfig":"5"},{"filePath":"8","messages":"9","suppressedMessages":"10","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1l9emcs",{"filePath":"11","messages":"12","suppressedMessages":"13","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"14","messages":"15","suppressedMessages":"16","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/fengmk2/git/github.com/node-modules/runscript/src/index.ts",[],[],"/Users/fengmk2/git/github.com/node-modules/runscript/test/runscript.test.ts",[],[],"/Users/fengmk2/git/github.com/node-modules/runscript/test/helper.ts",[],[]] \ No newline at end of file diff --git a/test/runscript.test.ts b/test/runscript.test.ts index a4c8e39..4ebbefe 100644 --- a/test/runscript.test.ts +++ b/test/runscript.test.ts @@ -62,7 +62,7 @@ describe('test/runscript.test.ts', () => { it('should reject on timeout (stderr)', () => { return runScript(`node ${getFixtures('timeout-stderr.js')}`, { stdio: 'pipe', - }, { timeout: 1500 }) + }, { timeout: 1700 }) .catch(err => { console.log(err); assert(err.name === 'RunScriptTimeoutError'); From 6065a6153ea23b4d976571423efc6306aa5edb2f Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Mon, 9 Dec 2024 21:25:20 +0800 Subject: [PATCH 3/4] f --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 5bc5989..bca8ad1 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ test/fixtures/ts/**/*.js package-lock.json .tshy dist +.eslintcache From 1e47b96449ac9306954b490b2b9362cbf6c6e7b8 Mon Sep 17 00:00:00 2001 From: fengmk2 Date: Mon, 9 Dec 2024 21:29:46 +0800 Subject: [PATCH 4/4] f --- test/runscript.test.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/runscript.test.ts b/test/runscript.test.ts index 4ebbefe..c4d3dea 100644 --- a/test/runscript.test.ts +++ b/test/runscript.test.ts @@ -63,19 +63,22 @@ describe('test/runscript.test.ts', () => { return runScript(`node ${getFixtures('timeout-stderr.js')}`, { stdio: 'pipe', }, { timeout: 1700 }) - .catch(err => { - console.log(err); - assert(err.name === 'RunScriptTimeoutError'); - assert.equal(err.stdio.stderr.toString(), 'timer start\necho every 600ms\necho every 600ms\n'); + .catch((err: unknown) => { + // console.log(err); + assert(err instanceof RunScriptTimeoutError); + assert.equal(err.name, 'RunScriptTimeoutError'); + assert.equal(err.timeout, 1700); + assert.match(err.stdio.stderr!.toString(), /timer start\necho every 600ms\n/); }); }); it('should normal exit before timeout', () => { return runScript(`node ${getFixtures('timeout-and-exit.js')}`, { stdio: 'pipe', - }, { timeout: 2000 }) + }, { timeout: 30000 }) .then(stdio => { - assert.equal(stdio.stderr!.toString(), 'timer start\necho every 600ms\necho every 600ms\nexit\n'); + assert.match(stdio.stderr!.toString(), /timer start\necho every 600ms\n/); + assert.match(stdio.stderr!.toString(), /\nexit\n/); }); });