UNPKG

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