diff --git a/api-extractor/ts-node.api.md b/api-extractor/ts-node.api.md index 6d42f4a42..1d7ad1289 100644 --- a/api-extractor/ts-node.api.md +++ b/api-extractor/ts-node.api.md @@ -28,6 +28,7 @@ export interface CreateOptions { emit?: boolean; esm?: boolean; experimentalReplAwait?: boolean; + preprocessor?: string; experimentalSpecifierResolution?: 'node' | 'explicit'; experimentalTsImportSpecifiers?: boolean; // (undocumented) diff --git a/package.json b/package.json index 8f3f4464e..b17064872 100644 --- a/package.json +++ b/package.json @@ -162,6 +162,7 @@ "arg": "^4.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", + "pretty-repl": "^3.1.1", "v8-compile-cache-lib": "^3.0.1" }, "prettier": { diff --git a/src/bin.ts b/src/bin.ts index 542fb6841..4911d3497 100644 --- a/src/bin.ts +++ b/src/bin.ts @@ -140,6 +140,7 @@ function parseArgv(argv: string[], entrypointArgs: Record) { '--scope': Boolean, '--scopeDir': String, '--noExperimentalReplAwait': Boolean, + '--preprocessor': String, '--experimentalSpecifierResolution': String, // Aliases. @@ -218,6 +219,7 @@ function parseArgv(argv: string[], entrypointArgs: Record) { '--scope': scope = undefined, '--scopeDir': scopeDir = undefined, '--noExperimentalReplAwait': noExperimentalReplAwait, + '--preprocessor': preprocessor, '--experimentalSpecifierResolution': experimentalSpecifierResolution, '--esm': esm, _: restArgs, @@ -257,6 +259,7 @@ function parseArgv(argv: string[], entrypointArgs: Record) { scope, scopeDir, noExperimentalReplAwait, + preprocessor, experimentalSpecifierResolution, esm, }; @@ -278,6 +281,7 @@ Options: --esm Bootstrap with the ESM loader, enabling full ESM support --swc Use the faster swc transpiler + --preprocessor Runs at the start of CLI -h, --help Print CLI usage -v, --version Print module version information. -vvv to print additional information @@ -355,6 +359,7 @@ function phase3(payload: BootstrapState) { scopeDir, esm, experimentalSpecifierResolution, + preprocessor, } = payload.parseArgvResult; const { cwd } = payload.phase2Result!; @@ -398,6 +403,7 @@ function phase3(payload: BootstrapState) { esm, experimentalSpecifierResolution: experimentalSpecifierResolution as ExperimentalSpecifierResolution, + preprocessor, }); // If ESM is enabled through the parsed tsconfig, stage4 should be run in a child diff --git a/src/configuration.ts b/src/configuration.ts index c59536986..0dd4f6c8a 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -401,6 +401,7 @@ function filterRecognizedTsConfigTsNodeOptions(jsonObject: any): { scopeDir, moduleTypes, experimentalReplAwait, + preprocessor, swc, experimentalResolver, esm, @@ -414,6 +415,7 @@ function filterRecognizedTsConfigTsNodeOptions(jsonObject: any): { compilerOptions, emit, experimentalReplAwait, + preprocessor, files, ignore, ignoreDiagnostics, diff --git a/src/index.ts b/src/index.ts index 58a47cc9e..6b3d22cb6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -301,6 +301,10 @@ export interface CreateOptions { * to get default, automatic behavior. */ experimentalReplAwait?: boolean; + /** + * Runs at the start of CLI. + */ + preprocessor?: string; /** * Override certain paths to be compiled and executed as CommonJS or ECMAScript modules. * When overridden, the tsconfig "module" and package.json "type" fields are overridden, and diff --git a/src/repl.ts b/src/repl.ts index 7b7c38367..f1221555c 100644 --- a/src/repl.ts +++ b/src/repl.ts @@ -1,13 +1,9 @@ import type * as _diff from 'diff'; import { homedir } from 'os'; import { join } from 'path'; -import { - Recoverable, - ReplOptions, - REPLServer, - start as nodeReplStart, -} from 'repl'; -import { Context, createContext, Script } from 'vm'; +import { Recoverable, ReplOptions, REPLServer } from 'repl'; +import { start as nodeReplStart } from 'pretty-repl'; +import { Context, Script } from 'vm'; import { Service, CreateOptions, TSError, env } from './index'; import { readFileSync, statSync } from 'fs'; import { Console } from 'console'; @@ -386,7 +382,7 @@ export function createRepl(options: CreateReplOptions = {}) { eval: nodeEval, useGlobal: true, ...optionsOverride, - }); + }) as REPLServer; nodeReplServer = repl; context = repl.context; @@ -421,6 +417,13 @@ export function createRepl(options: CreateReplOptions = {}) { .map((name) => `declare import ${name} = require('${name}')`) .join(';')}\n`; } + if (service!.options.preprocessor) { + const preprocessorContent = readFileSync( + service!.options.preprocessor, + 'utf8' + ); + state.input += `${preprocessorContent}; void 0;\n`; + } } reset(); diff --git a/src/test/helpers/preprocessor.ts b/src/test/helpers/preprocessor.ts new file mode 100644 index 000000000..ff1442213 --- /dev/null +++ b/src/test/helpers/preprocessor.ts @@ -0,0 +1,5 @@ +export const PreprocessorEnabled = true; + +export function isPreprocessorEnabled() { + return PreprocessorEnabled; +} diff --git a/yarn.lock b/yarn.lock index 359b2fa03..0a9b40db5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -924,7 +924,7 @@ __metadata: languageName: node linkType: hard -"ansi-regex@npm:^5.0.1": +"ansi-regex@npm:^5.0.0, ansi-regex@npm:^5.0.1": version: 5.0.1 resolution: "ansi-regex@npm:5.0.1" checksum: 2aa4bb54caf2d622f1afdad09441695af2a83aa3fe8b8afa581d205e57ed4261c183c4d3877cee25794443fde5876417d859c108078ab788d6af7e4fe52eb66b @@ -1261,7 +1261,17 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0": +"chalk@npm:^3.0.0": + version: 3.0.0 + resolution: "chalk@npm:3.0.0" + dependencies: + ansi-styles: ^4.1.0 + supports-color: ^7.1.0 + checksum: 8e3ddf3981c4da405ddbd7d9c8d91944ddf6e33d6837756979f7840a29272a69a5189ecae0ff84006750d6d1e92368d413335eab4db5476db6e6703a1d1e0505 + languageName: node + linkType: hard + +"chalk@npm:^4.0.0, chalk@npm:^4.1.1": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -1676,6 +1686,17 @@ __metadata: languageName: node linkType: hard +"emphasize@npm:^3.0.0": + version: 3.0.0 + resolution: "emphasize@npm:3.0.0" + dependencies: + chalk: ^3.0.0 + highlight.js: ~9.12.0 + lowlight: ~1.9.0 + checksum: fef6b2ff83edc12863fa85dc4e0dbf075fbc3de8cc8cb67bdc65c7967e5e49057d6f58fed4c199c91720aba11317b21a1c1a7b0a2a845bd4b9e180586ed13f4a + languageName: node + linkType: hard + "encoding@npm:^0.1.13": version: 0.1.13 resolution: "encoding@npm:0.1.13" @@ -1808,6 +1829,15 @@ __metadata: languageName: node linkType: hard +"fault@npm:^1.0.2": + version: 1.0.4 + resolution: "fault@npm:1.0.4" + dependencies: + format: ^0.2.0 + checksum: 5ac610d8b09424e0f2fa8cf913064372f2ee7140a203a79957f73ed557c0e79b1a3d096064d7f40bde8132a69204c1fe25ec23634c05c6da2da2039cff26c4e7 + languageName: node + linkType: hard + "figures@npm:^5.0.0": version: 5.0.0 resolution: "figures@npm:5.0.0" @@ -1888,6 +1918,13 @@ __metadata: languageName: node linkType: hard +"format@npm:^0.2.0": + version: 0.2.2 + resolution: "format@npm:0.2.2" + checksum: 646a60e1336250d802509cf24fb801e43bd4a70a07510c816fa133aa42cdbc9c21e66e9cc0801bb183c5b031c9d68be62e7fbb6877756e52357850f92aa28799 + languageName: node + linkType: hard + "fromentries@npm:^1.2.0": version: 1.3.2 resolution: "fromentries@npm:1.3.2" @@ -2078,6 +2115,13 @@ __metadata: languageName: node linkType: hard +"highlight.js@npm:~9.12.0": + version: 9.12.0 + resolution: "highlight.js@npm:9.12.0" + checksum: 46b357bdaac95da903736222f1662b1e1423d35c954407bf18ed35f9f2aa87947e28d83cada2a887105d0e95990199ae11bd8a448b7bf0bb3331b9efcd136037 + languageName: node + linkType: hard + "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -2609,6 +2653,16 @@ __metadata: languageName: node linkType: hard +"lowlight@npm:~1.9.0": + version: 1.9.2 + resolution: "lowlight@npm:1.9.2" + dependencies: + fault: ^1.0.2 + highlight.js: ~9.12.0 + checksum: a83edeab0a696733e88bde2e55e407227189969fa2084701b69fbebf38f1763584f802cd66df2c5834e7e56533b1e81f27d610d60868202215b1de9d3a77c149 + languageName: node + linkType: hard + "lru-cache@npm:^6.0.0": version: 6.0.0 resolution: "lru-cache@npm:6.0.0" @@ -3223,6 +3277,18 @@ __metadata: languageName: node linkType: hard +"pretty-repl@npm:^3.1.1": + version: 3.1.1 + resolution: "pretty-repl@npm:3.1.1" + dependencies: + ansi-regex: ^5.0.0 + chalk: ^4.1.1 + emphasize: ^3.0.0 + strip-ansi: ^6.0.0 + checksum: f4e54e079979cb7f536fd1907262fff39dc15ab13a366335dfcad15474dc3e8f41967bd5cb1dbe406281b1770b6fb2a43201710f5c9f9ac7986693e629df88e4 + languageName: node + linkType: hard + "process-on-spawn@npm:^1.0.0": version: 1.0.0 resolution: "process-on-spawn@npm:1.0.0" @@ -3832,6 +3898,7 @@ __metadata: make-error: ^1.1.1 nyc: ^15.0.1 outdent: ^0.8.0 + pretty-repl: ^3.1.1 proper-lockfile: ^4.1.2 proxyquire: ^2.0.0 rimraf: ^3.0.0