Skip to content

Commit d9f310e

Browse files
authored
Replace minimist with type-safe arg (#759)
1 parent f148008 commit d9f310e

File tree

6 files changed

+110
-106
lines changed

6 files changed

+110
-106
lines changed

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ ts-node
3434
ts-node -e 'console.log("Hello, world!")'
3535

3636
# Execute, and print, code with TypeScript.
37-
ts-node -p '"Hello, world!"'
37+
ts-node -p -e '"Hello, world!"'
3838

3939
# Pipe scripts to execute with TypeScript.
4040
echo "console.log('Hello, world!')" | ts-node
@@ -123,13 +123,13 @@ Supports `--print`, `--eval` and `--require` from [node.js CLI options](https://
123123

124124
_Environment variable denoted in parentheses._
125125

126-
* `-T, --transpileOnly` Use TypeScript's faster `transpileModule` (`TS_NODE_TRANSPILE_ONLY`, default: `false`)
126+
* `-T, --transpile-only` Use TypeScript's faster `transpileModule` (`TS_NODE_TRANSPILE_ONLY`, default: `false`)
127127
* `--cacheDirectory` Configure the output file cache directory (`TS_NODE_CACHE_DIRECTORY`)
128128
* `-I, --ignore [pattern]` Override the path patterns to skip compilation (`TS_NODE_IGNORE`, default: `/node_modules/`)
129129
* `-P, --project [path]` Path to TypeScript JSON project file (`TS_NODE_PROJECT`)
130130
* `-C, --compiler [name]` Specify a custom TypeScript compiler (`TS_NODE_COMPILER`, default: `typescript`)
131-
* `-D, --ignoreDiagnostics [code]` Ignore TypeScript warnings by diagnostic code (`TS_NODE_IGNORE_DIAGNOSTICS`)
132-
* `-O, --compilerOptions [opts]` JSON object to merge with compiler options (`TS_NODE_COMPILER_OPTIONS`)
131+
* `-D, --ignore-diagnostics [code]` Ignore TypeScript warnings by diagnostic code (`TS_NODE_IGNORE_DIAGNOSTICS`)
132+
* `-O, --compiler-options [opts]` JSON object to merge with compiler options (`TS_NODE_COMPILER_OPTIONS`)
133133
* `--files` Load files from `tsconfig.json` on startup (`TS_NODE_FILES`, default: `false`)
134134
* `--pretty` Use pretty diagnostic formatter (`TS_NODE_PRETTY`, default: `false`)
135135
* `--no-cache` Disable the local TypeScript Node cache (`TS_NODE_CACHE`, default: `true`)

package-lock.json

+6-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"@types/semver": "^5.3.34",
6060
"@types/source-map-support": "^0.4.0",
6161
"@types/yn": "types/npm-yn#ca75f6c82940fae6a06fb41d2d37a6aa9b4ea8e9",
62+
"arg": "^4.1.0",
6263
"chai": "^4.0.1",
6364
"istanbul": "^0.4.0",
6465
"mocha": "^5.0.1",
@@ -78,7 +79,6 @@
7879
"arrify": "^1.0.0",
7980
"diff": "^3.1.0",
8081
"make-error": "^1.1.1",
81-
"minimist": "^1.2.0",
8282
"source-map-support": "^0.5.6",
8383
"yn": "^2.0.0"
8484
}

src/bin.ts

+85-83
Original file line numberDiff line numberDiff line change
@@ -3,79 +3,76 @@
33
import { join, resolve } from 'path'
44
import { start, Recoverable } from 'repl'
55
import { inspect } from 'util'
6-
import arrify = require('arrify')
76
import Module = require('module')
8-
import minimist = require('minimist')
7+
import arg = require('arg')
98
import { diffLines } from 'diff'
109
import { Script } from 'vm'
1110
import { readFileSync, statSync } from 'fs'
1211
import { register, VERSION, DEFAULTS, TSError, parse } from './index'
1312

14-
interface Argv {
13+
const args = arg({
1514
// Node.js-like options.
16-
eval?: string
17-
print?: string
18-
require?: string | string[]
19-
// CLI options.
20-
help?: boolean
21-
version?: boolean
22-
// Register options.
23-
pretty?: boolean
24-
typeCheck?: boolean
25-
transpileOnly?: boolean
26-
files?: boolean
27-
compiler?: string
28-
ignore?: string | string[]
29-
project?: string
30-
skipIgnore?: boolean
31-
skipProject?: boolean
32-
ignoreDiagnostics?: string | string[]
33-
compilerOptions?: string
34-
_: string[]
35-
}
15+
'--eval': String,
16+
'--print': Boolean,
17+
'--require': [String],
3618

37-
const argv = minimist<Argv>(process.argv.slice(2), {
38-
stopEarly: true,
39-
string: ['eval', 'print', 'compiler', 'project', 'ignoreDiagnostics', 'require', 'ignore'],
40-
boolean: ['help', 'transpileOnly', 'typeCheck', 'version', 'files', 'pretty', 'skipProject', 'skipIgnore'],
41-
alias: {
42-
eval: ['e'],
43-
print: ['p'],
44-
require: ['r'],
45-
help: ['h'],
46-
version: ['v'],
47-
typeCheck: ['type-check'],
48-
transpileOnly: ['T', 'transpile-only'],
49-
ignore: ['I'],
50-
project: ['P'],
51-
skipIgnore: ['skip-ignore'],
52-
skipProject: ['skip-project'],
53-
compiler: ['C'],
54-
ignoreDiagnostics: ['D', 'ignore-diagnostics'],
55-
compilerOptions: ['O', 'compiler-options']
56-
},
57-
default: {
58-
files: DEFAULTS.files,
59-
pretty: DEFAULTS.pretty,
60-
typeCheck: DEFAULTS.typeCheck,
61-
transpileOnly: DEFAULTS.transpileOnly,
62-
ignore: DEFAULTS.ignore,
63-
project: DEFAULTS.project,
64-
skipIgnore: DEFAULTS.skipIgnore,
65-
skipProject: DEFAULTS.skipProject,
66-
compiler: DEFAULTS.compiler,
67-
ignoreDiagnostics: DEFAULTS.ignoreDiagnostics
68-
}
19+
// CLI options.
20+
'--files': Boolean,
21+
'--help': Boolean,
22+
'--version': arg.COUNT,
23+
24+
// Project options.
25+
'--compiler': String,
26+
'--compiler-options': parse,
27+
'--project': String,
28+
'--ignore-diagnostics': [String],
29+
'--ignore': [String],
30+
'--transpile-only': Boolean,
31+
'--type-check': Boolean,
32+
'--pretty': Boolean,
33+
'--skip-project': Boolean,
34+
'--skip-ignore': Boolean,
35+
36+
// Aliases.
37+
'-e': '--eval',
38+
'-p': '--print',
39+
'-r': '--require',
40+
'-h': '--help',
41+
'-v': '--version',
42+
'-T': '--transpile-only',
43+
'-I': '--ignore',
44+
'-P': '--project',
45+
'-C': '--compiler',
46+
'-D': '--ignore-diagnostics',
47+
'-O': '--compiler-options'
48+
}, {
49+
stopAtPositional: true
6950
})
7051

71-
if (argv.help) {
52+
const {
53+
'--help': help = false,
54+
'--version': version = 0,
55+
'--files': files = DEFAULTS.files,
56+
'--compiler': compiler = DEFAULTS.compiler,
57+
'--compiler-options': compilerOptions = DEFAULTS.compilerOptions,
58+
'--project': project = DEFAULTS.project,
59+
'--ignore-diagnostics': ignoreDiagnostics = DEFAULTS.ignoreDiagnostics,
60+
'--ignore': ignore = DEFAULTS.ignore,
61+
'--transpile-only': transpileOnly = DEFAULTS.transpileOnly,
62+
'--type-check': typeCheck = DEFAULTS.typeCheck,
63+
'--pretty': pretty = DEFAULTS.pretty,
64+
'--skip-project': skipProject = DEFAULTS.skipProject,
65+
'--skip-ignore': skipIgnore = DEFAULTS.skipIgnore
66+
} = args
67+
68+
if (help) {
7269
console.log(`
7370
Usage: ts-node [options] [ -e script | script.ts ] [arguments]
7471
7572
Options:
7673
7774
-e, --eval [code] Evaluate code
78-
-p, --print [code] Evaluate code and print result
75+
-p, --print Print result of \`--eval\`
7976
-r, --require [path] Require a node module before execution
8077
8178
-h, --help Print CLI usage
@@ -85,8 +82,8 @@ Options:
8582
-I, --ignore [pattern] Override the path patterns to skip compilation
8683
-P, --project [path] Path to TypeScript JSON project file
8784
-C, --compiler [name] Specify a custom TypeScript compiler
88-
-D, --ignoreDiagnostics [code] Ignore TypeScript warnings by diagnostic code
89-
-O, --compilerOptions [opts] JSON object to merge with compiler options
85+
-D, --ignore-diagnostics [code] Ignore TypeScript warnings by diagnostic code
86+
-O, --compiler-options [opts] JSON object to merge with compiler options
9087
9188
--files Load files from \`tsconfig.json\` on startup
9289
--pretty Use pretty diagnostic formatter
@@ -97,38 +94,43 @@ Options:
9794
process.exit(0)
9895
}
9996

97+
// Output project information.
98+
if (version === 1) {
99+
console.log(`v${VERSION}`)
100+
process.exit(0)
101+
}
102+
100103
const cwd = process.cwd()
101-
const code = argv.eval === undefined ? argv.print : argv.eval
102-
const isEval = typeof argv.eval === 'string' || !!argv.print // Minimist struggles with empty strings.
103-
const isPrinted = argv.print !== undefined
104+
const code = args['--eval']
105+
const isPrinted = args['--print'] !== undefined
104106

105107
// Register the TypeScript compiler instance.
106108
const service = register({
107-
files: argv.files,
108-
pretty: argv.pretty,
109-
typeCheck: argv.typeCheck,
110-
transpileOnly: argv.transpileOnly,
111-
ignore: argv.ignore,
112-
project: argv.project,
113-
skipIgnore: argv.skipIgnore,
114-
skipProject: argv.skipProject,
115-
compiler: argv.compiler,
116-
ignoreDiagnostics: argv.ignoreDiagnostics,
117-
compilerOptions: parse(argv.compilerOptions) || DEFAULTS.compilerOptions,
118-
readFile: isEval ? readFileEval : undefined,
119-
fileExists: isEval ? fileExistsEval : undefined
109+
files,
110+
pretty,
111+
typeCheck,
112+
transpileOnly,
113+
ignore,
114+
project,
115+
skipIgnore,
116+
skipProject,
117+
compiler,
118+
ignoreDiagnostics,
119+
compilerOptions,
120+
readFile: code ? readFileEval : undefined,
121+
fileExists: code ? fileExistsEval : undefined
120122
})
121123

122124
// Output project information.
123-
if (argv.version) {
125+
if (version >= 2) {
124126
console.log(`ts-node v${VERSION}`)
125127
console.log(`node ${process.version}`)
126-
console.log(`typescript v${service.ts.version}`)
128+
console.log(`compiler v${service.ts.version}`)
127129
process.exit(0)
128130
}
129131

130132
// Require specified modules before start-up.
131-
(Module as any)._preloadModules(arrify(argv.require))
133+
if (args['--require']) (Module as any)._preloadModules(args['--require'])
132134

133135
/**
134136
* Eval helpers.
@@ -138,16 +140,16 @@ const EVAL_PATH = join(cwd, EVAL_FILENAME)
138140
const EVAL_INSTANCE = { input: '', output: '', version: 0, lines: 0 }
139141

140142
// Execute the main contents (either eval, script or piped).
141-
if (isEval) {
142-
evalAndExit(code as string, isPrinted)
143+
if (code) {
144+
evalAndExit(code, isPrinted)
143145
} else {
144-
if (argv._.length) {
145-
process.argv = ['node'].concat(resolve(cwd, argv._[0])).concat(argv._.slice(1))
146+
if (args._.length) {
147+
process.argv = ['node'].concat(resolve(cwd, args._[0])).concat(args._.slice(1))
146148
process.execArgv.unshift(__filename)
147149
Module.runMain()
148150
} else {
149151
// Piping of execution _only_ occurs when no other script is specified.
150-
if ((process.stdin as any).isTTY) {
152+
if (process.stdin.isTTY) {
151153
startRepl()
152154
} else {
153155
let code = ''

src/index.spec.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ describe('ts-node', function () {
5353
})
5454

5555
it('should print scripts', function (done) {
56-
exec(`${BIN_EXEC} -p "import { example } from './tests/complex/index';example()"`, function (err, stdout) {
56+
exec(`${BIN_EXEC} -pe "import { example } from './tests/complex/index';example()"`, function (err, stdout) {
5757
expect(err).to.equal(null)
5858
expect(stdout).to.equal('example\n')
5959

@@ -67,7 +67,7 @@ describe('ts-node', function () {
6767
[
6868
BIN_EXEC,
6969
'-O "{\\\"allowJs\\\":true}"',
70-
'-p "import { main } from \'./tests/allow-js/run\';main()"'
70+
'-pe "import { main } from \'./tests/allow-js/run\';main()"'
7171
].join(' '),
7272
function (err, stdout) {
7373
expect(err).to.equal(null)
@@ -83,7 +83,7 @@ describe('ts-node', function () {
8383
[
8484
BIN_EXEC,
8585
'-O "{\\\"allowJs\\\":true}"',
86-
'-p "import { Foo2 } from \'./tests/allow-js/with-jsx\'; Foo2.sayHi()"'
86+
'-pe "import { Foo2 } from \'./tests/allow-js/with-jsx\'; Foo2.sayHi()"'
8787
].join(' '),
8888
function (err, stdout) {
8989
expect(err).to.equal(null)
@@ -133,7 +133,7 @@ describe('ts-node', function () {
133133

134134
it('should be able to ignore diagnostic', function (done) {
135135
exec(
136-
`${BIN_EXEC} --ignoreDiagnostics 2345 -e "import * as m from './tests/module';console.log(m.example(123))"`,
136+
`${BIN_EXEC} --ignore-diagnostics 2345 -e "import * as m from './tests/module';console.log(m.example(123))"`,
137137
function (err) {
138138
if (err === null) {
139139
return done('Command was expected to fail, but it succeeded.')
@@ -166,7 +166,7 @@ describe('ts-node', function () {
166166
})
167167

168168
it.skip('eval should work with source maps', function (done) {
169-
exec(`${BIN_EXEC} -p "import './tests/throw'"`, function (err) {
169+
exec(`${BIN_EXEC} -pe "import './tests/throw'"`, function (err) {
170170
if (err === null) {
171171
return done('Command was expected to fail, but it succeeded.')
172172
}
@@ -182,7 +182,7 @@ describe('ts-node', function () {
182182
})
183183

184184
it('should support transpile only mode', function (done) {
185-
exec(`${BIN_EXEC} --transpileOnly -p "x"`, function (err) {
185+
exec(`${BIN_EXEC} --transpile-only -pe "x"`, function (err) {
186186
if (err === null) {
187187
return done('Command was expected to fail, but it succeeded.')
188188
}
@@ -216,7 +216,7 @@ describe('ts-node', function () {
216216
})
217217

218218
it('should pipe into an eval script', function (done) {
219-
const cp = exec(`${BIN_EXEC} --fast -p 'process.stdin.isTTY'`, function (err, stdout) {
219+
const cp = exec(`${BIN_EXEC} --transpile-only -pe 'process.stdin.isTTY'`, function (err, stdout) {
220220
expect(err).to.equal(null)
221221
expect(stdout).to.equal('undefined\n')
222222

@@ -227,7 +227,7 @@ describe('ts-node', function () {
227227
})
228228

229229
it('should support require flags', function (done) {
230-
exec(`${BIN_EXEC} -r ./tests/hello-world -p "console.log('success')"`, function (err, stdout) {
230+
exec(`${BIN_EXEC} -r ./tests/hello-world -pe "console.log('success')"`, function (err, stdout) {
231231
expect(err).to.equal(null)
232232
expect(stdout).to.equal('Hello, world!\nsuccess\nundefined\n')
233233

src/index.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,12 @@ export interface Options {
6262
transpileOnly?: boolean | null
6363
files?: boolean | null
6464
compiler?: string
65-
ignore?: string | string[]
65+
ignore?: string[]
6666
project?: string
6767
skipIgnore?: boolean | null
6868
skipProject?: boolean | null
6969
compilerOptions?: object
70-
ignoreDiagnostics?: number | string | Array<number | string>
70+
ignoreDiagnostics?: Array<number | string>
7171
readFile?: (path: string) => string | undefined
7272
fileExists?: (path: string) => boolean
7373
transformers?: _ts.CustomTransformers
@@ -176,11 +176,12 @@ export function register (opts: Options = {}): Register {
176176
const options = Object.assign({}, DEFAULTS, opts)
177177
const originalJsHandler = require.extensions['.js']
178178

179-
const ignoreDiagnostics = arrify(options.ignoreDiagnostics).concat([
179+
const ignoreDiagnostics = [
180180
6059, // "'rootDir' is expected to contain all source files."
181181
18002, // "The 'files' list in config file is empty."
182-
18003 // "No inputs were found in config file."
183-
]).map(Number)
182+
18003, // "No inputs were found in config file."
183+
...(options.ignoreDiagnostics || [])
184+
].map(Number)
184185

185186
const memoryCache: MemoryCache = {
186187
contents: Object.create(null),

0 commit comments

Comments
 (0)