Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Socket
Sign inDemoInstall

ts-node

Package Overview
Dependencies
Maintainers
2
Versions
128
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ts-node - npm Package Compare versions

Comparing version 8.3.0 to 8.10.2

dist-raw/node-esm-resolve-implementation.js

5

dist/bin.d.ts
#!/usr/bin/env node
export {};
/**
* Main `bin` functionality.
*/
export declare function main(argv: string[]): void;

521

dist/bin.js

@@ -12,153 +12,251 @@ #!/usr/bin/env node

const fs_1 = require("fs");
const os_1 = require("os");
const index_1 = require("./index");
const args = arg({
// Node.js-like options.
'--eval': String,
'--print': Boolean,
'--require': [String],
// CLI options.
'--files': Boolean,
'--help': Boolean,
'--version': arg.COUNT,
// Project options.
'--compiler': String,
'--compiler-options': index_1.parse,
'--project': String,
'--ignore-diagnostics': [String],
'--ignore': [String],
'--transpile-only': Boolean,
'--type-check': Boolean,
'--pretty': Boolean,
'--skip-project': Boolean,
'--skip-ignore': Boolean,
'--prefer-ts-exts': Boolean,
'--log-error': Boolean,
// Aliases.
'-e': '--eval',
'-p': '--print',
'-r': '--require',
'-h': '--help',
'-v': '--version',
'-T': '--transpile-only',
'-I': '--ignore',
'-P': '--project',
'-C': '--compiler',
'-D': '--ignore-diagnostics',
'-O': '--compiler-options'
}, {
stopAtPositional: true
});
const { '--help': help = false, '--version': version = 0, '--files': files = index_1.DEFAULTS.files, '--compiler': compiler = index_1.DEFAULTS.compiler, '--compiler-options': compilerOptions = index_1.DEFAULTS.compilerOptions, '--project': project = index_1.DEFAULTS.project, '--ignore-diagnostics': ignoreDiagnostics = index_1.DEFAULTS.ignoreDiagnostics, '--ignore': ignore = index_1.DEFAULTS.ignore, '--transpile-only': transpileOnly = index_1.DEFAULTS.transpileOnly, '--type-check': typeCheck = index_1.DEFAULTS.typeCheck, '--pretty': pretty = index_1.DEFAULTS.pretty, '--skip-project': skipProject = index_1.DEFAULTS.skipProject, '--skip-ignore': skipIgnore = index_1.DEFAULTS.skipIgnore, '--prefer-ts-exts': preferTsExts = index_1.DEFAULTS.preferTsExts, '--log-error': logError = index_1.DEFAULTS.logError } = args;
if (help) {
console.log(`
Usage: ts-node [options] [ -e script | script.ts ] [arguments]
/**
* Eval filename for REPL/debug.
*/
const EVAL_FILENAME = `[eval].ts`;
/**
* Eval state management.
*/
class EvalState {
constructor(path) {
this.path = path;
this.input = '';
this.output = '';
this.version = 0;
this.lines = 0;
}
}
/**
* Main `bin` functionality.
*/
function main(argv) {
const args = arg({
// Node.js-like options.
'--eval': String,
'--interactive': Boolean,
'--print': Boolean,
'--require': [String],
// CLI options.
'--help': Boolean,
'--script-mode': Boolean,
'--version': arg.COUNT,
// Project options.
'--dir': String,
'--files': Boolean,
'--compiler': String,
'--compiler-options': index_1.parse,
'--project': String,
'--ignore-diagnostics': [String],
'--ignore': [String],
'--transpile-only': Boolean,
'--type-check': Boolean,
'--compiler-host': Boolean,
'--pretty': Boolean,
'--skip-project': Boolean,
'--skip-ignore': Boolean,
'--prefer-ts-exts': Boolean,
'--log-error': Boolean,
'--emit': Boolean,
// Aliases.
'-e': '--eval',
'-i': '--interactive',
'-p': '--print',
'-r': '--require',
'-h': '--help',
'-s': '--script-mode',
'-v': '--version',
'-T': '--transpile-only',
'-H': '--compiler-host',
'-I': '--ignore',
'-P': '--project',
'-C': '--compiler',
'-D': '--ignore-diagnostics',
'-O': '--compiler-options'
}, {
argv,
stopAtPositional: true
});
// Only setting defaults for CLI-specific flags
// Anything passed to `register()` can be `undefined`; `create()` will apply
// defaults.
const { '--dir': dir, '--help': help = false, '--script-mode': scriptMode = false, '--version': version = 0, '--require': requires = [], '--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;
if (help) {
console.log(`
Usage: ts-node [options] [ -e script | script.ts ] [arguments]
Options:
Options:
-e, --eval [code] Evaluate code
-p, --print Print result of \`--eval\`
-r, --require [path] Require a node module before execution
-e, --eval [code] Evaluate code
-p, --print Print result of \`--eval\`
-r, --require [path] Require a node module before execution
-i, --interactive Opens the REPL even if stdin does not appear to be a terminal
-h, --help Print CLI usage
-v, --version Print module version information
-h, --help Print CLI usage
-v, --version Print module version information
-s, --script-mode Use cwd from <script.ts> instead of current directory
-T, --transpile-only Use TypeScript's faster \`transpileModule\`
-I, --ignore [pattern] Override the path patterns to skip compilation
-P, --project [path] Path to TypeScript JSON project file
-C, --compiler [name] Specify a custom TypeScript compiler
-D, --ignore-diagnostics [code] Ignore TypeScript warnings by diagnostic code
-O, --compiler-options [opts] JSON object to merge with compiler options
-T, --transpile-only Use TypeScript's faster \`transpileModule\`
-H, --compiler-host Use TypeScript's compiler host API
-I, --ignore [pattern] Override the path patterns to skip compilation
-P, --project [path] Path to TypeScript JSON project file
-C, --compiler [name] Specify a custom TypeScript compiler
-D, --ignore-diagnostics [code] Ignore TypeScript warnings by diagnostic code
-O, --compiler-options [opts] JSON object to merge with compiler options
--files Load files from \`tsconfig.json\` on startup
--pretty Use pretty diagnostic formatter
--skip-project Skip reading \`tsconfig.json\`
--skip-ignore Skip \`--ignore\` checks
--prefer-ts-exts Prefer importing TypeScript files over JavaScript files
`);
process.exit(0);
}
// Output project information.
if (version === 1) {
console.log(`v${index_1.VERSION}`);
process.exit(0);
}
const cwd = process.cwd();
const code = args['--eval'];
const isPrinted = args['--print'] !== undefined;
/**
* Eval helpers.
*/
const EVAL_FILENAME = `[eval].ts`;
const EVAL_PATH = path_1.join(cwd, EVAL_FILENAME);
const EVAL_INSTANCE = { input: '', output: '', version: 0, lines: 0 };
// Register the TypeScript compiler instance.
const service = index_1.register({
files,
pretty,
typeCheck,
transpileOnly,
ignore,
project,
skipIgnore,
preferTsExts,
logError,
skipProject,
compiler,
ignoreDiagnostics,
compilerOptions,
readFile: code ? readFileEval : undefined,
fileExists: code ? fileExistsEval : undefined
});
// Output project information.
if (version >= 2) {
console.log(`ts-node v${index_1.VERSION}`);
console.log(`node ${process.version}`);
console.log(`compiler v${service.ts.version}`);
process.exit(0);
}
// Require specified modules before start-up.
if (args['--require'])
Module._preloadModules(args['--require']);
// Prepend `ts-node` arguments to CLI for child processes.
process.execArgv.unshift(__filename, ...process.argv.slice(2, process.argv.length - args._.length));
process.argv = [process.argv[1]].concat(args._.length ? path_1.resolve(cwd, args._[0]) : []).concat(args._.slice(1));
// Execute the main contents (either eval, script or piped).
if (code) {
evalAndExit(code, isPrinted);
}
else {
if (args._.length) {
Module.runMain();
--dir Specify working directory for config resolution
--scope Scope compiler to files within \`cwd\` only
--files Load \`files\`, \`include\` and \`exclude\` from \`tsconfig.json\` on startup
--pretty Use pretty diagnostic formatter (usually enabled by default)
--skip-project Skip reading \`tsconfig.json\`
--skip-ignore Skip \`--ignore\` checks
--prefer-ts-exts Prefer importing TypeScript files over JavaScript files
--log-error Logs TypeScript errors to stderr instead of throwing exceptions
`);
process.exit(0);
}
// Output project information.
if (version === 1) {
console.log(`v${index_1.VERSION}`);
process.exit(0);
}
const cwd = dir || process.cwd();
/** Unresolved. May point to a symlink, not realpath. May be missing file extension */
const scriptPath = args._.length ? path_1.resolve(cwd, args._[0]) : undefined;
const state = new EvalState(scriptPath || path_1.join(cwd, EVAL_FILENAME));
// Register the TypeScript compiler instance.
const service = index_1.register({
dir: getCwd(dir, scriptMode, scriptPath),
emit,
files,
pretty,
transpileOnly,
typeCheck,
compilerHost,
ignore,
preferTsExts,
logError,
project,
skipProject,
skipIgnore,
compiler,
ignoreDiagnostics,
compilerOptions,
readFile: code !== undefined
? (path) => {
if (path === state.path)
return state.input;
try {
return fs_1.readFileSync(path, 'utf8');
}
catch (err) { /* Ignore. */ }
}
: undefined,
fileExists: code !== undefined
? (path) => {
if (path === state.path)
return true;
try {
const stats = fs_1.statSync(path);
return stats.isFile() || stats.isFIFO();
}
catch (err) {
return false;
}
}
: undefined
});
// Output project information.
if (version >= 2) {
console.log(`ts-node v${index_1.VERSION}`);
console.log(`node ${process.version}`);
console.log(`compiler v${service.ts.version}`);
process.exit(0);
}
// Create a local module instance based on `cwd`.
const module = new Module(state.path);
module.filename = state.path;
module.paths = Module._nodeModulePaths(cwd);
Module._preloadModules(requires);
// Prepend `ts-node` arguments to CLI for child processes.
process.execArgv.unshift(__filename, ...process.argv.slice(2, process.argv.length - args._.length));
process.argv = [process.argv[1]].concat(scriptPath || []).concat(args._.slice(1));
// Execute the main contents (either eval, script or piped).
if (code !== undefined && !interactive) {
evalAndExit(service, state, module, code, print);
}
else {
// Piping of execution _only_ occurs when no other script is specified.
if (process.stdin.isTTY) {
startRepl();
if (args._.length) {
Module.runMain();
}
else {
let code = '';
process.stdin.on('data', (chunk) => code += chunk);
process.stdin.on('end', () => evalAndExit(code, isPrinted));
// Piping of execution _only_ occurs when no other script is specified.
// --interactive flag forces REPL
if (interactive || process.stdin.isTTY) {
startRepl(service, state, code);
}
else {
let buffer = code || '';
process.stdin.on('data', (chunk) => buffer += chunk);
process.stdin.on('end', () => evalAndExit(service, state, module, buffer, print));
}
}
}
}
exports.main = main;
/**
* Get project path from args.
*/
function getCwd(dir, scriptMode, scriptPath) {
// Validate `--script-mode` usage is correct.
if (scriptMode) {
if (!scriptPath) {
throw new TypeError('Script mode must be used with a script name, e.g. `ts-node -s <script.ts>`');
}
if (dir) {
throw new TypeError('Script mode cannot be combined with `--dir`');
}
// Use node's own resolution behavior to ensure we follow symlinks.
// scriptPath may omit file extension or point to a directory with or without package.json.
// This happens before we are registered, so we tell node's resolver to consider ts, tsx, and jsx files.
// In extremely rare cases, is is technically possible to resolve the wrong directory,
// because we do not yet know preferTsExts, jsx, nor allowJs.
// See also, justification why this will not happen in real-world situations:
// https://github.com/TypeStrong/ts-node/pull/1009#issuecomment-613017081
const exts = ['.js', '.jsx', '.ts', '.tsx'];
const extsTemporarilyInstalled = [];
for (const ext of exts) {
if (!hasOwnProperty(require.extensions, ext)) { // tslint:disable-line
extsTemporarilyInstalled.push(ext);
require.extensions[ext] = function () { }; // tslint:disable-line
}
}
try {
return path_1.dirname(require.resolve(scriptPath));
}
finally {
for (const ext of extsTemporarilyInstalled) {
delete require.extensions[ext]; // tslint:disable-line
}
}
}
return dir;
}
/**
* Evaluate a script.
*/
function evalAndExit(code, isPrinted) {
const module = new Module(EVAL_FILENAME);
module.filename = EVAL_FILENAME;
module.paths = Module._nodeModulePaths(cwd);
global.__filename = EVAL_FILENAME;
global.__dirname = cwd;
function evalAndExit(service, state, module, code, isPrinted) {
let result;
global.__filename = module.filename;
global.__dirname = path_1.dirname(module.filename);
global.exports = module.exports;
global.module = module;
global.require = module.require.bind(module);
let result;
try {
result = _eval(code);
result = _eval(service, state, code);
}
catch (error) {
if (error instanceof index_1.TSError) {
console.error(error.diagnosticText);
console.error(error);
process.exit(1);

@@ -175,9 +273,9 @@ }

*/
function _eval(input) {
const lines = EVAL_INSTANCE.lines;
function _eval(service, state, input) {
const lines = state.lines;
const isCompletion = !/\n$/.test(input);
const undo = appendEval(input);
const undo = appendEval(state, input);
let output;
try {
output = service.compile(EVAL_INSTANCE.input, EVAL_PATH, -lines);
output = service.compile(state.input, state.path, -lines);
}

@@ -189,3 +287,3 @@ catch (err) {

// Use `diff` to check for new JavaScript to execute.
const changes = diff_1.diffLines(EVAL_INSTANCE.output, output);
const changes = diff_1.diffLines(state.output, output);
if (isCompletion) {

@@ -195,6 +293,6 @@ undo();

else {
EVAL_INSTANCE.output = output;
state.output = output;
}
return changes.reduce((result, change) => {
return change.added ? exec(change.value, EVAL_FILENAME) : result;
return change.added ? exec(change.value, state.path) : result;
}, undefined);

@@ -212,3 +310,13 @@ }

*/
function startRepl() {
function startRepl(service, state, code) {
// Eval incoming code before the REPL starts.
if (code) {
try {
_eval(service, state, `${code}\n`);
}
catch (err) {
console.error(err);
process.exit(1);
}
}
const repl = repl_1.start({

@@ -222,8 +330,38 @@ prompt: '> ',

});
/**
* Eval code from the REPL.
*/
function replEval(code, _context, _filename, callback) {
let err = null;
let result;
// TODO: Figure out how to handle completion here.
if (code === '.scope') {
callback(err);
return;
}
try {
result = _eval(service, state, code);
}
catch (error) {
if (error instanceof index_1.TSError) {
// Support recoverable compilations using >= node 6.
if (repl_1.Recoverable && isRecoverable(error)) {
err = new repl_1.Recoverable(error);
}
else {
console.error(error);
}
}
else {
err = error;
}
}
return callback(err, result);
}
// Bookmark the point where we should reset the REPL state.
const resetEval = appendEval('');
const resetEval = appendEval(state, '');
function reset() {
resetEval();
// Hard fix for TypeScript forcing `Object.defineProperty(exports, ...)`.
exec('exports = module.exports', EVAL_FILENAME);
exec('exports = module.exports', state.path);
}

@@ -239,39 +377,22 @@ reset();

}
const undo = appendEval(identifier);
const { name, comment } = service.getTypeInfo(EVAL_INSTANCE.input, EVAL_PATH, EVAL_INSTANCE.input.length);
const undo = appendEval(state, identifier);
const { name, comment } = service.getTypeInfo(state.input, state.path, state.input.length);
undo();
repl.outputStream.write(`${name}\n${comment ? `${comment}\n` : ''}`);
if (name)
repl.outputStream.write(`${name}\n`);
if (comment)
repl.outputStream.write(`${comment}\n`);
repl.displayPrompt();
}
});
}
/**
* Eval code from the REPL.
*/
function replEval(code, _context, _filename, callback) {
let err = null;
let result;
// TODO: Figure out how to handle completion here.
if (code === '.scope') {
callback(err);
return;
// Set up REPL history when available natively via node.js >= 11.
if (repl.setupHistory) {
const historyPath = process.env.TS_NODE_HISTORY || path_1.join(os_1.homedir(), '.ts_node_repl_history');
repl.setupHistory(historyPath, err => {
if (!err)
return;
console.error(err);
process.exit(1);
});
}
try {
result = _eval(code);
}
catch (error) {
if (error instanceof index_1.TSError) {
// Support recoverable compilations using >= node 6.
if (repl_1.Recoverable && isRecoverable(error)) {
err = new repl_1.Recoverable(error);
}
else {
console.error(error.diagnosticText);
}
}
else {
err = error;
}
}
callback(err, result);
}

@@ -281,19 +402,19 @@ /**

*/
function appendEval(input) {
const undoInput = EVAL_INSTANCE.input;
const undoVersion = EVAL_INSTANCE.version;
const undoOutput = EVAL_INSTANCE.output;
const undoLines = EVAL_INSTANCE.lines;
function appendEval(state, input) {
const undoInput = state.input;
const undoVersion = state.version;
const undoOutput = state.output;
const undoLines = state.lines;
// Handle ASI issues with TypeScript re-evaluation.
if (undoInput.charAt(undoInput.length - 1) === '\n' && /^\s*[\[\(\`]/.test(input) && !/;\s*$/.test(undoInput)) {
EVAL_INSTANCE.input = `${EVAL_INSTANCE.input.slice(0, -1)};\n`;
if (undoInput.charAt(undoInput.length - 1) === '\n' && /^\s*[\/\[(`-]/.test(input) && !/;\s*$/.test(undoInput)) {
state.input = `${state.input.slice(0, -1)};\n`;
}
EVAL_INSTANCE.input += input;
EVAL_INSTANCE.lines += lineCount(input);
EVAL_INSTANCE.version++;
state.input += input;
state.lines += lineCount(input);
state.version++;
return function () {
EVAL_INSTANCE.input = undoInput;
EVAL_INSTANCE.output = undoOutput;
EVAL_INSTANCE.version = undoVersion;
EVAL_INSTANCE.lines = undoLines;
state.input = undoInput;
state.output = undoOutput;
state.version = undoVersion;
state.lines = undoLines;
};

@@ -313,27 +434,2 @@ }

}
/**
* Get the file text, checking for eval first.
*/
function readFileEval(path) {
if (path === EVAL_PATH)
return EVAL_INSTANCE.input;
try {
return fs_1.readFileSync(path, 'utf8');
}
catch (err) { /* Ignore. */ }
}
/**
* Get whether the file exists.
*/
function fileExistsEval(path) {
if (path === EVAL_PATH)
return true;
try {
const stats = fs_1.statSync(path);
return stats.isFile() || stats.isFIFO();
}
catch (err) {
return false;
}
}
const RECOVERY_CODES = new Set([

@@ -354,2 +450,9 @@ 1003,

}
/** Safe `hasOwnProperty` */
function hasOwnProperty(object, property) {
return Object.prototype.hasOwnProperty.call(object, property);
}
if (require.main === module) {
main(process.argv.slice(2));
}
//# sourceMappingURL=bin.js.map
import { BaseError } from 'make-error';
import * as _ts from 'typescript';
/**
* @internal
* Registered `ts-node` instance information.
*/
export declare const INSPECT_CUSTOM: symbol;
export declare const REGISTER_INSTANCE: unique symbol;
/**
* Expose `REGISTER_INSTANCE` information on node.js `process`.
*/
declare global {
namespace NodeJS {
interface Process {
[REGISTER_INSTANCE]?: Register;
}
}
}
/**
* Common TypeScript interfaces between versions.

@@ -33,23 +43,119 @@ */

/**
* Registration options.
* Options for creating a new TypeScript compiler instance.
*/
export interface Options {
pretty?: boolean | null;
typeCheck?: boolean | null;
transpileOnly?: boolean | null;
logError?: boolean | null;
files?: boolean | null;
export interface CreateOptions {
/**
* Specify working directory for config resolution.
*
* @default process.cwd()
*/
dir?: string;
/**
* Emit output files into `.ts-node` directory.
*
* @default false
*/
emit?: boolean;
/**
* Scope compiler to files within `cwd`.
*
* @default false
*/
scope?: boolean;
/**
* Use pretty diagnostic formatter.
*
* @default false
*/
pretty?: boolean;
/**
* Use TypeScript's faster `transpileModule`.
*
* @default false
*/
transpileOnly?: boolean;
/**
* **DEPRECATED** Specify type-check is enabled (e.g. `transpileOnly == false`).
*
* @default true
*/
typeCheck?: boolean;
/**
* Use TypeScript's compiler host API.
*
* @default false
*/
compilerHost?: boolean;
/**
* Logs TypeScript errors to stderr instead of throwing exceptions.
*
* @default false
*/
logError?: boolean;
/**
* Load files from `tsconfig.json` on startup.
*
* @default false
*/
files?: boolean;
/**
* Specify a custom TypeScript compiler.
*
* @default "typescript"
*/
compiler?: string;
/**
* Override the path patterns to skip compilation.
*
* @default /node_modules/
* @docsDefault "/node_modules/"
*/
ignore?: string[];
/**
* Path to TypeScript JSON project file.
*/
project?: string;
skipIgnore?: boolean | null;
skipProject?: boolean | null;
preferTsExts?: boolean | null;
/**
* Skip project config resolution and loading.
*
* @default false
*/
skipProject?: boolean;
/**
* Skip ignore check.
*
* @default false
*/
skipIgnore?: boolean;
/**
* JSON object to merge with compiler options.
*
* @allOf [{"$ref": "https://schemastore.azurewebsites.net/schemas/json/tsconfig.json#definitions/compilerOptionsDefinition/properties/compilerOptions"}]
*/
compilerOptions?: object;
/**
* Ignore TypeScript warnings by diagnostic code.
*/
ignoreDiagnostics?: Array<number | string>;
readFile?: (path: string) => string | undefined;
fileExists?: (path: string) => boolean;
transformers?: _ts.CustomTransformers;
transformers?: _ts.CustomTransformers | ((p: _ts.Program) => _ts.CustomTransformers);
}
/**
* Options for registering a TypeScript compiler instance globally.
*/
export interface RegisterOptions extends CreateOptions {
/**
* Re-order file extensions so that TypeScript imports are preferred.
*
* @default false
*/
preferTsExts?: boolean;
}
/**
* Must be an interface to support `typescript-json-schema`.
*/
export interface TsConfigOptions extends Omit<RegisterOptions, 'transformers' | 'readFile' | 'fileExists' | 'skipProject' | 'project' | 'dir'> {
}
/**
* Information retrieved from type info check.

@@ -62,5 +168,6 @@ */

/**
* Default register options.
* Default register options, including values specified via environment
* variables.
*/
export declare const DEFAULTS: Options;
export declare const DEFAULTS: RegisterOptions;
/**

@@ -91,5 +198,7 @@ * Split a string array of values.

export interface Register {
cwd: string;
extensions: string[];
ts: TSCommon;
config: _ts.ParsedCommandLine;
options: RegisterOptions;
enabled(enabled?: boolean): boolean;
ignored(fileName: string): boolean;
compile(code: string, fileName: string, lineOffset?: number): string;

@@ -99,4 +208,8 @@ getTypeInfo(code: string, fileName: string, position: number): TypeInfo;

/**
* Register TypeScript compiler.
* Register TypeScript compiler instance onto node.js
*/
export declare function register(opts?: Options): Register;
export declare function register(opts?: RegisterOptions): Register;
/**
* Create TypeScript compiler instance.
*/
export declare function create(rawOptions?: CreateOptions): Register;

@@ -5,6 +5,10 @@ "use strict";

const sourceMapSupport = require("source-map-support");
const yn_1 = require("yn");
const ynModule = require("yn");
const make_error_1 = require("make-error");
const util = require("util");
/**
* Registered `ts-node` instance information.
*/
exports.REGISTER_INSTANCE = Symbol.for('ts-node.register.instance');
/**
* @internal

@@ -14,6 +18,17 @@ */

/**
* Wrapper around yn module that returns `undefined` instead of `null`.
* This is implemented by yn v4, but we're staying on v3 to avoid v4's node 10 requirement.
*/
function yn(value) {
var _a;
return (_a = ynModule(value)) !== null && _a !== void 0 ? _a : undefined;
}
/**
* Debugging `ts-node`.
*/
const shouldDebug = yn_1.default(process.env.TS_NODE_DEBUG);
const debug = shouldDebug ? console.log.bind(console, 'ts-node') : () => undefined;
const shouldDebug = yn(process.env.TS_NODE_DEBUG);
/** @internal */
exports.debug = shouldDebug ?
(...args) => console.log(`[ts-node ${new Date().toISOString()}]`, ...args)
: () => undefined;
const debugFn = shouldDebug ?

@@ -23,3 +38,3 @@ (key, fn) => {

return (x) => {
debug(key, x, ++i);
exports.debug(key, x, ++i);
return fn(x);

@@ -34,29 +49,36 @@ };

/**
* Track the project information.
* Like `Object.assign`, but ignores `undefined` properties.
*/
class MemoryCache {
constructor(rootFileNames = []) {
this.fileContents = new Map();
this.fileVersions = new Map();
for (const fileName of rootFileNames)
this.fileVersions.set(fileName, 1);
function assign(initialValue, ...sources) {
for (const source of sources) {
for (const key of Object.keys(source)) {
const value = source[key];
if (value !== undefined)
initialValue[key] = value;
}
}
return initialValue;
}
/**
* Default register options.
* Default register options, including values specified via environment
* variables.
*/
exports.DEFAULTS = {
files: yn_1.default(process.env['TS_NODE_FILES']),
pretty: yn_1.default(process.env['TS_NODE_PRETTY']),
compiler: process.env['TS_NODE_COMPILER'],
compilerOptions: parse(process.env['TS_NODE_COMPILER_OPTIONS']),
ignore: split(process.env['TS_NODE_IGNORE']),
project: process.env['TS_NODE_PROJECT'],
skipIgnore: yn_1.default(process.env['TS_NODE_SKIP_IGNORE']),
skipProject: yn_1.default(process.env['TS_NODE_SKIP_PROJECT']),
preferTsExts: yn_1.default(process.env['TS_NODE_PREFER_TS_EXTS']),
ignoreDiagnostics: split(process.env['TS_NODE_IGNORE_DIAGNOSTICS']),
typeCheck: yn_1.default(process.env['TS_NODE_TYPE_CHECK']),
transpileOnly: yn_1.default(process.env['TS_NODE_TRANSPILE_ONLY']),
logError: yn_1.default(process.env['TS_NODE_LOG_ERROR'])
dir: process.env.TS_NODE_DIR,
emit: yn(process.env.TS_NODE_EMIT),
scope: yn(process.env.TS_NODE_SCOPE),
files: yn(process.env.TS_NODE_FILES),
pretty: yn(process.env.TS_NODE_PRETTY),
compiler: process.env.TS_NODE_COMPILER,
compilerOptions: parse(process.env.TS_NODE_COMPILER_OPTIONS),
ignore: split(process.env.TS_NODE_IGNORE),
project: process.env.TS_NODE_PROJECT,
skipProject: yn(process.env.TS_NODE_SKIP_PROJECT),
skipIgnore: yn(process.env.TS_NODE_SKIP_IGNORE),
preferTsExts: yn(process.env.TS_NODE_PREFER_TS_EXTS),
ignoreDiagnostics: split(process.env.TS_NODE_IGNORE_DIAGNOSTICS),
transpileOnly: yn(process.env.TS_NODE_TRANSPILE_ONLY),
typeCheck: yn(process.env.TS_NODE_TYPE_CHECK),
compilerHost: yn(process.env.TS_NODE_COMPILER_HOST),
logError: yn(process.env.TS_NODE_LOG_ERROR)
};

@@ -72,3 +94,3 @@ /**

noEmit: false,
outDir: '$$ts-node$$'
outDir: '.ts-node'
};

@@ -126,8 +148,61 @@ /**

}
/** @internal */
function getExtensions(config) {
const tsExtensions = ['.ts'];
const jsExtensions = [];
// Enable additional extensions when JSX or `allowJs` is enabled.
if (config.options.jsx)
tsExtensions.push('.tsx');
if (config.options.allowJs)
jsExtensions.push('.js');
if (config.options.jsx && config.options.allowJs)
jsExtensions.push('.jsx');
return { tsExtensions, jsExtensions };
}
exports.getExtensions = getExtensions;
/**
* Register TypeScript compiler.
* Register TypeScript compiler instance onto node.js
*/
function register(opts = {}) {
const options = Object.assign({}, exports.DEFAULTS, opts);
const originalJsHandler = require.extensions['.js']; // tslint:disable-line
const service = create(opts);
const { tsExtensions, jsExtensions } = getExtensions(service.config);
const extensions = [...tsExtensions, ...jsExtensions];
// Expose registered instance globally.
process[exports.REGISTER_INSTANCE] = service;
// Register the extensions.
registerExtensions(service.options.preferTsExts, extensions, service, originalJsHandler);
return service;
}
exports.register = register;
/**
* Create TypeScript compiler instance.
*/
function create(rawOptions = {}) {
var _a, _b;
const dir = (_a = rawOptions.dir) !== null && _a !== void 0 ? _a : exports.DEFAULTS.dir;
const compilerName = (_b = rawOptions.compiler) !== null && _b !== void 0 ? _b : exports.DEFAULTS.compiler;
const cwd = dir ? path_1.resolve(dir) : process.cwd();
/**
* Load the typescript compiler. It is required to load the tsconfig but might
* be changed by the tsconfig, so we sometimes have to do this twice.
*/
function loadCompiler(name) {
const compiler = require.resolve(name || 'typescript', { paths: [cwd, __dirname] });
const ts = require(compiler);
return { compiler, ts };
}
// Compute minimum options to read the config file.
let { compiler, ts } = loadCompiler(compilerName);
// Read config file and merge new options between env and CLI options.
const { config, options: tsconfigOptions } = readConfig(cwd, ts, rawOptions);
const options = assign({}, exports.DEFAULTS, tsconfigOptions || {}, rawOptions);
// If `compiler` option changed based on tsconfig, re-load the compiler.
if (options.compiler !== compilerName) {
({ compiler, ts } = loadCompiler(options.compiler));
}
const readFile = options.readFile || ts.sys.readFile;
const fileExists = options.fileExists || ts.sys.fileExists;
const transpileOnly = options.transpileOnly === true || options.typeCheck === false;
const transformers = options.transformers || undefined;
const ignoreDiagnostics = [

@@ -139,19 +214,10 @@ 6059,

].map(Number);
const ignore = options.skipIgnore ? [] : (options.ignore || ['/node_modules/']).map(str => new RegExp(str));
// Require the TypeScript compiler and configuration.
const cwd = process.cwd();
const typeCheck = options.typeCheck === true || options.transpileOnly !== true;
const compiler = require.resolve(options.compiler || 'typescript', { paths: [cwd, __dirname] });
const ts = require(compiler);
const transformers = options.transformers || undefined;
const readFile = options.readFile || ts.sys.readFile;
const fileExists = options.fileExists || ts.sys.fileExists;
const config = readConfig(cwd, ts, fileExists, readFile, options);
const configDiagnosticList = filterDiagnostics(config.errors, ignoreDiagnostics);
const extensions = ['.ts'];
const outputCache = new Map();
const isScoped = options.scope ? (relname) => relname.charAt(0) !== '.' : () => true;
const shouldIgnore = createIgnore(options.skipIgnore ? [] : (options.ignore || ['(?:^|/)node_modules/']).map(str => new RegExp(str)));
const diagnosticHost = {
getNewLine: () => ts.sys.newLine,
getCurrentDirectory: () => cwd,
getCanonicalFileName: (path) => path
getCanonicalFileName: ts.sys.useCaseSensitiveFileNames ? x => x : x => x.toLowerCase()
};

@@ -162,7 +228,8 @@ // Install source map support and read from memory cache.

retrieveFile(path) {
return outputCache.get(path) || '';
var _a;
return ((_a = outputCache.get(normalizeSlashes(path))) === null || _a === void 0 ? void 0 : _a.content) || '';
}
});
const formatDiagnostics = process.stdout.isTTY || options.pretty
? ts.formatDiagnosticsWithColorAndContext
? (ts.formatDiagnosticsWithColorAndContext || ts.formatDiagnostics)
: ts.formatDiagnostics;

@@ -188,9 +255,2 @@ function createTSError(diagnostics) {

reportTSError(configDiagnosticList);
// Enable additional extensions when JSX or `allowJs` is enabled.
if (config.options.jsx)
extensions.push('.tsx');
if (config.options.allowJs)
extensions.push('.js');
if (config.options.jsx && config.options.allowJs)
extensions.push('.jsx');
/**

@@ -205,117 +265,268 @@ * Get the extension for a transpiled file.

*/
let getOutput = function (code, fileName, lineOffset = 0) {
let getOutput;
let getTypeInfo;
const getOutputTranspileOnly = (code, fileName, overrideCompilerOptions) => {
const result = ts.transpileModule(code, {
fileName,
transformers,
compilerOptions: config.options,
compilerOptions: overrideCompilerOptions ? Object.assign(Object.assign({}, config.options), overrideCompilerOptions) : config.options,
reportDiagnostics: true
});
const diagnosticList = result.diagnostics ?
filterDiagnostics(result.diagnostics, ignoreDiagnostics) :
[];
const diagnosticList = filterDiagnostics(result.diagnostics || [], ignoreDiagnostics);
if (diagnosticList.length)
reportTSError(configDiagnosticList);
reportTSError(diagnosticList);
return [result.outputText, result.sourceMapText];
};
let getTypeInfo = function (_code, _fileName, _position) {
throw new TypeError(`Type information is unavailable without "--type-check"`);
};
// Use full language services when the fast option is disabled.
if (typeCheck) {
const memoryCache = new MemoryCache(config.fileNames);
if (!transpileOnly) {
const fileContents = new Map();
const rootFileNames = config.fileNames.slice();
const cachedReadFile = cachedLookup(debugFn('readFile', readFile));
// Create the compiler host for type checking.
const serviceHost = {
getScriptFileNames: () => Array.from(memoryCache.fileVersions.keys()),
getScriptVersion: (fileName) => {
const version = memoryCache.fileVersions.get(fileName);
return version === undefined ? '' : version.toString();
},
getScriptSnapshot(fileName) {
let contents = memoryCache.fileContents.get(fileName);
// Read contents into TypeScript memory cache.
if (contents === undefined) {
contents = cachedReadFile(fileName);
if (contents === undefined)
return;
memoryCache.fileVersions.set(fileName, 1);
memoryCache.fileContents.set(fileName, contents);
// Use language services by default (TODO: invert next major version).
if (!options.compilerHost) {
let projectVersion = 1;
const fileVersions = new Map(rootFileNames.map(fileName => [fileName, 0]));
const getCustomTransformers = () => {
if (typeof transformers === 'function') {
const program = service.getProgram();
return program ? transformers(program) : undefined;
}
return ts.ScriptSnapshot.fromString(contents);
},
readFile: cachedReadFile,
readDirectory: cachedLookup(debugFn('readDirectory', ts.sys.readDirectory)),
getDirectories: cachedLookup(debugFn('getDirectories', ts.sys.getDirectories)),
fileExists: cachedLookup(debugFn('fileExists', fileExists)),
directoryExists: cachedLookup(debugFn('directoryExists', ts.sys.directoryExists)),
getNewLine: () => ts.sys.newLine,
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
getCurrentDirectory: () => cwd,
getCompilationSettings: () => config.options,
getDefaultLibFileName: () => ts.getDefaultLibFilePath(config.options),
getCustomTransformers: () => transformers
};
const registry = ts.createDocumentRegistry(ts.sys.useCaseSensitiveFileNames, cwd);
const service = ts.createLanguageService(serviceHost, registry);
// Set the file contents into cache manually.
const updateMemoryCache = function (contents, fileName) {
const fileVersion = memoryCache.fileVersions.get(fileName) || 0;
// Avoid incrementing cache when nothing has changed.
if (memoryCache.fileContents.get(fileName) === contents)
return;
memoryCache.fileVersions.set(fileName, fileVersion + 1);
memoryCache.fileContents.set(fileName, contents);
};
getOutput = function (code, fileName, lineOffset = 0) {
updateMemoryCache(code, fileName);
const output = service.getEmitOutput(fileName);
// Get the relevant diagnostics - this is 3x faster than `getPreEmitDiagnostics`.
const diagnostics = service.getSemanticDiagnostics(fileName)
.concat(service.getSyntacticDiagnostics(fileName));
const diagnosticList = filterDiagnostics(diagnostics, ignoreDiagnostics);
if (diagnosticList.length)
reportTSError(diagnosticList);
if (output.emitSkipped) {
throw new TypeError(`${path_1.relative(cwd, fileName)}: Emit skipped`);
return transformers;
};
// Create the compiler host for type checking.
const serviceHost = {
getProjectVersion: () => String(projectVersion),
getScriptFileNames: () => Array.from(fileVersions.keys()),
getScriptVersion: (fileName) => {
const version = fileVersions.get(fileName);
return version ? version.toString() : '';
},
getScriptSnapshot(fileName) {
let contents = fileContents.get(fileName);
// Read contents into TypeScript memory cache.
if (contents === undefined) {
contents = cachedReadFile(fileName);
if (contents === undefined)
return;
fileVersions.set(fileName, 1);
fileContents.set(fileName, contents);
}
return ts.ScriptSnapshot.fromString(contents);
},
readFile: cachedReadFile,
readDirectory: ts.sys.readDirectory,
getDirectories: cachedLookup(debugFn('getDirectories', ts.sys.getDirectories)),
fileExists: cachedLookup(debugFn('fileExists', fileExists)),
directoryExists: cachedLookup(debugFn('directoryExists', ts.sys.directoryExists)),
getNewLine: () => ts.sys.newLine,
useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
getCurrentDirectory: () => cwd,
getCompilationSettings: () => config.options,
getDefaultLibFileName: () => ts.getDefaultLibFilePath(config.options),
getCustomTransformers: getCustomTransformers
};
const registry = ts.createDocumentRegistry(ts.sys.useCaseSensitiveFileNames, cwd);
const service = ts.createLanguageService(serviceHost, registry);
const updateMemoryCache = (contents, fileName) => {
// Add to `rootFiles` when discovered for the first time.
if (!fileVersions.has(fileName)) {
rootFileNames.push(fileName);
}
const previousVersion = fileVersions.get(fileName) || 0;
const previousContents = fileContents.get(fileName);
// Avoid incrementing cache when nothing has changed.
if (contents !== previousContents) {
fileVersions.set(fileName, previousVersion + 1);
fileContents.set(fileName, contents);
// Increment project version for every file change.
projectVersion++;
}
};
let previousProgram = undefined;
getOutput = (code, fileName) => {
updateMemoryCache(code, fileName);
const programBefore = service.getProgram();
if (programBefore !== previousProgram) {
exports.debug(`compiler rebuilt Program instance when getting output for ${fileName}`);
}
const output = service.getEmitOutput(fileName);
// Get the relevant diagnostics - this is 3x faster than `getPreEmitDiagnostics`.
const diagnostics = service.getSemanticDiagnostics(fileName)
.concat(service.getSyntacticDiagnostics(fileName));
const programAfter = service.getProgram();
exports.debug('invariant: Is service.getProject() identical before and after getting emit output and diagnostics? (should always be true) ', programBefore === programAfter);
previousProgram = programAfter;
const diagnosticList = filterDiagnostics(diagnostics, ignoreDiagnostics);
if (diagnosticList.length)
reportTSError(diagnosticList);
if (output.emitSkipped) {
throw new TypeError(`${path_1.relative(cwd, fileName)}: Emit skipped`);
}
// Throw an error when requiring `.d.ts` files.
if (output.outputFiles.length === 0) {
throw new TypeError(`Unable to require file: ${path_1.relative(cwd, fileName)}\n` +
'This is usually the result of a faulty configuration or import. ' +
'Make sure there is a `.js`, `.json` or other executable extension with ' +
'loader attached before `ts-node` available.');
}
return [output.outputFiles[1].text, output.outputFiles[0].text];
};
getTypeInfo = (code, fileName, position) => {
updateMemoryCache(code, fileName);
const info = service.getQuickInfoAtPosition(fileName, position);
const name = ts.displayPartsToString(info ? info.displayParts : []);
const comment = ts.displayPartsToString(info ? info.documentation : []);
return { name, comment };
};
}
else {
const sys = Object.assign(Object.assign(Object.assign({}, ts.sys), diagnosticHost), { readFile: (fileName) => {
const cacheContents = fileContents.get(fileName);
if (cacheContents !== undefined)
return cacheContents;
return cachedReadFile(fileName);
}, readDirectory: ts.sys.readDirectory, getDirectories: cachedLookup(debugFn('getDirectories', ts.sys.getDirectories)), fileExists: cachedLookup(debugFn('fileExists', fileExists)), directoryExists: cachedLookup(debugFn('directoryExists', ts.sys.directoryExists)), resolvePath: cachedLookup(debugFn('resolvePath', ts.sys.resolvePath)), realpath: ts.sys.realpath ? cachedLookup(debugFn('realpath', ts.sys.realpath)) : undefined });
const host = ts.createIncrementalCompilerHost
? ts.createIncrementalCompilerHost(config.options, sys)
: Object.assign(Object.assign({}, sys), { getSourceFile: (fileName, languageVersion) => {
const contents = sys.readFile(fileName);
if (contents === undefined)
return;
return ts.createSourceFile(fileName, contents, languageVersion);
}, getDefaultLibLocation: () => normalizeSlashes(path_1.dirname(compiler)), getDefaultLibFileName: () => normalizeSlashes(path_1.join(path_1.dirname(compiler), ts.getDefaultLibFileName(config.options))), useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames });
// Fallback for older TypeScript releases without incremental API.
let builderProgram = ts.createIncrementalProgram
? ts.createIncrementalProgram({
rootNames: rootFileNames.slice(),
options: config.options,
host: host,
configFileParsingDiagnostics: config.errors,
projectReferences: config.projectReferences
})
: ts.createEmitAndSemanticDiagnosticsBuilderProgram(rootFileNames.slice(), config.options, host, undefined, config.errors, config.projectReferences);
// Read and cache custom transformers.
const customTransformers = typeof transformers === 'function'
? transformers(builderProgram.getProgram())
: transformers;
// Set the file contents into cache manually.
const updateMemoryCache = (contents, fileName) => {
const sourceFile = builderProgram.getSourceFile(fileName);
fileContents.set(fileName, contents);
// Add to `rootFiles` when discovered by compiler for the first time.
if (sourceFile === undefined) {
rootFileNames.push(fileName);
}
// Update program when file changes.
if (sourceFile === undefined || sourceFile.text !== contents) {
builderProgram = ts.createEmitAndSemanticDiagnosticsBuilderProgram(rootFileNames.slice(), config.options, host, builderProgram, config.errors, config.projectReferences);
}
};
getOutput = (code, fileName) => {
const output = ['', ''];
updateMemoryCache(code, fileName);
const sourceFile = builderProgram.getSourceFile(fileName);
if (!sourceFile)
throw new TypeError(`Unable to read file: ${fileName}`);
const program = builderProgram.getProgram();
const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile);
const diagnosticList = filterDiagnostics(diagnostics, ignoreDiagnostics);
if (diagnosticList.length)
reportTSError(diagnosticList);
const result = builderProgram.emit(sourceFile, (path, file, writeByteOrderMark) => {
if (path.endsWith('.map')) {
output[1] = file;
}
else {
output[0] = file;
}
if (options.emit)
sys.writeFile(path, file, writeByteOrderMark);
}, undefined, undefined, customTransformers);
if (result.emitSkipped) {
throw new TypeError(`${path_1.relative(cwd, fileName)}: Emit skipped`);
}
// Throw an error when requiring files that cannot be compiled.
if (output[0] === '') {
if (program.isSourceFileFromExternalLibrary(sourceFile)) {
throw new TypeError(`Unable to compile file from external library: ${path_1.relative(cwd, fileName)}`);
}
throw new TypeError(`Unable to require file: ${path_1.relative(cwd, fileName)}\n` +
'This is usually the result of a faulty configuration or import. ' +
'Make sure there is a `.js`, `.json` or other executable extension with ' +
'loader attached before `ts-node` available.');
}
return output;
};
getTypeInfo = (code, fileName, position) => {
updateMemoryCache(code, fileName);
const sourceFile = builderProgram.getSourceFile(fileName);
if (!sourceFile)
throw new TypeError(`Unable to read file: ${fileName}`);
const node = getTokenAtPosition(ts, sourceFile, position);
const checker = builderProgram.getProgram().getTypeChecker();
const symbol = checker.getSymbolAtLocation(node);
if (!symbol)
return { name: '', comment: '' };
const type = checker.getTypeOfSymbolAtLocation(symbol, node);
const signatures = [...type.getConstructSignatures(), ...type.getCallSignatures()];
return {
name: signatures.length ? signatures.map(x => checker.signatureToString(x)).join('\n') : checker.typeToString(type),
comment: ts.displayPartsToString(symbol ? symbol.getDocumentationComment(checker) : [])
};
};
// Write `.tsbuildinfo` when `--build` is enabled.
if (options.emit && config.options.incremental) {
process.on('exit', () => {
// Emits `.tsbuildinfo` to filesystem.
builderProgram.getProgram().emitBuildInfo();
});
}
// Throw an error when requiring `.d.ts` files.
if (output.outputFiles.length === 0) {
throw new TypeError('Unable to require `.d.ts` file.\n' +
'This is usually the result of a faulty configuration or import. ' +
'Make sure there is a `.js`, `.json` or another executable extension and ' +
'loader (attached before `ts-node`) available alongside ' +
`\`${path_1.basename(fileName)}\`.`);
}
return [output.outputFiles[1].text, output.outputFiles[0].text];
}
}
else {
if (typeof transformers === 'function') {
throw new TypeError('Transformers function is unavailable in "--transpile-only"');
}
getOutput = getOutputTranspileOnly;
getTypeInfo = () => {
throw new TypeError('Type information is unavailable in "--transpile-only"');
};
getTypeInfo = function (code, fileName, position) {
updateMemoryCache(code, fileName);
const info = service.getQuickInfoAtPosition(fileName, position);
const name = ts.displayPartsToString(info ? info.displayParts : []);
const comment = ts.displayPartsToString(info ? info.documentation : []);
return { name, comment };
};
}
const cannotCompileViaBothCodepathsErrorMessage = 'Cannot compile the same file via both `require()` and ESM hooks codepaths. ' +
'This breaks source-map-support, which cannot tell the difference between the two sourcemaps. ' +
'To avoid this problem, load each .ts file as only ESM or only CommonJS.';
// Create a simple TypeScript compiler proxy.
function compile(code, fileName, lineOffset) {
const [value, sourceMap] = getOutput(code, fileName, lineOffset);
const output = updateOutput(value, fileName, sourceMap, getExtension);
outputCache.set(fileName, output);
function compile(code, fileName, lineOffset = 0) {
const normalizedFileName = normalizeSlashes(fileName);
const [value, sourceMap] = getOutput(code, normalizedFileName);
const output = updateOutput(value, normalizedFileName, sourceMap, getExtension);
outputCache.set(normalizedFileName, { content: output });
return output;
}
const register = { cwd, compile, getTypeInfo, extensions, ts };
// Register the extensions.
registerExtensions(opts, extensions, ignore, register, originalJsHandler);
return register;
let active = true;
const enabled = (enabled) => enabled === undefined ? active : (active = !!enabled);
const ignored = (fileName) => {
if (!active)
return true;
const relname = path_1.relative(cwd, fileName);
if (!config.options.allowJs) {
const ext = path_1.extname(fileName);
if (ext === '.js' || ext === '.jsx')
return true;
}
return !isScoped(relname) || shouldIgnore(relname);
};
return { ts, config, compile, getTypeInfo, ignored, enabled, options };
}
exports.register = register;
exports.create = create;
/**
* Check if the filename should be ignored.
*/
function shouldIgnore(filename, ignore) {
const relname = normalizeSlashes(filename);
return ignore.some(x => x.test(relname));
function createIgnore(ignore) {
return (relname) => {
const path = normalizeSlashes(relname);
return ignore.some(x => x.test(path));
};
}
/**
* "Refreshes" an extension on `require.extentions`.
* "Refreshes" an extension on `require.extensions`.
*

@@ -332,8 +543,8 @@ * @param {string} ext

*/
function registerExtensions(opts, extensions, ignore, register, originalJsHandler) {
function registerExtensions(preferTsExts, extensions, register, originalJsHandler) {
// Register new extensions.
for (const ext of extensions) {
registerExtension(ext, ignore, register, originalJsHandler);
registerExtension(ext, register, originalJsHandler);
}
if (opts.preferTsExts) {
if (preferTsExts) {
// tslint:disable-next-line

@@ -348,11 +559,10 @@ const preferredExtensions = new Set([...extensions, ...Object.keys(require.extensions)]);

*/
function registerExtension(ext, ignore, register, originalHandler) {
function registerExtension(ext, register, originalHandler) {
const old = require.extensions[ext] || originalHandler; // tslint:disable-line
require.extensions[ext] = function (m, filename) {
if (shouldIgnore(filename, ignore)) {
if (register.ignored(filename))
return old(m, filename);
}
const _compile = m._compile;
m._compile = function (code, fileName) {
debug('module._compile', fileName);
exports.debug('module._compile', fileName);
return _compile.call(this, register.compile(code, fileName), fileName);

@@ -374,4 +584,2 @@ };

delete config.options.emitDeclarationOnly;
delete config.options.tsBuildInfoFile;
delete config.options.incremental;
// Target ES5 output by default (instead of ES3).

@@ -388,13 +596,16 @@ if (config.options.target === undefined) {

/**
* Load TypeScript configuration.
* Load TypeScript configuration. Returns the parsed TypeScript config and
* any `ts-node` options specified in the config file.
*/
function readConfig(cwd, ts, fileExists, readFile, options) {
function readConfig(cwd, ts, rawOptions) {
var _a, _b;
let config = { compilerOptions: {} };
let basePath = normalizeSlashes(cwd);
let basePath = cwd;
let configFileName = undefined;
const { fileExists = ts.sys.fileExists, readFile = ts.sys.readFile, skipProject = exports.DEFAULTS.skipProject, project = exports.DEFAULTS.project } = rawOptions;
// Read project configuration when available.
if (!options.skipProject) {
configFileName = options.project
? normalizeSlashes(path_1.resolve(cwd, options.project))
: ts.findConfigFile(normalizeSlashes(cwd), fileExists);
if (!skipProject) {
configFileName = project
? path_1.resolve(cwd, project)
: ts.findConfigFile(cwd, fileExists);
if (configFileName) {

@@ -404,10 +615,16 @@ const result = ts.readConfigFile(configFileName, readFile);

if (result.error) {
return { errors: [result.error], fileNames: [], options: {} };
return {
config: { errors: [result.error], fileNames: [], options: {} },
options: {}
};
}
config = result.config;
basePath = normalizeSlashes(path_1.dirname(configFileName));
basePath = path_1.dirname(configFileName);
}
}
// Fix ts-node options that come from tsconfig.json
const tsconfigOptions = Object.assign({}, config['ts-node']);
// Remove resolution of "files".
if (!options.files) {
const files = (_b = (_a = rawOptions.files) !== null && _a !== void 0 ? _a : tsconfigOptions.files) !== null && _b !== void 0 ? _b : exports.DEFAULTS.files;
if (!files) {
config.files = [];

@@ -417,4 +634,10 @@ config.include = [];

// Override default configuration options `ts-node` requires.
config.compilerOptions = Object.assign({}, config.compilerOptions, options.compilerOptions, TS_NODE_COMPILER_OPTIONS);
return fixConfig(ts, ts.parseJsonConfigFileContent(config, ts.sys, basePath, undefined, configFileName));
config.compilerOptions = Object.assign({}, config.compilerOptions, exports.DEFAULTS.compilerOptions, tsconfigOptions.compilerOptions, rawOptions.compilerOptions, TS_NODE_COMPILER_OPTIONS);
const fixedConfig = fixConfig(ts, ts.parseJsonConfigFileContent(config, {
fileExists,
readFile,
readDirectory: ts.sys.readDirectory,
useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames
}, basePath, undefined, configFileName));
return { config: fixedConfig, options: tsconfigOptions };
}

@@ -446,2 +669,23 @@ /**

}
/**
* Get token at file position.
*
* Reference: https://github.com/microsoft/TypeScript/blob/fcd9334f57d85b73dd66ad2d21c02e84822f4841/src/services/utilities.ts#L705-L731
*/
function getTokenAtPosition(ts, sourceFile, position) {
let current = sourceFile;
outer: while (true) {
for (const child of current.getChildren(sourceFile)) {
const start = child.getFullStart();
if (start > position)
break;
const end = child.getEnd();
if (position <= end) {
current = child;
continue outer;
}
}
return current;
}
}
//# sourceMappingURL=index.js.map
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -10,8 +19,21 @@ const chai_1 = require("chai");

const index_1 = require("./index");
const fs_1 = require("fs");
const promisify = require("util.promisify");
const execP = promisify(child_process_1.exec);
const TEST_DIR = path_1.join(__dirname, '../tests');
const EXEC_PATH = path_1.join(__dirname, '../dist/bin');
const PROJECT = path_1.join(TEST_DIR, semver.gte(ts.version, '2.5.0') ? 'tsconfig.json5' : 'tsconfig.json');
const BIN_EXEC = `node "${EXEC_PATH}" --project "${PROJECT}"`;
const PROJECT = path_1.join(TEST_DIR, 'tsconfig.json');
const BIN_PATH = path_1.join(TEST_DIR, 'node_modules/.bin/ts-node');
const BIN_SCRIPT_PATH = path_1.join(TEST_DIR, 'node_modules/.bin/ts-node-script');
const SOURCE_MAP_REGEXP = /\/\/# sourceMappingURL=data:application\/json;charset=utf\-8;base64,[\w\+]+=*$/;
// Pack and install ts-node locally, necessary to test package "exports"
before(function () {
return __awaiter(this, void 0, void 0, function* () {
this.timeout(30000);
yield execP(`npm install`, { cwd: TEST_DIR });
const packageLockPath = path_1.join(TEST_DIR, 'package-lock.json');
fs_1.existsSync(packageLockPath) && fs_1.unlinkSync(packageLockPath);
});
});
describe('ts-node', function () {
const cmd = `"${BIN_PATH}" --project "${PROJECT}"`;
this.timeout(10000);

@@ -24,3 +46,3 @@ it('should export the correct version', function () {

it('should execute cli', function (done) {
child_process_1.exec(`${BIN_EXEC} tests/hello-world`, function (err, stdout) {
child_process_1.exec(`${cmd} tests/hello-world`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -32,3 +54,3 @@ chai_1.expect(stdout).to.equal('Hello, world!\n');

it('should register via cli', function (done) {
child_process_1.exec(`node -r ../register hello-world.ts`, {
child_process_1.exec(`node -r ts-node/register hello-world.ts`, {
cwd: TEST_DIR

@@ -42,3 +64,3 @@ }, function (err, stdout) {

it('should execute cli with absolute path', function (done) {
child_process_1.exec(`${BIN_EXEC} "${path_1.join(TEST_DIR, 'hello-world')}"`, function (err, stdout) {
child_process_1.exec(`${cmd} "${path_1.join(TEST_DIR, 'hello-world')}"`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -50,3 +72,3 @@ chai_1.expect(stdout).to.equal('Hello, world!\n');

it('should print scripts', function (done) {
child_process_1.exec(`${BIN_EXEC} -pe "import { example } from './tests/complex/index';example()"`, function (err, stdout) {
child_process_1.exec(`${cmd} -pe "import { example } from './tests/complex/index';example()"`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -57,6 +79,22 @@ chai_1.expect(stdout).to.equal('example\n');

});
it('should provide registered information globally', function (done) {
child_process_1.exec(`${cmd} tests/env`, function (err, stdout) {
chai_1.expect(err).to.equal(null);
chai_1.expect(stdout).to.equal('object\n');
return done();
});
});
it('should provide registered information on register', function (done) {
child_process_1.exec(`node -r ts-node/register env.ts`, {
cwd: TEST_DIR
}, function (err, stdout) {
chai_1.expect(err).to.equal(null);
chai_1.expect(stdout).to.equal('object\n');
return done();
});
});
if (semver.gte(ts.version, '1.8.0')) {
it('should allow js', function (done) {
child_process_1.exec([
BIN_EXEC,
cmd,
'-O "{\\\"allowJs\\\":true}"',

@@ -72,3 +110,3 @@ '-pe "import { main } from \'./tests/allow-js/run\';main()"'

child_process_1.exec([
BIN_EXEC,
cmd,
'-O "{\\\"allowJs\\\":true}"',

@@ -84,3 +122,3 @@ '-pe "import { Foo2 } from \'./tests/allow-js/with-jsx\'; Foo2.sayHi()"'

it('should eval code', function (done) {
child_process_1.exec(`${BIN_EXEC} -e "import * as m from './tests/module';console.log(m.example('test'))"`, function (err, stdout) {
child_process_1.exec(`${cmd} -e "import * as m from './tests/module';console.log(m.example('test'))"`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -92,3 +130,3 @@ chai_1.expect(stdout).to.equal('TEST\n');

it('should import empty files', function (done) {
child_process_1.exec(`${BIN_EXEC} -e "import './tests/empty'"`, function (err, stdout) {
child_process_1.exec(`${cmd} -e "import './tests/empty'"`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -100,3 +138,3 @@ chai_1.expect(stdout).to.equal('');

it('should throw errors', function (done) {
child_process_1.exec(`${BIN_EXEC} -e "import * as m from './tests/module';console.log(m.example(123))"`, function (err) {
child_process_1.exec(`${cmd} -e "import * as m from './tests/module';console.log(m.example(123))"`, function (err) {
if (err === null) {

@@ -111,3 +149,3 @@ return done('Command was expected to fail, but it succeeded.');

it('should be able to ignore diagnostic', function (done) {
child_process_1.exec(`${BIN_EXEC} --ignore-diagnostics 2345 -e "import * as m from './tests/module';console.log(m.example(123))"`, function (err) {
child_process_1.exec(`${cmd} --ignore-diagnostics 2345 -e "import * as m from './tests/module';console.log(m.example(123))"`, function (err) {
if (err === null) {

@@ -121,3 +159,3 @@ return done('Command was expected to fail, but it succeeded.');

it('should work with source maps', function (done) {
child_process_1.exec(`${BIN_EXEC} tests/throw`, function (err) {
child_process_1.exec(`${cmd} tests/throw`, function (err) {
if (err === null) {

@@ -127,3 +165,3 @@ return done('Command was expected to fail, but it succeeded.');

chai_1.expect(err.message).to.contain([
`${path_1.join(__dirname, '../tests/throw.ts')}:3`,
`${path_1.join(__dirname, '../tests/throw.ts')}:100`,
' bar () { throw new Error(\'this is a demo\') }',

@@ -136,4 +174,4 @@ ' ^',

});
it.skip('eval should work with source maps', function (done) {
child_process_1.exec(`${BIN_EXEC} -pe "import './tests/throw'"`, function (err) {
it('eval should work with source maps', function (done) {
child_process_1.exec(`${cmd} -pe "import './tests/throw'"`, function (err) {
if (err === null) {

@@ -143,3 +181,3 @@ return done('Command was expected to fail, but it succeeded.');

chai_1.expect(err.message).to.contain([
`${path_1.join(__dirname, '../tests/throw.ts')}:3`,
`${path_1.join(__dirname, '../tests/throw.ts')}:100`,
' bar () { throw new Error(\'this is a demo\') }',

@@ -152,3 +190,3 @@ ' ^'

it('should support transpile only mode', function (done) {
child_process_1.exec(`${BIN_EXEC} --transpile-only -pe "x"`, function (err) {
child_process_1.exec(`${cmd} --transpile-only -pe "x"`, function (err) {
if (err === null) {

@@ -161,4 +199,13 @@ return done('Command was expected to fail, but it succeeded.');

});
it('should throw error even in transpileOnly mode', function (done) {
child_process_1.exec(`${cmd} --transpile-only -pe "console."`, function (err) {
if (err === null) {
return done('Command was expected to fail, but it succeeded.');
}
chai_1.expect(err.message).to.contain('error TS1003: Identifier expected');
return done();
});
});
it('should pipe into `ts-node` and evaluate', function (done) {
const cp = child_process_1.exec(BIN_EXEC, function (err, stdout) {
const cp = child_process_1.exec(cmd, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -171,3 +218,3 @@ chai_1.expect(stdout).to.equal('hello\n');

it('should pipe into `ts-node`', function (done) {
const cp = child_process_1.exec(`${BIN_EXEC} -p`, function (err, stdout) {
const cp = child_process_1.exec(`${cmd} -p`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -180,3 +227,3 @@ chai_1.expect(stdout).to.equal('true\n');

it('should pipe into an eval script', function (done) {
const cp = child_process_1.exec(`${BIN_EXEC} --transpile-only -pe 'process.stdin.isTTY'`, function (err, stdout) {
const cp = child_process_1.exec(`${cmd} --transpile-only -pe "process.stdin.isTTY"`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -188,4 +235,14 @@ chai_1.expect(stdout).to.equal('undefined\n');

});
it('should run REPL when --interactive passed and stdin is not a TTY', function (done) {
const cp = child_process_1.exec(`${cmd} --interactive`, function (err, stdout) {
chai_1.expect(err).to.equal(null);
chai_1.expect(stdout).to.equal('> 123\n' +
'undefined\n' +
'> ');
return done();
});
cp.stdin.end('console.log("123")\n');
});
it('should support require flags', function (done) {
child_process_1.exec(`${BIN_EXEC} -r ./tests/hello-world -pe "console.log('success')"`, function (err, stdout) {
child_process_1.exec(`${cmd} -r ./tests/hello-world -pe "console.log('success')"`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -197,3 +254,3 @@ chai_1.expect(stdout).to.equal('Hello, world!\nsuccess\nundefined\n');

it('should support require from node modules', function (done) {
child_process_1.exec(`${BIN_EXEC} -r typescript -e "console.log('success')"`, function (err, stdout) {
child_process_1.exec(`${cmd} -r typescript -e "console.log('success')"`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -205,3 +262,3 @@ chai_1.expect(stdout).to.equal('success\n');

it.skip('should use source maps with react tsx', function (done) {
child_process_1.exec(`${BIN_EXEC} -r ./tests/emit-compiled.ts tests/jsx-react.tsx`, function (err, stdout) {
child_process_1.exec(`${cmd} -r ./tests/emit-compiled.ts tests/jsx-react.tsx`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -213,3 +270,3 @@ chai_1.expect(stdout).to.equal('todo');

it('should allow custom typings', function (done) {
child_process_1.exec(`${BIN_EXEC} tests/custom-types`, function (err, stdout) {
child_process_1.exec(`${cmd} tests/custom-types`, function (err, stdout) {
chai_1.expect(err).to.match(/Error: Cannot find module 'does-not-exist'/);

@@ -220,3 +277,3 @@ return done();

it('should preserve `ts-node` context with child process', function (done) {
child_process_1.exec(`${BIN_EXEC} tests/child-process`, function (err, stdout) {
child_process_1.exec(`${cmd} tests/child-process`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -228,3 +285,3 @@ chai_1.expect(stdout).to.equal('Hello, world!\n');

it('should import js before ts by default', function (done) {
child_process_1.exec(`${BIN_EXEC} tests/import-order/compiled`, function (err, stdout) {
child_process_1.exec(`${cmd} tests/import-order/compiled`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -236,3 +293,3 @@ chai_1.expect(stdout).to.equal('Hello, JavaScript!\n');

it('should import ts before js when --prefer-ts-exts flag is present', function (done) {
child_process_1.exec(`${BIN_EXEC} --prefer-ts-exts tests/import-order/compiled`, function (err, stdout) {
child_process_1.exec(`${cmd} --prefer-ts-exts tests/import-order/compiled`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -243,4 +300,11 @@ chai_1.expect(stdout).to.equal('Hello, TypeScript!\n');

});
it('should import ts before js when TS_NODE_PREFER_TS_EXTS env is present', function (done) {
child_process_1.exec(`${cmd} tests/import-order/compiled`, { env: Object.assign(Object.assign({}, process.env), { TS_NODE_PREFER_TS_EXTS: 'true' }) }, function (err, stdout) {
chai_1.expect(err).to.equal(null);
chai_1.expect(stdout).to.equal('Hello, TypeScript!\n');
return done();
});
});
it('should ignore .d.ts files', function (done) {
child_process_1.exec(`${BIN_EXEC} tests/import-order/importer`, function (err, stdout) {
child_process_1.exec(`${cmd} tests/import-order/importer`, function (err, stdout) {
chai_1.expect(err).to.equal(null);

@@ -251,5 +315,127 @@ chai_1.expect(stdout).to.equal('Hello, World!\n');

});
describe('issue #884', function () {
it('should compile', function (done) {
// TODO disabled because it consistently fails on Windows on TS 2.7
if (process.platform === 'win32' && semver.satisfies(ts.version, '2.7')) {
this.skip();
}
else {
child_process_1.exec(`"${BIN_PATH}" --project tests/issue-884/tsconfig.json tests/issue-884`, function (err, stdout) {
chai_1.expect(err).to.equal(null);
chai_1.expect(stdout).to.equal('');
return done();
});
}
});
});
describe('issue #986', function () {
it('should not compile', function (done) {
child_process_1.exec(`"${BIN_PATH}" --project tests/issue-986/tsconfig.json tests/issue-986`, function (err, stdout, stderr) {
chai_1.expect(err).not.to.equal(null);
chai_1.expect(stderr).to.contain('Cannot find name \'TEST\''); // TypeScript error.
chai_1.expect(stdout).to.equal('');
return done();
});
});
it('should compile with `--files`', function (done) {
child_process_1.exec(`"${BIN_PATH}" --files --project tests/issue-986/tsconfig.json tests/issue-986`, function (err, stdout, stderr) {
chai_1.expect(err).not.to.equal(null);
chai_1.expect(stderr).to.contain('ReferenceError: TEST is not defined'); // Runtime error.
chai_1.expect(stdout).to.equal('');
return done();
});
});
});
if (semver.gte(ts.version, '2.7.0')) {
it('should support script mode', function (done) {
child_process_1.exec(`${BIN_SCRIPT_PATH} tests/scope/a/log`, function (err, stdout) {
chai_1.expect(err).to.equal(null);
chai_1.expect(stdout).to.equal('.ts\n');
return done();
});
});
it('should read tsconfig relative to realpath, not symlink, in scriptMode', function (done) {
if (fs_1.statSync(path_1.join(TEST_DIR, 'main-realpath/symlink/symlink.tsx')).isSymbolicLink()) {
child_process_1.exec(`${BIN_SCRIPT_PATH} tests/main-realpath/symlink/symlink.tsx`, function (err, stdout) {
chai_1.expect(err).to.equal(null);
chai_1.expect(stdout).to.equal('');
return done();
});
}
else {
this.skip();
}
});
}
describe('should read ts-node options from tsconfig.json', function () {
const BIN_EXEC = `"${BIN_PATH}" --project tests/tsconfig-options/tsconfig.json`;
it('should override compiler options from env', function (done) {
child_process_1.exec(`${BIN_EXEC} tests/tsconfig-options/log-options.js`, {
env: Object.assign(Object.assign({}, process.env), { TS_NODE_COMPILER_OPTIONS: '{"typeRoots": ["env-typeroots"]}' })
}, function (err, stdout) {
chai_1.expect(err).to.equal(null);
const { config } = JSON.parse(stdout);
chai_1.expect(config.options.typeRoots).to.deep.equal([path_1.join(__dirname, '../tests/tsconfig-options/env-typeroots').replace(/\\/g, '/')]);
return done();
});
});
it('should use options from `tsconfig.json`', function (done) {
child_process_1.exec(`${BIN_EXEC} tests/tsconfig-options/log-options.js`, function (err, stdout) {
chai_1.expect(err).to.equal(null);
const { options, config } = JSON.parse(stdout);
chai_1.expect(config.options.typeRoots).to.deep.equal([path_1.join(__dirname, '../tests/tsconfig-options/tsconfig-typeroots').replace(/\\/g, '/')]);
chai_1.expect(config.options.types).to.deep.equal(['tsconfig-tsnode-types']);
chai_1.expect(options.pretty).to.equal(undefined);
chai_1.expect(options.skipIgnore).to.equal(false);
chai_1.expect(options.transpileOnly).to.equal(true);
return done();
});
});
it('should have flags override `tsconfig.json`', function (done) {
child_process_1.exec(`${BIN_EXEC} --skip-ignore --compiler-options "{\\"types\\":[\\"flags-types\\"]}" tests/tsconfig-options/log-options.js`, function (err, stdout) {
chai_1.expect(err).to.equal(null);
const { options, config } = JSON.parse(stdout);
chai_1.expect(config.options.typeRoots).to.deep.equal([path_1.join(__dirname, '../tests/tsconfig-options/tsconfig-typeroots').replace(/\\/g, '/')]);
chai_1.expect(config.options.types).to.deep.equal(['flags-types']);
chai_1.expect(options.pretty).to.equal(undefined);
chai_1.expect(options.skipIgnore).to.equal(true);
chai_1.expect(options.transpileOnly).to.equal(true);
return done();
});
});
it('should have `tsconfig.json` override environment', function (done) {
child_process_1.exec(`${BIN_EXEC} tests/tsconfig-options/log-options.js`, {
env: Object.assign(Object.assign({}, process.env), { TS_NODE_PRETTY: 'true', TS_NODE_SKIP_IGNORE: 'true' })
}, function (err, stdout) {
chai_1.expect(err).to.equal(null);
const { options, config } = JSON.parse(stdout);
chai_1.expect(config.options.typeRoots).to.deep.equal([path_1.join(__dirname, '../tests/tsconfig-options/tsconfig-typeroots').replace(/\\/g, '/')]);
chai_1.expect(config.options.types).to.deep.equal(['tsconfig-tsnode-types']);
chai_1.expect(options.pretty).to.equal(true);
chai_1.expect(options.skipIgnore).to.equal(false);
chai_1.expect(options.transpileOnly).to.equal(true);
return done();
});
});
});
describe('compiler host', function () {
it('should execute cli', function (done) {
child_process_1.exec(`${cmd} --compiler-host tests/hello-world`, function (err, stdout) {
chai_1.expect(err).to.equal(null);
chai_1.expect(stdout).to.equal('Hello, world!\n');
return done();
});
});
it('should give ts error for invalid node_modules', function (done) {
child_process_1.exec(`${cmd} --compiler-host --skip-ignore tests/from-node-modules/from-node-modules`, function (err, stdout) {
if (err === null)
return done('Expected an error');
chai_1.expect(err.message).to.contain('Unable to compile file from external library');
return done();
});
});
});
});
describe('register', function () {
index_1.register({
const registered = index_1.register({
project: PROJECT,

@@ -260,6 +446,55 @@ compilerOptions: {

});
const moduleTestPath = require.resolve('../tests/module');
afterEach(() => {
// Re-enable project after every test.
registered.enabled(true);
});
it('should be able to require typescript', function () {
const m = require('../tests/module');
const m = require(moduleTestPath);
chai_1.expect(m.example('foo')).to.equal('FOO');
});
it('should support dynamically disabling', function () {
delete require.cache[moduleTestPath];
chai_1.expect(registered.enabled(false)).to.equal(false);
chai_1.expect(() => require(moduleTestPath)).to.throw(/Unexpected token/);
delete require.cache[moduleTestPath];
chai_1.expect(registered.enabled()).to.equal(false);
chai_1.expect(() => require(moduleTestPath)).to.throw(/Unexpected token/);
delete require.cache[moduleTestPath];
chai_1.expect(registered.enabled(true)).to.equal(true);
chai_1.expect(() => require(moduleTestPath)).to.not.throw();
delete require.cache[moduleTestPath];
chai_1.expect(registered.enabled()).to.equal(true);
chai_1.expect(() => require(moduleTestPath)).to.not.throw();
});
if (semver.gte(ts.version, '2.7.0')) {
it('should support compiler scopes', function () {
const calls = [];
registered.enabled(false);
const compilers = [
index_1.register({ dir: path_1.join(TEST_DIR, 'scope/a'), scope: true }),
index_1.register({ dir: path_1.join(TEST_DIR, 'scope/b'), scope: true })
];
compilers.forEach(c => {
const old = c.compile;
c.compile = (code, fileName, lineOffset) => {
calls.push(fileName);
return old(code, fileName, lineOffset);
};
});
try {
chai_1.expect(require('../tests/scope/a').ext).to.equal('.ts');
chai_1.expect(require('../tests/scope/b').ext).to.equal('.ts');
}
finally {
compilers.forEach(c => c.enabled(false));
}
chai_1.expect(calls).to.deep.equal([
path_1.join(TEST_DIR, 'scope/a/index.ts'),
path_1.join(TEST_DIR, 'scope/b/index.ts')
]);
delete require.cache[moduleTestPath];
chai_1.expect(() => require(moduleTestPath)).to.throw();
});
}
it('should compile through js and ts', function () {

@@ -286,3 +521,3 @@ const m = require('../tests/complex');

'Error: this is a demo',
` at Foo.bar (${path_1.join(__dirname, '../tests/throw.ts')}:3:18)`
` at Foo.bar (${path_1.join(__dirname, '../tests/throw.ts')}:100:18)`
].join('\n'));

@@ -313,3 +548,3 @@ done();

catch (error) {
chai_1.expect(error.stack).to.contain('SyntaxError: Unexpected token <\n');
chai_1.expect(error.stack).to.contain('SyntaxError: Unexpected token');
}

@@ -321,3 +556,30 @@ chai_1.expect(compiled).to.match(SOURCE_MAP_REGEXP);

});
describe('create', () => {
it('should create generic compiler instances', () => {
const service = index_1.create({ compilerOptions: { target: 'es5' }, skipProject: true });
const output = service.compile('const x = 10', 'test.ts');
chai_1.expect(output).to.contain('var x = 10;');
});
});
if (semver.gte(process.version, '13.0.0')) {
describe('esm', () => {
this.slow(1000);
const cmd = `node --loader ../../esm.mjs`;
it('should compile and execute as ESM', (done) => {
child_process_1.exec(`${cmd} index.ts`, { cwd: path_1.join(__dirname, '../tests/esm') }, function (err, stdout) {
chai_1.expect(err).to.equal(null);
chai_1.expect(stdout).to.equal('foo bar baz biff\n');
return done();
});
});
it('supports --experimental-specifier-resolution=node', (done) => {
child_process_1.exec(`${cmd} --experimental-specifier-resolution=node index.ts`, { cwd: path_1.join(__dirname, '../tests/esm-node-resolver') }, function (err, stdout) {
chai_1.expect(err).to.equal(null);
chai_1.expect(stdout).to.equal('foo bar baz biff\n');
return done();
});
});
});
}
});
//# sourceMappingURL=index.spec.js.map
{
"name": "ts-node",
"version": "8.3.0",
"version": "8.10.2",
"description": "TypeScript execution environment and REPL for node.js, with source map support",

@@ -8,19 +8,32 @@ "main": "dist/index.js",

"bin": {
"ts-node": "dist/bin.js"
"ts-node": "dist/bin.js",
"ts-script": "dist/bin-script-deprecated.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js"
},
"files": [
"dist/",
"dist-raw/",
"register/",
"LICENSE"
"esm.mjs",
"LICENSE",
"tsconfig.schema.json",
"tsconfig.schemastore-schema.json"
],
"scripts": {
"lint": "tslint \"src/**/*.ts\" --project tsconfig.json",
"build": "rimraf dist && tsc",
"lint-fix": "tslint \"src/**/*.ts\" --project tsconfig.json --fix",
"clean": "rimraf dist && rimraf tsconfig.schema.json && rimraf tsconfig.schemastore-schema.json && rimraf tests/ts-node-packed.tgz",
"build": "npm run build-nopack && npm run build-pack",
"build-nopack": "npm run clean && npm run build-tsc && npm run build-configSchema",
"build-tsc": "tsc",
"build-configSchema": "typescript-json-schema --topRef --refs --validationKeywords allOf --out tsconfig.schema.json tsconfig.json TsConfigSchema && node --require ./register ./scripts/create-merged-schema",
"build-pack": "node ./scripts/build-pack.js",
"test-spec": "mocha dist/**/*.spec.js -R spec --bail",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- \"dist/**/*.spec.js\" -R spec --bail",
"test": "npm run build && npm run lint && npm run test-cov",
"prepare": "npm run build"
"prepare": "npm run build-nopack"
},
"engines": {
"node": ">=4.2.0"
"node": ">=6.0.0"
},

@@ -52,22 +65,25 @@ "repository": {

"@types/diff": "^4.0.2",
"@types/mocha": "^5.0.0",
"@types/node": "^12.0.2",
"@types/mocha": "^5.2.7",
"@types/node": "13.13.5",
"@types/proxyquire": "^1.3.28",
"@types/react": "^16.0.2",
"@types/semver": "^6.0.0",
"@types/semver": "^7.1.0",
"@types/source-map-support": "^0.5.0",
"axios": "^0.19.0",
"chai": "^4.0.1",
"istanbul": "^0.4.0",
"mocha": "^6.1.4",
"mocha": "^6.2.2",
"ntypescript": "^1.201507091536.1",
"proxyquire": "^2.0.0",
"react": "^16.0.0",
"rimraf": "^2.5.4",
"semver": "^6.1.0",
"tslint": "^5.11.0",
"tslint-config-standard": "^8.0.1",
"typescript": "^3.2.4"
"rimraf": "^3.0.0",
"semver": "^7.1.3",
"tslint": "^6.1.0",
"tslint-config-standard": "^9.0.0",
"typescript": "3.8.3",
"typescript-json-schema": "^0.42.0",
"util.promisify": "^1.0.1"
},
"peerDependencies": {
"typescript": ">=2.0"
"typescript": ">=2.7"
},

@@ -78,5 +94,5 @@ "dependencies": {

"make-error": "^1.1.1",
"source-map-support": "^0.5.6",
"yn": "^3.0.0"
"source-map-support": "^0.5.17",
"yn": "3.1.1"
}
}

@@ -1,2 +0,2 @@

# ![TypeScript Node](logo.svg)
# ![TypeScript Node](logo.svg?sanitize=true)

@@ -8,4 +8,8 @@ [![NPM version][npm-image]][npm-url]

> TypeScript execution and REPL for node.js, with source map support. **Works with `typescript@>=2.0`**.
> TypeScript execution and REPL for node.js, with source map support. **Works with `typescript@>=2.7`**.
### *Experimental ESM support*
Native ESM support is currently experimental. For usage, limitations, and to provide feedback, see [#1007](https://github.com/TypeStrong/ts-node/issues/1007).
## Installation

@@ -15,8 +19,8 @@

# Locally in your project.
npm install -D typescript
npm install -D ts-node
npm install -D typescript
# Or globally with TypeScript.
npm install -g typescript
npm install -g ts-node
npm install -g typescript
```

@@ -28,2 +32,4 @@

### Shell
```sh

@@ -43,3 +49,9 @@ # Execute a script as `node` + `tsc`.

# Pipe scripts to execute with TypeScript.
echo "console.log('Hello, world!')" | ts-node
echo 'console.log("Hello, world!")' | ts-node
# Equivalent to ts-node --script-mode
ts-node-script scripts.ts
# Equivalent to ts-node --transpile-only
ts-node-transpile-only scripts.ts
```

@@ -49,2 +61,19 @@

### Shebang
```typescript
#!/usr/bin/env ts-node-script
console.log("Hello, world!")
```
`ts-node-script` is recommended because it enables `--script-mode`, discovering `tsconfig.json` relative to the script's location instead of `process.cwd()`. This makes scripts more portable.
Passing CLI arguments via shebang is allowed on Mac but not Linux. For example, the following will fail on Linux:
```
#!/usr/bin/env ts-node --script-mode --transpile-only --files
// This shebang is not portable. It only works on Mac
```
### Programmatic

@@ -56,4 +85,10 @@

#### Developers
**TS Node** exports a `create()` function that can be used to initialize a TypeScript compiler that isn't registered to `require.extensions`, and it uses the same code as `register`.
### Mocha
Mocha 6
```sh

@@ -65,2 +100,8 @@ mocha --require ts-node/register --watch-extensions ts,tsx "test/**/*.{ts,tsx}" [...args]

Mocha 7
```sh
mocha --require ts-node/register --extensions ts,tsx --watch --watch-files src 'tests/**/*.{ts,tsx}' [...args]
```
### Tape

@@ -100,2 +141,8 @@

### IntelliJ (and WebStorm)
Create a new Node.js configuration and add `-r ts-node/register` to "Node parameters."
**Note:** If you are using the `--project <tsconfig.json>` command line argument as per the [Configuration Options](#configuration-options), and want to apply this same behavior when launching in IntelliJ, specify under "Environment Variables": `TS_NODE_PROJECT=<tsconfig.json>`.
## How It Works

@@ -115,2 +162,6 @@

It is resolved relative to `--dir` using [the same search behavior as `tsc`](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html). In `--script-mode`, this is the directory containing the script. Otherwise it is resolved relative to `process.cwd()`, which matches the behavior of `tsc`.
Use `--project` to specify the path to your `tsconfig.json`, ignoring `--dir`.
**Tip**: You can use `ts-node` together with [tsconfig-paths](https://www.npmjs.com/package/tsconfig-paths) to load modules according to the `paths` section in `tsconfig.json`.

@@ -120,3 +171,3 @@

You can set options by passing them before the script path, via programmatic usage or via environment variables.
You can set options by passing them before the script path, via programmatic usage, via `tsconfig.json`, or via environment variables.

@@ -127,14 +178,18 @@ ```sh

**Note:** [`ntypescript`](https://github.com/TypeStrong/ntypescript#readme) is an example of a TypeScript-compatible `compiler`.
### CLI Options
Supports `--print`, `--eval` and `--require` from [node.js CLI options](https://nodejs.org/api/cli.html).
`ts-node` supports `--print` (`-p`), `--eval` (`-e`), `--require` (`-r`) and `--interactive` (`-i`) similar to the [node.js CLI options](https://nodejs.org/api/cli.html).
* `--help` Prints help text
* `--version` Prints version information
* `-h, --help` Prints the help text
* `-v, --version` Prints the version. `-vv` prints node and typescript compiler versions, too
* `-s, --script-mode` Resolve config relative to the directory of the passed script instead of the current directory. Changes default of `--dir`
### CLI and Programmatic Options
_Environment variable denoted in parentheses._
_The name of the environment variable and the option's default value are denoted in parentheses._
* `-T, --transpile-only` Use TypeScript's faster `transpileModule` (`TS_NODE_TRANSPILE_ONLY`, default: `false`)
* `-H, --compiler-host` Use TypeScript's compiler host API (`TS_NODE_COMPILER_HOST`, default: `false`)
* `-I, --ignore [pattern]` Override the path patterns to skip compilation (`TS_NODE_IGNORE`, default: `/node_modules/`)

@@ -145,15 +200,42 @@ * `-P, --project [path]` Path to TypeScript JSON project file (`TS_NODE_PROJECT`)

* `-O, --compiler-options [opts]` JSON object to merge with compiler options (`TS_NODE_COMPILER_OPTIONS`)
* `--files` Load files from `tsconfig.json` on startup (`TS_NODE_FILES`, default: `false`)
* `--dir` Specify working directory for config resolution (`TS_NODE_CWD`, default: `process.cwd()`, or `dirname(scriptPath)` if `--script-mode`)
* `--scope` Scope compiler to files within `cwd` (`TS_NODE_SCOPE`, default: `false`)
* `--files` Load `files`, `include` and `exclude` from `tsconfig.json` on startup (`TS_NODE_FILES`, default: `false`)
* `--pretty` Use pretty diagnostic formatter (`TS_NODE_PRETTY`, default: `false`)
* `--skip-project` Skip project config resolution and loading (`TS_NODE_SKIP_PROJECT`, default: `false`)
* `--skip-ignore` Skip ignore checks (`TS_NODE_SKIP_IGNORE`, default: `false`)
* `--log-error` Logs errors of types instead of exit the process (`TS_NODE_LOG_ERROR`, default: `false`)
* `--emit` Emit output files into `.ts-node` directory (`TS_NODE_EMIT`, default: `false`)
* `--prefer-ts-exts` Re-order file extensions so that TypeScript imports are preferred (`TS_NODE_PREFER_TS_EXTS`, default: `false`)
* `--log-error` Logs TypeScript errors to stderr instead of throwing exceptions (`TS_NODE_LOG_ERROR`, default: `false`)
### Programmatic Only Options
### Programmatic-only Options
* `transformers` An array of transformers to pass to TypeScript
* `readFile` Custom TypeScript-compatible file reading function
* `fileExists` Custom TypeScript-compatible file existence function
* `transformers` `_ts.CustomTransformers | ((p: _ts.Program) => _ts.CustomTransformers)`: An object with transformers or a function that accepts a program and returns an transformers object to pass to TypeScript. Function isn't available with `transpileOnly` flag
* `readFile`: Custom TypeScript-compatible file reading function
* `fileExists`: Custom TypeScript-compatible file existence function
### Options via tsconfig.json
Most options can be specified by a `"ts-node"` object in `tsconfig.json` using their programmatic, camelCase names. For example, to enable `--transpile-only`:
```json
// tsconfig.json
{
"ts-node": {
"transpileOnly": true
},
"compilerOptions": {}
}
```
Our bundled [JSON schema](https://unpkg.com/browse/ts-node@8.8.2/tsconfig.schema.json) lists all compatible options.
## SyntaxError
Any error that is not a `TSError` is from node.js (e.g. `SyntaxError`), and cannot be fixed by TypeScript or `ts-node`. These are runtime issues with your code.
### Import Statements
Current node.js stable releases do not support ES modules. Additionally, `ts-node` does not have the required hooks into node.js to support ES modules. You will need to set `"module": "commonjs"` in your `tsconfig.json` for your code to work.
## Help! My Types Are Missing!

@@ -167,3 +249,3 @@

```
```json
{

@@ -178,3 +260,3 @@ "compilerOptions": {

```
```text
<project_root>/

@@ -189,3 +271,3 @@ -- tsconfig.json

```
```typescript
declare module '<module_name>' {

@@ -216,3 +298,3 @@ // module definitions go here

**Tip:** If you _must_ use `files`, enable `--files` flags or set `TS_NODE_FILES=true`.
**Tip:** If you _must_ use `files`, `include`, or `exclude`, enable `--files` flags or set `TS_NODE_FILES=true`.

@@ -219,0 +301,0 @@ ## Watching and Restarting

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc