UNPKG

11.2 kBJavaScriptView Raw
1#!/usr/bin/env node
2"use strict";
3Object.defineProperty(exports, "__esModule", { value: true });
4var _a;
5var path_1 = require("path");
6var repl_1 = require("repl");
7var util_1 = require("util");
8var Module = require("module");
9var arg = require("arg");
10var diff_1 = require("diff");
11var vm_1 = require("vm");
12var fs_1 = require("fs");
13var index_1 = require("./index");
14var args = arg({
15 // Node.js-like options.
16 '--eval': String,
17 '--print': Boolean,
18 '--require': [String],
19 // CLI options.
20 '--files': Boolean,
21 '--help': Boolean,
22 '--version': arg.COUNT,
23 // Project options.
24 '--compiler': String,
25 '--compiler-options': index_1.parse,
26 '--project': String,
27 '--ignore-diagnostics': [String],
28 '--ignore': [String],
29 '--transpile-only': Boolean,
30 '--type-check': Boolean,
31 '--pretty': Boolean,
32 '--skip-project': Boolean,
33 '--skip-ignore': Boolean,
34 // Aliases.
35 '-e': '--eval',
36 '-p': '--print',
37 '-r': '--require',
38 '-h': '--help',
39 '-v': '--version',
40 '-T': '--transpile-only',
41 '-I': '--ignore',
42 '-P': '--project',
43 '-C': '--compiler',
44 '-D': '--ignore-diagnostics',
45 '-O': '--compiler-options'
46}, {
47 stopAtPositional: true
48});
49var _b = args["--help"], help = _b === void 0 ? false : _b, _c = args["--version"], version = _c === void 0 ? 0 : _c, _d = args["--files"], files = _d === void 0 ? index_1.DEFAULTS.files : _d, _e = args["--compiler"], compiler = _e === void 0 ? index_1.DEFAULTS.compiler : _e, _f = args["--compiler-options"], compilerOptions = _f === void 0 ? index_1.DEFAULTS.compilerOptions : _f, _g = args["--project"], project = _g === void 0 ? index_1.DEFAULTS.project : _g, _h = args["--ignore-diagnostics"], ignoreDiagnostics = _h === void 0 ? index_1.DEFAULTS.ignoreDiagnostics : _h, _j = args["--ignore"], ignore = _j === void 0 ? index_1.DEFAULTS.ignore : _j, _k = args["--transpile-only"], transpileOnly = _k === void 0 ? index_1.DEFAULTS.transpileOnly : _k, _l = args["--type-check"], typeCheck = _l === void 0 ? index_1.DEFAULTS.typeCheck : _l, _m = args["--pretty"], pretty = _m === void 0 ? index_1.DEFAULTS.pretty : _m, _o = args["--skip-project"], skipProject = _o === void 0 ? index_1.DEFAULTS.skipProject : _o, _p = args["--skip-ignore"], skipIgnore = _p === void 0 ? index_1.DEFAULTS.skipIgnore : _p;
50if (help) {
51 console.log("\nUsage: ts-node [options] [ -e script | script.ts ] [arguments]\n\nOptions:\n\n -e, --eval [code] Evaluate code\n -p, --print Print result of `--eval`\n -r, --require [path] Require a node module before execution\n\n -h, --help Print CLI usage\n -v, --version Print module version information\n\n -T, --transpile-only Use TypeScript's faster `transpileModule`\n -I, --ignore [pattern] Override the path patterns to skip compilation\n -P, --project [path] Path to TypeScript JSON project file\n -C, --compiler [name] Specify a custom TypeScript compiler\n -D, --ignore-diagnostics [code] Ignore TypeScript warnings by diagnostic code\n -O, --compiler-options [opts] JSON object to merge with compiler options\n\n --files Load files from `tsconfig.json` on startup\n --pretty Use pretty diagnostic formatter\n --skip-project Skip reading `tsconfig.json`\n --skip-ignore Skip `--ignore` checks\n");
52 process.exit(0);
53}
54// Output project information.
55if (version === 1) {
56 console.log("v" + index_1.VERSION);
57 process.exit(0);
58}
59var cwd = process.cwd();
60var code = args['--eval'];
61var isPrinted = args['--print'] !== undefined;
62// Register the TypeScript compiler instance.
63var service = index_1.register({
64 files: files,
65 pretty: pretty,
66 typeCheck: typeCheck,
67 transpileOnly: transpileOnly,
68 ignore: ignore,
69 project: project,
70 skipIgnore: skipIgnore,
71 skipProject: skipProject,
72 compiler: compiler,
73 ignoreDiagnostics: ignoreDiagnostics,
74 compilerOptions: compilerOptions,
75 readFile: code ? readFileEval : undefined,
76 fileExists: code ? fileExistsEval : undefined
77});
78// Output project information.
79if (version >= 2) {
80 console.log("ts-node v" + index_1.VERSION);
81 console.log("node " + process.version);
82 console.log("compiler v" + service.ts.version);
83 process.exit(0);
84}
85// Require specified modules before start-up.
86if (args['--require'])
87 Module._preloadModules(args['--require']);
88/**
89 * Eval helpers.
90 */
91var EVAL_FILENAME = "[eval].ts";
92var EVAL_PATH = path_1.join(cwd, EVAL_FILENAME);
93var EVAL_INSTANCE = { input: '', output: '', version: 0, lines: 0 };
94// Prepend `ts-node` arguments to CLI for child processes.
95(_a = process.execArgv).unshift.apply(_a, [__filename].concat(process.argv.slice(2, process.argv.length - args._.length)));
96process.argv = [process.argv[1]].concat(args._.length ? path_1.resolve(cwd, args._[0]) : []).concat(args._.slice(1));
97// Execute the main contents (either eval, script or piped).
98if (code) {
99 evalAndExit(code, isPrinted);
100}
101else {
102 if (args._.length) {
103 Module.runMain();
104 }
105 else {
106 // Piping of execution _only_ occurs when no other script is specified.
107 if (process.stdin.isTTY) {
108 startRepl();
109 }
110 else {
111 var code_1 = '';
112 process.stdin.on('data', function (chunk) { return code_1 += chunk; });
113 process.stdin.on('end', function () { return evalAndExit(code_1, isPrinted); });
114 }
115 }
116}
117/**
118 * Evaluate a script.
119 */
120function evalAndExit(code, isPrinted) {
121 var module = new Module(EVAL_FILENAME);
122 module.filename = EVAL_FILENAME;
123 module.paths = Module._nodeModulePaths(cwd);
124 global.__filename = EVAL_FILENAME;
125 global.__dirname = cwd;
126 global.exports = module.exports;
127 global.module = module;
128 global.require = module.require.bind(module);
129 var result;
130 try {
131 result = _eval(code);
132 }
133 catch (error) {
134 if (error instanceof index_1.TSError) {
135 console.error(error.diagnosticText);
136 process.exit(1);
137 }
138 throw error;
139 }
140 if (isPrinted) {
141 console.log(typeof result === 'string' ? result : util_1.inspect(result));
142 }
143}
144/**
145 * Evaluate the code snippet.
146 */
147function _eval(input) {
148 var lines = EVAL_INSTANCE.lines;
149 var isCompletion = !/\n$/.test(input);
150 var undo = appendEval(input);
151 var output;
152 try {
153 output = service.compile(EVAL_INSTANCE.input, EVAL_PATH, -lines);
154 }
155 catch (err) {
156 undo();
157 throw err;
158 }
159 // Use `diff` to check for new JavaScript to execute.
160 var changes = diff_1.diffLines(EVAL_INSTANCE.output, output);
161 if (isCompletion) {
162 undo();
163 }
164 else {
165 EVAL_INSTANCE.output = output;
166 }
167 return changes.reduce(function (result, change) {
168 return change.added ? exec(change.value, EVAL_FILENAME) : result;
169 }, undefined);
170}
171/**
172 * Execute some code.
173 */
174function exec(code, filename) {
175 var script = new vm_1.Script(code, { filename: filename });
176 return script.runInThisContext();
177}
178/**
179 * Start a CLI REPL.
180 */
181function startRepl() {
182 var repl = repl_1.start({
183 prompt: '> ',
184 input: process.stdin,
185 output: process.stdout,
186 terminal: process.stdout.isTTY,
187 eval: replEval,
188 useGlobal: true
189 });
190 // Bookmark the point where we should reset the REPL state.
191 var resetEval = appendEval('');
192 function reset() {
193 resetEval();
194 // Hard fix for TypeScript forcing `Object.defineProperty(exports, ...)`.
195 exec('exports = module.exports', EVAL_FILENAME);
196 }
197 reset();
198 repl.on('reset', reset);
199 repl.defineCommand('type', {
200 help: 'Check the type of a TypeScript identifier',
201 action: function (identifier) {
202 if (!identifier) {
203 repl.displayPrompt();
204 return;
205 }
206 var undo = appendEval(identifier);
207 var _a = service.getTypeInfo(EVAL_INSTANCE.input, EVAL_PATH, EVAL_INSTANCE.input.length), name = _a.name, comment = _a.comment;
208 undo();
209 repl.outputStream.write(name + "\n" + (comment ? comment + "\n" : ''));
210 repl.displayPrompt();
211 }
212 });
213}
214/**
215 * Eval code from the REPL.
216 */
217function replEval(code, _context, _filename, callback) {
218 var err = null;
219 var result;
220 // TODO: Figure out how to handle completion here.
221 if (code === '.scope') {
222 callback(err);
223 return;
224 }
225 try {
226 result = _eval(code);
227 }
228 catch (error) {
229 if (error instanceof index_1.TSError) {
230 // Support recoverable compilations using >= node 6.
231 if (repl_1.Recoverable && isRecoverable(error)) {
232 err = new repl_1.Recoverable(error);
233 }
234 else {
235 console.error(error.diagnosticText);
236 }
237 }
238 else {
239 err = error;
240 }
241 }
242 callback(err, result);
243}
244/**
245 * Append to the eval instance and return an undo function.
246 */
247function appendEval(input) {
248 var undoInput = EVAL_INSTANCE.input;
249 var undoVersion = EVAL_INSTANCE.version;
250 var undoOutput = EVAL_INSTANCE.output;
251 var undoLines = EVAL_INSTANCE.lines;
252 // Handle ASI issues with TypeScript re-evaluation.
253 if (undoInput.charAt(undoInput.length - 1) === '\n' && /^\s*[\[\(\`]/.test(input) && !/;\s*$/.test(undoInput)) {
254 EVAL_INSTANCE.input = EVAL_INSTANCE.input.slice(0, -1) + ";\n";
255 }
256 EVAL_INSTANCE.input += input;
257 EVAL_INSTANCE.lines += lineCount(input);
258 EVAL_INSTANCE.version++;
259 return function () {
260 EVAL_INSTANCE.input = undoInput;
261 EVAL_INSTANCE.output = undoOutput;
262 EVAL_INSTANCE.version = undoVersion;
263 EVAL_INSTANCE.lines = undoLines;
264 };
265}
266/**
267 * Count the number of lines.
268 */
269function lineCount(value) {
270 var count = 0;
271 for (var _i = 0, value_1 = value; _i < value_1.length; _i++) {
272 var char = value_1[_i];
273 if (char === '\n') {
274 count++;
275 }
276 }
277 return count;
278}
279/**
280 * Get the file text, checking for eval first.
281 */
282function readFileEval(path) {
283 if (path === EVAL_PATH)
284 return EVAL_INSTANCE.input;
285 try {
286 return fs_1.readFileSync(path, 'utf8');
287 }
288 catch (err) { /* Ignore. */ }
289}
290/**
291 * Get whether the file exists.
292 */
293function fileExistsEval(path) {
294 if (path === EVAL_PATH)
295 return true;
296 try {
297 var stats = fs_1.statSync(path);
298 return stats.isFile() || stats.isFIFO();
299 }
300 catch (err) {
301 return false;
302 }
303}
304var RECOVERY_CODES = new Set([
305 1003,
306 1005,
307 1109,
308 1126,
309 1160,
310 1161,
311 2355 // "A function whose declared type is neither 'void' nor 'any' must return a value."
312]);
313/**
314 * Check if a function can recover gracefully.
315 */
316function isRecoverable(error) {
317 return error.diagnosticCodes.every(function (code) { return RECOVERY_CODES.has(code); });
318}
319//# sourceMappingURL=bin.js.map
\No newline at end of file