bin.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #!/usr/bin/env node
  2. "use strict";
  3. Object.defineProperty(exports, "__esModule", { value: true });
  4. exports.main = void 0;
  5. const path_1 = require("path");
  6. const util_1 = require("util");
  7. const Module = require("module");
  8. const arg = require("arg");
  9. const repl_1 = require("./repl");
  10. const index_1 = require("./index");
  11. /**
  12. * Main `bin` functionality.
  13. */
  14. function main(argv = process.argv.slice(2), entrypointArgs = {}) {
  15. const args = Object.assign(Object.assign({}, entrypointArgs), arg({
  16. // Node.js-like options.
  17. '--eval': String,
  18. '--interactive': Boolean,
  19. '--print': Boolean,
  20. '--require': [String],
  21. // CLI options.
  22. '--help': Boolean,
  23. '--script-mode': Boolean,
  24. '--version': arg.COUNT,
  25. // Project options.
  26. '--dir': String,
  27. '--files': Boolean,
  28. '--compiler': String,
  29. '--compiler-options': index_1.parse,
  30. '--project': String,
  31. '--ignore-diagnostics': [String],
  32. '--ignore': [String],
  33. '--transpile-only': Boolean,
  34. '--type-check': Boolean,
  35. '--compiler-host': Boolean,
  36. '--pretty': Boolean,
  37. '--skip-project': Boolean,
  38. '--skip-ignore': Boolean,
  39. '--prefer-ts-exts': Boolean,
  40. '--log-error': Boolean,
  41. '--emit': Boolean,
  42. // Aliases.
  43. '-e': '--eval',
  44. '-i': '--interactive',
  45. '-p': '--print',
  46. '-r': '--require',
  47. '-h': '--help',
  48. '-s': '--script-mode',
  49. '-v': '--version',
  50. '-T': '--transpile-only',
  51. '-H': '--compiler-host',
  52. '-I': '--ignore',
  53. '-P': '--project',
  54. '-C': '--compiler',
  55. '-D': '--ignore-diagnostics',
  56. '-O': '--compiler-options'
  57. }, {
  58. argv,
  59. stopAtPositional: true
  60. }));
  61. // Only setting defaults for CLI-specific flags
  62. // Anything passed to `register()` can be `undefined`; `create()` will apply
  63. // defaults.
  64. const { '--dir': dir, '--help': help = false, '--script-mode': scriptMode = false, '--version': version = 0, '--require': argsRequire = [], '--eval': code = undefined, '--print': print = false, '--interactive': interactive = false, '--files': files, '--compiler': compiler, '--compiler-options': compilerOptions, '--project': project, '--ignore-diagnostics': ignoreDiagnostics, '--ignore': ignore, '--transpile-only': transpileOnly, '--type-check': typeCheck, '--compiler-host': compilerHost, '--pretty': pretty, '--skip-project': skipProject, '--skip-ignore': skipIgnore, '--prefer-ts-exts': preferTsExts, '--log-error': logError, '--emit': emit } = args;
  65. if (help) {
  66. console.log(`
  67. Usage: ts-node [options] [ -e script | script.ts ] [arguments]
  68. Options:
  69. -e, --eval [code] Evaluate code
  70. -p, --print Print result of \`--eval\`
  71. -r, --require [path] Require a node module before execution
  72. -i, --interactive Opens the REPL even if stdin does not appear to be a terminal
  73. -h, --help Print CLI usage
  74. -v, --version Print module version information
  75. -s, --script-mode Use cwd from <script.ts> instead of current directory
  76. -T, --transpile-only Use TypeScript's faster \`transpileModule\`
  77. -H, --compiler-host Use TypeScript's compiler host API
  78. -I, --ignore [pattern] Override the path patterns to skip compilation
  79. -P, --project [path] Path to TypeScript JSON project file
  80. -C, --compiler [name] Specify a custom TypeScript compiler
  81. -D, --ignore-diagnostics [code] Ignore TypeScript warnings by diagnostic code
  82. -O, --compiler-options [opts] JSON object to merge with compiler options
  83. --dir Specify working directory for config resolution
  84. --scope Scope compiler to files within \`cwd\` only
  85. --files Load \`files\`, \`include\` and \`exclude\` from \`tsconfig.json\` on startup
  86. --pretty Use pretty diagnostic formatter (usually enabled by default)
  87. --skip-project Skip reading \`tsconfig.json\`
  88. --skip-ignore Skip \`--ignore\` checks
  89. --prefer-ts-exts Prefer importing TypeScript files over JavaScript files
  90. --log-error Logs TypeScript errors to stderr instead of throwing exceptions
  91. `);
  92. process.exit(0);
  93. }
  94. // Output project information.
  95. if (version === 1) {
  96. console.log(`v${index_1.VERSION}`);
  97. process.exit(0);
  98. }
  99. const cwd = dir || process.cwd();
  100. /** Unresolved. May point to a symlink, not realpath. May be missing file extension */
  101. const scriptPath = args._.length ? path_1.resolve(cwd, args._[0]) : undefined;
  102. const state = new repl_1.EvalState(scriptPath || path_1.join(cwd, repl_1.EVAL_FILENAME));
  103. const replService = repl_1.createRepl({ state });
  104. const { evalAwarePartialHost } = replService;
  105. // Register the TypeScript compiler instance.
  106. const service = index_1.register({
  107. dir: getCwd(dir, scriptMode, scriptPath),
  108. emit,
  109. files,
  110. pretty,
  111. transpileOnly,
  112. typeCheck,
  113. compilerHost,
  114. ignore,
  115. preferTsExts,
  116. logError,
  117. project,
  118. skipProject,
  119. skipIgnore,
  120. compiler,
  121. ignoreDiagnostics,
  122. compilerOptions,
  123. require: argsRequire,
  124. readFile: code !== undefined ? evalAwarePartialHost.readFile : undefined,
  125. fileExists: code !== undefined ? evalAwarePartialHost.fileExists : undefined
  126. });
  127. // Bind REPL service to ts-node compiler service (chicken-and-egg problem)
  128. replService.setService(service);
  129. // Output project information.
  130. if (version >= 2) {
  131. console.log(`ts-node v${index_1.VERSION}`);
  132. console.log(`node ${process.version}`);
  133. console.log(`compiler v${service.ts.version}`);
  134. process.exit(0);
  135. }
  136. // Create a local module instance based on `cwd`.
  137. const module = new Module(state.path);
  138. module.filename = state.path;
  139. module.paths = Module._nodeModulePaths(cwd);
  140. // Prepend `ts-node` arguments to CLI for child processes.
  141. process.execArgv.unshift(__filename, ...process.argv.slice(2, process.argv.length - args._.length));
  142. process.argv = [process.argv[1]].concat(scriptPath || []).concat(args._.slice(1));
  143. // Execute the main contents (either eval, script or piped).
  144. if (code !== undefined && !interactive) {
  145. evalAndExit(replService, module, code, print);
  146. }
  147. else {
  148. if (args._.length) {
  149. Module.runMain();
  150. }
  151. else {
  152. // Piping of execution _only_ occurs when no other script is specified.
  153. // --interactive flag forces REPL
  154. if (interactive || process.stdin.isTTY) {
  155. replService.start(code);
  156. }
  157. else {
  158. let buffer = code || '';
  159. process.stdin.on('data', (chunk) => buffer += chunk);
  160. process.stdin.on('end', () => evalAndExit(replService, module, buffer, print));
  161. }
  162. }
  163. }
  164. }
  165. exports.main = main;
  166. /**
  167. * Get project path from args.
  168. */
  169. function getCwd(dir, scriptMode, scriptPath) {
  170. // Validate `--script-mode` usage is correct.
  171. if (scriptMode) {
  172. if (!scriptPath) {
  173. throw new TypeError('Script mode must be used with a script name, e.g. `ts-node -s <script.ts>`');
  174. }
  175. if (dir) {
  176. throw new TypeError('Script mode cannot be combined with `--dir`');
  177. }
  178. // Use node's own resolution behavior to ensure we follow symlinks.
  179. // scriptPath may omit file extension or point to a directory with or without package.json.
  180. // This happens before we are registered, so we tell node's resolver to consider ts, tsx, and jsx files.
  181. // In extremely rare cases, is is technically possible to resolve the wrong directory,
  182. // because we do not yet know preferTsExts, jsx, nor allowJs.
  183. // See also, justification why this will not happen in real-world situations:
  184. // https://github.com/TypeStrong/ts-node/pull/1009#issuecomment-613017081
  185. const exts = ['.js', '.jsx', '.ts', '.tsx'];
  186. const extsTemporarilyInstalled = [];
  187. for (const ext of exts) {
  188. if (!hasOwnProperty(require.extensions, ext)) { // tslint:disable-line
  189. extsTemporarilyInstalled.push(ext);
  190. require.extensions[ext] = function () { }; // tslint:disable-line
  191. }
  192. }
  193. try {
  194. return path_1.dirname(require.resolve(scriptPath));
  195. }
  196. finally {
  197. for (const ext of extsTemporarilyInstalled) {
  198. delete require.extensions[ext]; // tslint:disable-line
  199. }
  200. }
  201. }
  202. return dir;
  203. }
  204. /**
  205. * Evaluate a script.
  206. */
  207. function evalAndExit(replService, module, code, isPrinted) {
  208. let result;
  209. global.__filename = module.filename;
  210. global.__dirname = path_1.dirname(module.filename);
  211. global.exports = module.exports;
  212. global.module = module;
  213. global.require = module.require.bind(module);
  214. try {
  215. result = replService.evalCode(code);
  216. }
  217. catch (error) {
  218. if (error instanceof index_1.TSError) {
  219. console.error(error);
  220. process.exit(1);
  221. }
  222. throw error;
  223. }
  224. if (isPrinted) {
  225. console.log(typeof result === 'string' ? result : util_1.inspect(result));
  226. }
  227. }
  228. /** Safe `hasOwnProperty` */
  229. function hasOwnProperty(object, property) {
  230. return Object.prototype.hasOwnProperty.call(object, property);
  231. }
  232. if (require.main === module) {
  233. main();
  234. }
  235. //# sourceMappingURL=bin.js.map