├── .editorconfig ├── .git-blame-ignore-revs ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── config.yml │ └── feature-request.md └── workflows │ ├── continuous-integration.yml │ ├── e2e-git-installs.yml │ └── website.yml ├── .gitignore ├── .vscode ├── launch.json ├── tasks.json └── tests.code-snippets ├── .yarn ├── plugins │ └── @yarnpkg │ │ └── plugin-compat.cjs └── releases │ └── yarn-3.4.1.cjs ├── .yarnrc.yml ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── api-extractor.json ├── api-extractor └── ts-node.api.md ├── ava.config.cjs ├── child-loader.mjs ├── codecov.yml ├── development-docs ├── README.md ├── isExternalLibraryImport.md ├── nodenextNode16.md ├── release-template.md ├── repl-api.md ├── rootDirOutDirMapping.md ├── test-style-guide.md └── yarnPnpInterop.md ├── dist-raw ├── NODE-LICENSE.md ├── README.md ├── node-internal-constants.js ├── node-internal-errors.js ├── node-internal-modules-cjs-helpers.js ├── node-internal-modules-cjs-loader.js ├── node-internal-modules-esm-get_format.js ├── node-internal-modules-esm-resolve.js ├── node-internal-modules-package_json_reader.js ├── node-internal-repl-await.js ├── node-internalBinding-fs.js ├── node-nativemodule.js ├── node-options.js ├── node-primordials.js └── runmain-hack.js ├── dprint.json ├── esm-usage-example ├── README.md ├── bar.ts ├── foo.ts ├── index.js ├── package.json └── tsconfig.json ├── esm.mjs ├── esm └── transpile-only.mjs ├── justfile ├── logo-icon.svg ├── logo.svg ├── node10 └── tsconfig.json ├── node12 └── tsconfig.json ├── node14 └── tsconfig.json ├── node16 └── tsconfig.json ├── node18 └── tsconfig.json ├── node20 └── tsconfig.json ├── nyc.config.js ├── package.json ├── raw ├── README.md ├── download-and-compare.sh ├── node-internal-errors-2d5d77306f6dff9110c1f77fefab25f973415770-stripped.js ├── node-internal-errors-2d5d77306f6dff9110c1f77fefab25f973415770.js ├── node-internal-errors-b533fb3508009e5f567cc776daba8fbf665386a6-stripped.js ├── node-internal-errors-b533fb3508009e5f567cc776daba8fbf665386a6.js ├── node-internal-modules-cjs-helpers-v17.0.1-stripped.js ├── node-internal-modules-cjs-helpers-v17.0.1.js ├── node-internal-modules-cjs-loader-2d5d77306f6dff9110c1f77fefab25f973415770.js ├── node-internal-modules-cjs-loader-v15.3.0-stripped.js ├── node-internal-modules-cjs-loader-v15.3.0.js ├── node-internal-modules-cjs-loader-v17.0.1-stripped.js ├── node-internal-modules-cjs-loader-v17.0.1.js ├── node-internal-modules-esm-get_format-v15.3.0.js ├── node-internal-modules-esm-resolve-v13.12.0.js ├── node-internal-modules-esm-resolve-v15.3.0-stripped.js ├── node-internal-modules-esm-resolve-v15.3.0.js ├── node-internal-modules-package_json_reader-v15.3.0.js ├── node-internal-repl-await-88799930794045795e8abac874730f9eba7e2300.js └── node-internal-repl-await-v17.0.0.js ├── register ├── files.js ├── index.js ├── transpile-only.js └── type-check.js ├── screenshot.png ├── scripts ├── build-manifest.mjs ├── build-pack.js ├── create-merged-schema.ts ├── node-nightly.sh ├── prepack.mjs └── update-schemastore-schema-with-compiler-options.ts ├── src ├── bin-cwd.ts ├── bin-esm.ts ├── bin-script.ts ├── bin-transpile.ts ├── bin.ts ├── child │ ├── argv-payload.ts │ ├── child-entrypoint.ts │ ├── child-loader.ts │ ├── child-require.ts │ └── spawn-child.ts ├── cjs-resolve-hooks.ts ├── configuration.ts ├── esm.ts ├── file-extensions.ts ├── index.ts ├── module-type-classifier.ts ├── node-module-type-classifier.ts ├── node-resolver-functions.ts.disabled ├── repl.ts ├── resolver-functions.ts ├── test │ ├── ci-node-and-ts-versions.spec.ts │ ├── configuration │ │ ├── resolution.spec.ts │ │ └── tsnode-opts-from-tsconfig.spec.ts │ ├── create.spec.ts │ ├── diagnostics.spec.ts │ ├── esm-loader.spec.ts │ ├── helpers │ │ ├── command-lines.ts │ │ ├── ctx-tmp-dir.ts │ │ ├── ctx-ts-node.ts │ │ ├── exec.ts │ │ ├── index.ts │ │ ├── misc.ts │ │ ├── paths.ts │ │ ├── reset-node-environment.ts │ │ └── version-checks.ts │ ├── index.spec.ts │ ├── module-node │ │ ├── 1778.spec.ts │ │ └── module-node.spec.ts │ ├── package.spec.ts │ ├── pluggable-dep-resolution.spec.ts │ ├── register.spec.ts │ ├── regression.spec.ts │ ├── reminders.spec.ts │ ├── remove-env-var-force-color.js │ ├── repl │ │ ├── helpers │ │ │ ├── ctx-repl.ts │ │ │ ├── macros.ts │ │ │ └── misc.ts │ │ ├── node-repl-tla.ts │ │ ├── repl-environment.spec.ts │ │ └── repl.spec.ts │ ├── resolver.spec.ts │ ├── sourcemaps.spec.ts │ ├── test-loader.d.ts │ ├── test-loader.mjs │ ├── testlib.ts │ ├── transpile-only.spec.ts │ ├── transpilers.spec.ts │ ├── ts-import-specifiers.spec.ts │ └── tsconfig-bases.spec.ts ├── transpilers │ ├── swc.ts │ └── types.ts ├── ts-compiler-types.ts ├── ts-internals.ts ├── ts-transpile-module.ts ├── tsconfig-schema.ts ├── tsconfigs.ts └── util.ts ├── tests ├── 1488 │ ├── index.js │ ├── package.json │ └── tsconfig.json ├── 1778 │ ├── index.ts │ ├── node_modules │ │ └── foo │ │ │ ├── cjs │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ └── package.json │ │ │ ├── esm │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ │ └── package.json │ ├── package.json │ └── tsconfig.json ├── 1996 │ ├── empty.ts │ ├── index.ts │ ├── transpiler.js │ ├── tsconfig.custom-transpiler.json │ └── tsconfig.json ├── 2076 │ ├── node_modules │ │ └── custom-tsconfig │ │ │ └── tsconfig.json │ └── tsconfig.json ├── .gitignore ├── .yarnrc.yml ├── allow-js │ ├── run.js │ └── with-jsx.jsx ├── child-process.ts ├── compiler-error.ts ├── complex │ ├── example.js │ ├── foo.ts │ └── index.ts ├── custom-types.ts ├── cwd-and-script-mode │ ├── a │ │ ├── index.ts │ │ └── tsconfig.json │ └── b │ │ ├── index.ts │ │ └── tsconfig.json ├── emit-compiled.ts ├── emit-skipped-fallback │ ├── outside-rootDir │ │ └── foo.js │ └── tsconfig.json ├── empty.ts ├── env.ts ├── esm-child-process │ ├── process-forking-js │ │ ├── index.ts │ │ ├── package.json │ │ ├── tsconfig.json │ │ └── worker.js │ ├── process-forking-ts-abs │ │ ├── index.ts │ │ ├── package.json │ │ ├── subfolder │ │ │ └── worker.ts │ │ └── tsconfig.json │ ├── process-forking-ts │ │ ├── index.ts │ │ ├── package.json │ │ ├── subfolder │ │ │ └── worker.ts │ │ └── tsconfig.json │ ├── via-flag │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json │ └── via-tsconfig │ │ ├── index.ts │ │ ├── package.json │ │ ├── sleep.ts │ │ └── tsconfig.json ├── esm-custom-loader │ ├── index.ts │ ├── loader.mjs │ ├── package.json │ └── tsconfig.json ├── esm-err-require-esm │ ├── esm-package │ │ ├── loaded-as.ts │ │ └── package.json │ └── index.js ├── esm-import-assertions │ ├── car.json │ ├── importJson.ts │ ├── package.json │ └── tsconfig.json ├── esm-import-cache │ ├── index.ts │ ├── log1.ts │ ├── log2.ts │ ├── package.json │ └── tsconfig.json ├── esm-import-http-url │ └── index.mjs ├── esm-loader-context │ ├── index.mjs │ ├── jsonModuleA.json │ ├── jsonModuleB.json │ ├── loader.mjs │ ├── moduleA.mjs │ ├── moduleB.mjs │ ├── moduleC.mjs │ └── moduleD.mjs ├── esm-loader-entrypoint-cjs-fallback │ ├── extensionless-entrypoint │ └── relies-upon-cjs-resolution │ │ └── index.js ├── esm-node-resolver │ ├── bar │ │ └── index.ts │ ├── baz.js │ ├── biff.jsx │ ├── foo.ts │ ├── index.ts │ ├── node_modules │ │ └── libfoo │ │ │ ├── entrypoint.js │ │ │ ├── index.d.ts │ │ │ └── package.json │ ├── package.json │ └── tsconfig.json ├── esm-transpile-only │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── esm │ ├── bar.ts │ ├── baz.js │ ├── biff.jsx │ ├── foo.ts │ ├── index.ts │ ├── node_modules │ │ └── libfoo │ │ │ ├── entrypoint.js │ │ │ ├── index.d.ts │ │ │ └── package.json │ ├── package.json │ ├── throw error.ts │ └── tsconfig.json ├── from-node-modules │ ├── from-node-modules.ts │ ├── node_modules │ │ └── external │ │ │ ├── index.ts │ │ │ ├── javascript-module-imported-externally │ │ │ └── index.ts │ │ │ ├── javascript-module-imported-internally │ │ │ └── index.ts │ │ │ ├── javascript-module-required-externally │ │ │ └── index.ts │ │ │ ├── javascript-module-required-internally │ │ │ └── index.ts │ │ │ ├── typescript-module-imported-externally │ │ │ └── index.ts │ │ │ ├── typescript-module-imported-internally │ │ │ └── index.ts │ │ │ ├── typescript-module-required-externally │ │ │ └── index.ts │ │ │ └── typescript-module-required-internally │ │ │ └── index.ts │ └── tsconfig.json ├── hello-world.ts ├── import-order │ ├── compiled.js │ ├── compiled.ts │ ├── defined.d.ts │ ├── defined.js │ └── importer.ts ├── issue-884 │ ├── index-2.ts │ ├── index.ts │ └── tsconfig.json ├── issue-986 │ ├── index.ts │ ├── tsconfig.json │ └── types.ts ├── jsx-react.tsx ├── legacy-source-map-support-interop │ └── index.ts ├── local-types-node │ └── node_modules │ │ └── @types │ │ └── node │ │ ├── index.d.ts │ │ └── package.json ├── main-realpath │ ├── symlink │ │ ├── symlink.tsx │ │ └── tsconfig.json │ └── target │ │ ├── target.tsx │ │ └── tsconfig.json ├── maxnodemodulesjsdepth-scoped │ ├── index.ts │ ├── node_modules │ │ └── @scoped │ │ │ ├── a │ │ │ ├── has-semantic-error.js │ │ │ └── index.js │ │ │ └── b │ │ │ ├── has-semantic-error.js │ │ │ └── index.js │ ├── other.ts │ └── tsconfig.json ├── maxnodemodulesjsdepth │ ├── index.ts │ ├── node_modules │ │ └── external │ │ │ ├── has-semantic-error.js │ │ │ └── index.js │ ├── other.ts │ └── tsconfig.json ├── module-types │ ├── override-to-cjs │ │ ├── package.json │ │ ├── src │ │ │ ├── cjs-subdir │ │ │ │ ├── esm-exception.ts │ │ │ │ └── index.ts │ │ │ └── should-be-esm.ts │ │ ├── test-webpack-config.cjs │ │ ├── test.cjs │ │ ├── test.mjs │ │ ├── tsconfig-swc.json │ │ ├── tsconfig.json │ │ └── webpack.config.ts │ └── override-to-esm │ │ ├── package.json │ │ ├── src │ │ ├── esm-subdir │ │ │ ├── cjs-exception.ts │ │ │ └── index.ts │ │ └── should-be-cjs.ts │ │ ├── test.cjs │ │ ├── test.mjs │ │ ├── tsconfig-swc.json │ │ └── tsconfig.json ├── module.ts ├── package.json ├── pluggable-dep-resolution │ ├── node_modules │ │ ├── @swc │ │ │ ├── core │ │ │ │ └── index.js │ │ │ └── wasm │ │ │ │ └── index.js │ │ ├── custom-compiler │ │ │ └── index.js │ │ ├── custom-swc │ │ │ └── index.js │ │ ├── custom-transpiler │ │ │ └── index.js │ │ └── shared-config │ │ │ ├── node_modules │ │ │ ├── @swc │ │ │ │ ├── core │ │ │ │ │ └── index.js │ │ │ │ └── wasm │ │ │ │ │ └── index.js │ │ │ ├── custom-compiler │ │ │ │ └── index.js │ │ │ ├── custom-swc │ │ │ │ └── index.js │ │ │ └── custom-transpiler │ │ │ │ └── index.js │ │ │ ├── tsconfig-custom-compiler.json │ │ │ ├── tsconfig-custom-transpiler.json │ │ │ ├── tsconfig-swc-core.json │ │ │ ├── tsconfig-swc-custom-backend.json │ │ │ ├── tsconfig-swc-wasm.json │ │ │ └── tsconfig-swc.json │ ├── tsconfig-custom-compiler.json │ ├── tsconfig-custom-transpiler.json │ ├── tsconfig-extend-custom-compiler.json │ ├── tsconfig-extend-custom-transpiler.json │ ├── tsconfig-extend-swc-core.json │ ├── tsconfig-extend-swc-custom-backend.json │ ├── tsconfig-extend-swc-wasm.json │ ├── tsconfig-extend-swc.json │ ├── tsconfig-swc-core.json │ ├── tsconfig-swc-custom-backend.json │ ├── tsconfig-swc-wasm.json │ └── tsconfig-swc.json ├── recursive-fork │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── repl-ignored-diagnostics │ └── index.ts ├── repl-in-esm-package │ ├── package.json │ └── tsconfig.json ├── repl │ ├── script.js │ └── tla-import.ts ├── require-cache.ts ├── resolver │ ├── README.md │ ├── package.json │ └── test.sh ├── scope │ ├── a │ │ ├── index.ts │ │ ├── log.ts │ │ └── tsconfig.json │ ├── b │ │ ├── index.ts │ │ └── tsconfig.json │ └── c │ │ ├── config │ │ ├── index.ts │ │ ├── scopedir │ │ │ └── index.ts │ │ └── tsconfig.json │ │ ├── index.js │ │ └── scopedir │ │ └── index.ts ├── signals.ts ├── spy-swc-transpiler.js ├── throw error react tsx.tsx ├── throw error.ts ├── transpile-only-swc-native-esm │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── transpile-only-swc-shorthand-via-tsconfig │ ├── index.ts │ └── tsconfig.json ├── transpile-only-swc-via-tsconfig │ ├── index.ts │ └── tsconfig.json ├── transpile-only-swc │ ├── index.ts │ └── tsconfig.json ├── ts45-ext │ ├── ext-cts │ │ ├── index.cts │ │ └── tsconfig.json │ └── ext-mts │ │ ├── entrypoint.mjs │ │ ├── index.mts │ │ └── tsconfig.json ├── tsconfig-bases │ ├── node14 │ │ └── tsconfig.json │ ├── node16 │ │ └── tsconfig.json │ ├── node18 │ │ └── tsconfig.json │ └── node20 │ │ └── tsconfig.json ├── tsconfig-extends-multiple │ ├── a │ │ ├── require-hook-from-a.js │ │ └── tsconfig.json │ ├── b │ │ └── tsconfig.json │ ├── c │ │ └── tsconfig.json │ ├── d │ │ └── tsconfig.json │ ├── empty.ts │ ├── node_modules │ │ └── transpiler-from-c │ │ │ └── index.js │ └── tsconfig.json ├── tsconfig-extends │ ├── other │ │ ├── require-hook.js │ │ └── tsconfig.json │ └── tsconfig.json ├── tsconfig-options │ ├── log-options1.js │ ├── log-options2.js │ ├── required1.js │ ├── required2.js │ └── tsconfig.json ├── tsconfig-transpile-only.json ├── tsconfig.json ├── typings │ └── does-not-exist │ │ └── index.d.ts ├── with-jsx.tsx ├── working-dir │ ├── cjs │ │ └── index.ts │ ├── esm │ │ ├── index.ts │ │ ├── package.json │ │ └── tsconfig.json │ ├── forking │ │ ├── index.ts │ │ └── subfolder │ │ │ └── worker.ts │ └── tsconfig.json └── yarn.lock ├── transpilers ├── swc-experimental.js └── swc.js ├── tsconfig.build-dist-raw.json ├── tsconfig.build-dist.json ├── tsconfig.build-schema.json ├── tsconfig.json ├── tsdoc.json ├── website ├── .gitignore ├── README.md ├── babel.config.js ├── docs │ ├── api.md │ ├── commonjs-vs-native-ecmascript-modules.md │ ├── compilers.md │ ├── configuration.md │ ├── how-it-works.md │ ├── installation.md │ ├── module-type-overrides.md │ ├── options-table.md │ ├── options.md │ ├── overview.md │ ├── paths.md │ ├── performance.md │ ├── recipes │ │ ├── ava.md │ │ ├── gulp.md │ │ ├── intellij.md │ │ ├── mocha.md │ │ ├── npx-and-yarn-dlx.md │ │ ├── other.md │ │ ├── tape.md │ │ ├── visual-studio-code.md │ │ └── watching-and-restarting.md │ ├── scope.md │ ├── swc.md │ ├── transpilers.md │ ├── troubleshooting.md │ ├── types.md │ └── usage.md ├── docusaurus.config.js ├── package.json ├── readme-sources │ ├── license.md │ └── prefix.md ├── scripts │ └── build-readme.mjs ├── sidebars.js ├── src │ ├── css │ │ └── custom.css │ ├── pages │ │ ├── index.js │ │ └── styles.module.css │ └── theme │ │ └── DocBreadcrumbs │ │ ├── index.tsx │ │ └── styles.module.css ├── static │ ├── .nojekyll │ └── img │ │ ├── favicon.ico │ │ ├── favicon │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── browserconfig.xml │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ ├── html_code.html │ │ ├── mstile-150x150.png │ │ ├── safari-pinned-tab.svg │ │ └── site.webmanifest │ │ ├── logo-icon.svg │ │ ├── logo.svg │ │ ├── opengraph.pdn │ │ ├── opengraph.png │ │ ├── screenshot.png │ │ ├── undraw_docusaurus_mountain.svg │ │ ├── undraw_docusaurus_react.svg │ │ └── undraw_docusaurus_tree.svg ├── types │ └── lib_greeter.ts └── yarn.lock └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | # This also tells github.com how wide to render tabs 7 | indent_size = 2 8 | indent_style = space 9 | end_of_line = lf 10 | charset = utf-8 11 | trim_trailing_whitespace = true 12 | insert_final_newline = true 13 | 14 | [{package.json,*.yml,dist-raw/**}] 15 | # In case we switch to tabs above, these must still be spaces 16 | indent_style = space 17 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Prettier formatting 2 | 9d05cb684fc3a6e492832100a125ea07d1cc98c5 3 | 7ff608d1a0f7160e7776c34d7a146c8cc90d76ac 4 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | raw/* linguist-vendored 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [blakeembrey, cspotcode] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'Bug report' 3 | about: 'Create a report to help us improve' 4 | 5 | --- 6 | 7 | ### Search Terms 8 | 9 | 10 | 11 | 16 | 17 | ### Expected Behavior 18 | 19 | 20 | 21 | ### Actual Behavior 22 | 23 | 24 | 25 | ### Steps to reproduce the problem 26 | 27 | 28 | 29 | ### Minimal reproduction 30 | 31 | 32 | 33 | 41 | 42 | ### Specifications 43 | 44 | 45 | * ts-node version: 46 | * node version: 47 | * TypeScript version: 48 | * tsconfig.json, if you're using one: 49 | ``` 50 | {} 51 | ``` 52 | * package.json: 53 | ``` 54 | {} 55 | ``` 56 | * Operating system and version: 57 | * If Windows, are you using WSL or WSL2?: 58 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | contact_links: 3 | - 4 | name: Question 5 | about: "Please ask and answer usage questions in our Discussion forum." 6 | url: "https://github.com/TypeStrong/ts-node/discussions" 7 | - 8 | name: Chat 9 | about: "Alternatively, ask on the TypeScript Community Discord." 10 | url: "https://discord.gg/3rBctmf3dP" 11 | - 12 | name: "Help! My Types Are Missing!" 13 | about: "This is likely a configuration problem. Check our README" 14 | url: "https://typestrong.org/ts-node/docs/troubleshooting#missing-types" 15 | - 16 | name: "TSError or SyntaxError" 17 | about: "These errors come from TypeScript and node, respectively. Use Discussions or Discord for usage and configuration help." 18 | url: "https://typestrong.org/ts-node/docs/troubleshooting" 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 'Feature request' 3 | about: 'Suggest an idea for this project' 4 | 5 | --- 6 | 7 | ### Desired Behavior 8 | 9 | 10 | 11 | ### Is this request related to a problem? 12 | 13 | 14 | 15 | 16 | 17 | ### Alternatives you've considered 18 | 19 | 20 | 21 | ### Additional context 22 | 23 | 24 | -------------------------------------------------------------------------------- /.github/workflows/website.yml: -------------------------------------------------------------------------------- 1 | name: Publish website 2 | on: 3 | # branches pushed by collaborators 4 | push: 5 | branches: 6 | - docs 7 | permissions: {} 8 | jobs: 9 | build: 10 | permissions: 11 | contents: write 12 | name: Build & Deploy 13 | runs-on: ubuntu-20.04 14 | steps: 15 | # checkout code 16 | - uses: actions/checkout@v2 17 | # install node 18 | - name: Use Node.js 18 19 | uses: actions/setup-node@v3 20 | with: 21 | node-version: 18 22 | # Render typedoc 23 | - run: npm install && npx typedoc 24 | # Render docusaurus and deploy website 25 | - run: | 26 | set -euo pipefail 27 | git config --global user.name "GitHub Action" 28 | git config --global user.email "github-action@users.noreply.github.com" 29 | cd website 30 | yarn 31 | yarn deploy 32 | env: 33 | GIT_USER: ${{ github.actor }} 34 | GIT_PASS: ${{ secrets.GITHUB_TOKEN }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | /tests/node_modules/ 3 | /.nyc_output/ 4 | /coverage/ 5 | .DS_Store 6 | npm-debug.log 7 | /dist/ 8 | /tsconfig.schema.json 9 | /tsconfig.schemastore-schema.json 10 | /.idea/ 11 | /.vscode/* 12 | !/.vscode/launch.json 13 | /website/static/api 14 | /tsconfig.tsbuildinfo 15 | /temp 16 | /tmp 17 | /yarn-error.log 18 | /.yarn/install-state.gz 19 | /tests/.yarn/install-state.gz 20 | /tests/.yarn/cache 21 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Debug AVA test file", 5 | "type": "node", 6 | "request": "launch", 7 | "preLaunchTask": "npm: pre-debug", 8 | "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/ava", 9 | "program": "${file}", 10 | "outputCapture": "std", 11 | "skipFiles": [ 12 | "/**/*.js" 13 | ] 14 | }, 15 | { 16 | "name": "Debug resolver test", 17 | "type": "pwa-node", 18 | "request": "launch", 19 | "cwd": "${workspaceFolder}/tests/tmp/resolver-0029-preferSrc-typeModule-allowJs-skipIgnore-experimentalSpecifierResolutionNode", 20 | "runtimeArgs": [ 21 | "--loader", 22 | "../../../esm.mjs" 23 | ], 24 | "program": "./src/entrypoint-0000-src-to-src.cjs" 25 | }, 26 | { 27 | "name": "Debug Example: running a test fixture against local ts-node/esm loader", 28 | "type": "pwa-node", 29 | "request": "launch", 30 | "cwd": "${workspaceFolder}/tests/esm", 31 | "runtimeArgs": [ 32 | "--loader", 33 | "../../ts-node/esm" 34 | ], 35 | "program": "throw error.ts", 36 | "outputCapture": "std", 37 | "skipFiles": [ 38 | "/**/*.js" 39 | ] 40 | } 41 | ] 42 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": [ 3 | { 4 | "type": "npm", 5 | "script": "pre-debug", 6 | "problemMatcher": [ 7 | "$tsc" 8 | ], 9 | "label": "npm: pre-debug", 10 | "detail": "npm run build-tsc && npm run build-pack" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /.vscode/tests.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "Test: macro": { 3 | "prefix": "macro", 4 | "body": [ 5 | "const macro = test.macro(($1) => async (t) => {", 6 | " $0", 7 | "});" 8 | ] 9 | }, 10 | "Test: macro w/title": { 11 | "prefix": "macroTitle", 12 | "body": [ 13 | "const macro = test.macro(($1) => [", 14 | " (given) => given,", 15 | " async (t) => {", 16 | " $0", 17 | " }", 18 | "]);" 19 | ] 20 | }, 21 | "Test: suite": { 22 | "prefix": "suite", 23 | "body": [ 24 | "test.suite(\"$1\", (${2|test,{context},{contextEach}|}) => {", 25 | " ${2/(test$)|(\\{context\\}$)|(\\{contextEach\\}$)/${2:+const test = context(}${3:+const test = contextEach(}/m}$0", 26 | "});" 27 | ] 28 | }, 29 | "Test: context builder": { 30 | "prefix": "ctx", 31 | "body": [ 32 | "export const ctx${1:Name} = async (t) => {", 33 | " $0", 34 | " return {};", 35 | "};", 36 | "export namespace ctx$1 {", 37 | " export type Ctx = Awaited>;", 38 | " export type T = ExecutionContext;", 39 | "}" 40 | ] 41 | }, 42 | "Test: before": { 43 | "prefix": "before", 44 | "body": [ 45 | "test.before(async (t) => {", 46 | " $0", 47 | "});" 48 | ] 49 | }, 50 | "Test: beforeEach": { 51 | "prefix": "beforeEach", 52 | "body": [ 53 | "test.beforeEach(async (t) => {", 54 | " $0", 55 | "});" 56 | ] 57 | }, 58 | "Test: teardown": { 59 | "prefix": "teardown", 60 | "body": [ 61 | "t.teardown(async (t) => {", 62 | " $0", 63 | "});" 64 | ] 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /.yarn/plugins/@yarnpkg/plugin-compat.cjs: -------------------------------------------------------------------------------- 1 | // No-op plugin to disable yarn's own plugin-compat, preventing any unexpected 2 | // modifications to the typescript package and others 3 | module.exports = { 4 | name: `@yarnpkg/plugin-compat`, 5 | factory: require => ({}) 6 | }; 7 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | enableGlobalCache: true 2 | 3 | nmHoistingLimits: workspaces 4 | 5 | nmMode: hardlinks-global 6 | 7 | nodeLinker: node-modules 8 | 9 | plugins: 10 | - path: .yarn/plugins/@yarnpkg/plugin-compat.cjs 11 | spec: .yarn/plugins/@yarnpkg/plugin-compat.cjs 12 | 13 | yarnPath: .yarn/releases/yarn-3.4.1.cjs 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Blake Embrey (hello@blakeembrey.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Security contact information 4 | 5 | To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. 6 | -------------------------------------------------------------------------------- /child-loader.mjs: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'url'; 2 | import { createRequire } from 'module'; 3 | const require = createRequire(fileURLToPath(import.meta.url)); 4 | 5 | // TODO why use require() here? I think we can just `import` 6 | /** @type {import('./dist/child-loader')} */ 7 | const childLoader = require('./dist/child/child-loader'); 8 | export const { resolve, load, getFormat, transformSource } = childLoader; 9 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | fixes: 2 | # Remap from npm-installed ts-node to root of project 3 | # This can take the place of ./scripts/rewrite-coverage-paths.js 4 | - "tests/node_modules/ts-node/::" 5 | 6 | coverage: 7 | status: 8 | patch: 9 | default: 10 | # Do not fail when `patch` coverage is low. When this fails, it is misleading and not necessarily bad. 11 | # For example if a patch changes 2 lines, and only one is covered, then patch coverage is 50%. 12 | target: 0% 13 | project: 14 | default: 15 | threshold: 1% 16 | 17 | comment: 18 | layout: "files" 19 | -------------------------------------------------------------------------------- /development-docs/README.md: -------------------------------------------------------------------------------- 1 | This directory contains a variety of documents: 2 | 3 | - notes 4 | - old to-do lists 5 | - design ideas from when I implemented various features 6 | - templates for drafting release notes 7 | - etc 8 | 9 | It is useful to me to keep these notes. If you find their presence 10 | confusing, you can safely ignore this directory. 11 | -------------------------------------------------------------------------------- /development-docs/nodenextNode16.md: -------------------------------------------------------------------------------- 1 | # Adding support for NodeNext, Node16, `.cts`, `.mts`, `.cjs`, `.mjs` 2 | 3 | *This feature has already been implemented. Here are my notes from when 4 | I was doing the work* 5 | 6 | ## TODOs 7 | 8 | Implement node module type classifier: 9 | - if NodeNext or Node12: ask classifier for CJS or ESM determination 10 | Add `ForceNodeNextCJSEmit` 11 | 12 | Does our code check for .d.ts extensions anywhere? 13 | - if so, teach it about .d.cts and .d.mts 14 | 15 | For nodenext and node12, support supplemental "flavor" information: 16 | - 17 | 18 | Think about splitting out index.ts further: 19 | - register.ts - hooking stuff 20 | - types.ts 21 | - env.ts - env vars and global registration types (process.symbol) 22 | - service.ts 23 | 24 | # TESTS 25 | 26 | Matrix: 27 | 28 | - package.json type absent, commonjs, and module 29 | - import and require 30 | - from cjs and esm 31 | - .cts, .cjs 32 | - .mts, .mjs 33 | - typechecking, transpileOnly, and swc 34 | - dynamic import 35 | - import = require 36 | - static import 37 | - allowJs on and off 38 | 39 | Notes about specific matrix entries: 40 | - require mjs, mts from cjs throws error 41 | 42 | Rethink: 43 | `getOutput`: null in transpile-only mode. Also may return emitskipped 44 | `getOutputTranspileOnly`: configured module option 45 | `getOutputForceCommonJS`: `commonjs` module option 46 | `getOutputForceNodeCommonJS`: `nodenext` cjs module option 47 | `getOutputForceESM`: `esnext` module option 48 | 49 | Add second layer of classification to classifier: 50 | if classifier returns `auto` (no `moduleType` override) 51 | - if `getOutput` emits, done 52 | - else call `nodeModuleTypeClassifier` 53 | - delegate to appropriate `getOutput` based on its response 54 | -------------------------------------------------------------------------------- /development-docs/release-template.md: -------------------------------------------------------------------------------- 1 | ## Template to be copy-pasted as a template for new release notes. 2 | 3 | --- 4 | 5 | 9 | Questions about this release? Ask in the official discussion thread: #TODO 10 | 11 | 12 | 13 | *Breaking changes are prefixed with **[BREAKING]*** 14 | 15 | **Added** 16 | 17 | - Adds description of thing added (#Issue, #PR, #etc) @contributor-name 18 | 19 | 20 | - Optionally add details ([docs](link to docs)) 21 | - Or multiple docs links ([CLI docs](link to docusaurus page), [API docs](link to typedoc page)) 22 | 23 | **Changed** 24 | 25 | - **[BREAKING]** Make yadda yadda... 26 | 27 | **Deprecated** 28 | 29 | **Removed** 30 | 31 | **Fixed** 32 | 33 | - Fix #TODO: Description of fix (#Issue, #PR, #etc) 34 | 35 | **Docs** 36 | 37 | - In the past I've documented major improvements to docs, new docsite, new docs sections about confusing bits 38 | - In general should avoid changelog entries that do not affect ts-node consumers 39 | 40 | **Misc** 41 | 42 | - In the past I've documented improvements to testing, codecov, etc. 43 | - In general should avoid changelog entries that do not affect ts-node consumers 44 | 45 | https://github.com/TypeStrong/ts-node/compare/vTODO...vTODO 46 | https://github.com/TypeStrong/ts-node/milestone/TODO 47 | 48 | --- 49 | 50 | ## Discussion thread template 51 | 52 | --- 53 | 54 | Discussion thread for the vTODO release. 55 | 56 | [Release notes](https://github.com/TypeStrong/ts-node/releases/tag/vTODO) 57 | -------------------------------------------------------------------------------- /development-docs/repl-api.md: -------------------------------------------------------------------------------- 1 | ## How to create your own ts-node powered REPL 2 | 3 | - Create ts-node REPL service which includes EvalState 4 | - Create ts-node compiler service using EvalState-aware `readFile` and `fileExists` implementations from REPL 5 | - Bind REPL service to compiler service (chicken-and-egg problem necessitates late binding) 6 | - Either: 7 | - call REPL method start() to start a REPL 8 | - create your own node repl but pass it REPL service's nodeEval() function 9 | 10 | ``` 11 | import * as tsnode from 'ts-node'; 12 | const repl = tsnode.createRepl(); 13 | const service = tsnode.register({ 14 | ... options, 15 | ...repl.evalAwarePartialHost 16 | }); 17 | repl.setService(service); 18 | 19 | // Start it 20 | repl.start(); 21 | 22 | // or 23 | const nodeRepl = require('repl').start({ 24 | ...options, 25 | eval: repl.nodeEval 26 | }); 27 | ``` 28 | -------------------------------------------------------------------------------- /development-docs/rootDirOutDirMapping.md: -------------------------------------------------------------------------------- 1 | ## Musings about resolving between rootDir and outDir 2 | 3 | When /dist and /src are understood to be overlaid because of src -> dist compiling 4 | /dist/ 5 | /src/ 6 | 7 | Loop over require.extensions 8 | /src/foo.js 9 | /src/foo.mjs 10 | /src/foo.cjs 11 | /src/foo.ts 12 | /src/foo.mts 13 | /src/foo.cts 14 | /src/foo/index.js 15 | /src/foo/index.mjs 16 | /src/foo/index.ts 17 | // Where do we check package.json main?? 18 | 19 | 20 | /dist/foo.js 21 | /dist/foo.ts 22 | 23 | 24 | _resolveLookupPaths 25 | _findPath 26 | _resolveFilename 27 | 28 | _findPath calls resolveExports calls packageExportsResolve, which is in the ESM loader 29 | 30 | Is anything within packageExportsResolve hooked/modified by us? File extension swapping? 31 | 32 | 33 | When resolver calls statSync('./dist/foo.js') and we intercept and discover './src/foo.ts' 34 | How to redirect? We need to rewrite whatever local variable is storing `./dist/foo.js` 35 | -------------------------------------------------------------------------------- /development-docs/test-style-guide.md: -------------------------------------------------------------------------------- 1 | ## Test guidelines 2 | 3 | *These notes are my attempt at keeping myself consistent when writing tests. Nothing too formal.* 4 | 5 | ### DRYing up tests with reusable functions 6 | 7 | If a reusable function does not need access to anything from the context, 8 | it's a plain function. 9 | 10 | If the reusable function needs access to stuff from context, it's a 11 | context helper. 12 | 13 | If the reusable function implements all the necessary assertions within itself, it's a macro. 14 | 15 | ### Function args 16 | 17 | Plain functions w/many options should accept a single option-bag. 18 | Should also have `setOptions` method to overlay additional options, and `getOptions` to inspect. 19 | *At time of writing, I have not implemented `setOptions` nor `getOptions`* 20 | 21 | Never destructure `t` 22 | Never destructure `test` 23 | Only exception: destructure `{context}` or `{contextEach}` if calling `const test = context(fooCtx)` b/c avoids `test = _test.context()` 24 | 25 | ### Consistent naming 26 | 27 | When exec-ing a process: 28 | 29 | Awaited result is in local var `r` 30 | Non-awaited is in local var `p` 31 | Do not destructure either way. 32 | 33 | Context builders are named with a `ctx` prefix and also declare a couple types on their namespace. See src/test/helpers/ctx* for format. 34 | -------------------------------------------------------------------------------- /development-docs/yarnPnpInterop.md: -------------------------------------------------------------------------------- 1 | ## Yarn PnP interop 2 | 3 | Asked about it here: 4 | https://discord.com/channels/226791405589233664/654372321225605128/957301175609344070 5 | 6 | PnP API checks if import specifiers are for dependencies: non-relative, non-absolute 7 | libfoo 8 | @scope/libfoo 9 | 10 | When they are, it does `resolveToUnqualified` to map to an unqualified path. 11 | This path points to the module's location on disk (in a zip, perhaps) but does 12 | not handle file extension resolution or stuff like that. 13 | 14 | To interop with PnP, we need PnP to *only* `resolveToUnqualified`. 15 | We do everything else. 16 | 17 | ```typescript 18 | import { Module } from 'module'; 19 | import fs from 'fs'; 20 | 21 | const pathRegExp = /^(?![a-zA-Z]:[\\/]|\\\\|\.{0,2}(?:\/|$))((?:@[^/]+\/)?[^/]+)\/*(.*|)$/; 22 | 23 | const originalModuleResolveFilename = Module._resolveFilename; 24 | Module._resolveFilename = function ( 25 | request: string, 26 | parent: typeof Module | null | undefined, 27 | isMain: boolean, 28 | options?: { [key: string]: any } 29 | ) { 30 | const dependencyNameMatch = request.match(pathRegExp); 31 | if (dependencyNameMatch !== null) { 32 | 33 | const [, dependencyName, subPath] = dependencyNameMatch; 34 | 35 | const unqualified = pnpapi.resolveToUnqualified(....); 36 | 37 | // Do your modified resolution on the unqualified path here 38 | 39 | } else { 40 | 41 | // Do your modified resolution here; no need for PnP 42 | 43 | } 44 | 45 | }; 46 | ``` 47 | 48 | PnP can be installed at runtime. 49 | 50 | To conditionally check if PnP is available at the start of *every* resolution: 51 | 52 | ```typescript 53 | // Get the pnpapi of either the issuer or the specifier. 54 | // The latter is required when the specifier is an absolute path to a 55 | // zip file and the issuer doesn't belong to a pnpapi 56 | const {findPnPApi} = Module; 57 | const pnpapi = findPnPApi ? (findPnpApi(issuer) ?? (url ? findPnpApi(specifier) : null)) : null; 58 | if (pnpapi) {...} 59 | ``` 60 | -------------------------------------------------------------------------------- /dist-raw/NODE-LICENSE.md: -------------------------------------------------------------------------------- 1 | This directory contains portions of Node.js source code which is licensed as follows: 2 | 3 | --- 4 | 5 | Copyright Joyent, Inc. and other Node contributors. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a 8 | copy of this software and associated documentation files (the 9 | "Software"), to deal in the Software without restriction, including 10 | without limitation the rights to use, copy, modify, merge, publish, 11 | distribute, sublicense, and/or sell copies of the Software, and to permit 12 | persons to whom the Software is furnished to do so, subject to the 13 | following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included 16 | in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 21 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 22 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24 | USE OR OTHER DEALINGS IN THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /dist-raw/README.md: -------------------------------------------------------------------------------- 1 | The `dist-raw` directory contains JS sources that are distributed verbatim, not compiled nor typechecked via TS. 2 | 3 | To implement ESM support, we unfortunately must duplicate some of node's built-in functionality that is not 4 | exposed via an API. We have copy-pasted the necessary code from https://github.com/nodejs/node/tree/master/lib 5 | then modified it to suite our needs. 6 | 7 | Formatting may be intentionally bad to keep the diff as small as possible, to make it easier to merge 8 | upstream changes and understand our modifications. For example, when we need to wrap node's source code 9 | in a factory function, we will not indent the function body, to avoid whitespace changes in the diff. 10 | 11 | One obvious problem with this approach: the code has been pulled from one version of node, whereas users of ts-node 12 | run multiple versions of node. 13 | Users running node 14 may see that ts-node behaves like node 18, for example. 14 | 15 | ## `raw` directory 16 | 17 | Within the `raw` directory, we keep unmodified copies of the node source files. This allows us to use diffing tools to 18 | compare files in `raw` to those in `dist-raw`, which will highlight all of the changes we have made. Hopefully, these 19 | changes are as minimal as possible. 20 | 21 | ## Naming convention 22 | 23 | Not used consistently, but the idea is: 24 | 25 | `node-(...-)-.js` 26 | 27 | `node-internal-errors.js` -> `github.com/nodejs/node/blob/TAG/lib/internal/errors.js` 28 | 29 | So, take the path within node's `lib/` directory, and replace slashes with hyphens. 30 | 31 | In the `raw` directory, files are suffixed with the version number or revision from which 32 | they were downloaded. 33 | 34 | If they have a `stripped` suffix, this means they have large chunks of code deleted, but no other modifications. 35 | This is useful when diffing. Sometimes our `dist-raw` files only have a small part of a much larger node source file. 36 | It is easier to diff `raw/*-stripped.js` against `dist-raw/*.js`. 37 | -------------------------------------------------------------------------------- /dist-raw/node-internal-constants.js: -------------------------------------------------------------------------------- 1 | // Copied from https://github.com/nodejs/node/blob/master/lib/internal/constants.js 2 | module.exports = { 3 | CHAR_FORWARD_SLASH: 47, /* / */ 4 | }; 5 | -------------------------------------------------------------------------------- /dist-raw/node-internal-modules-package_json_reader.js: -------------------------------------------------------------------------------- 1 | // copied from https://github.com/nodejs/node/blob/v15.3.0/lib/internal/modules/package_json_reader.js 2 | 'use strict'; 3 | 4 | const { SafeMap } = require('./node-primordials'); 5 | const { internalModuleReadJSON } = require('./node-internalBinding-fs'); 6 | const { pathToFileURL } = require('url'); 7 | const { toNamespacedPath } = require('path'); 8 | // const { getOptionValue } = require('./node-options'); 9 | 10 | const cache = new SafeMap(); 11 | 12 | let manifest; 13 | 14 | /** 15 | * @param {string} jsonPath 16 | * @return {{string: string, containsKeys: boolean}} 17 | */ 18 | function read(jsonPath) { 19 | if (cache.has(jsonPath)) { 20 | return cache.get(jsonPath); 21 | } 22 | 23 | const [string, containsKeys] = internalModuleReadJSON( 24 | toNamespacedPath(jsonPath) 25 | ); 26 | const result = { string, containsKeys }; 27 | if (string !== undefined) { 28 | if (manifest === undefined) { 29 | // manifest = getOptionValue('--experimental-policy') ? 30 | // require('internal/process/policy').manifest : 31 | // null; 32 | // disabled for now. I am not sure if/how we should support this 33 | manifest = null; 34 | } 35 | if (manifest !== null) { 36 | const jsonURL = pathToFileURL(jsonPath); 37 | manifest.assertIntegrity(jsonURL, string); 38 | } 39 | } 40 | cache.set(jsonPath, result); 41 | return result; 42 | } 43 | 44 | module.exports = { read }; 45 | -------------------------------------------------------------------------------- /dist-raw/node-internalBinding-fs.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const {versionGteLt} = require('../dist/util'); 3 | 4 | // In node's core, this is implemented in C 5 | // https://github.com/nodejs/node/blob/v15.3.0/src/node_file.cc#L891-L985 6 | /** 7 | * @param {string} path 8 | * @returns {[] | [string, boolean]} 9 | */ 10 | function internalModuleReadJSON(path) { 11 | let string 12 | try { 13 | string = fs.readFileSync(path, 'utf8') 14 | } catch (e) { 15 | if (e.code === 'ENOENT') return [] 16 | throw e 17 | } 18 | // Node's implementation checks for the presence of relevant keys: main, name, type, exports, imports 19 | // Node does this for performance to skip unnecessary parsing. 20 | // This would slow us down and, based on our usage, we can skip it. 21 | const containsKeys = true 22 | return [string, containsKeys] 23 | } 24 | 25 | // In node's core, this is implemented in C 26 | // https://github.com/nodejs/node/blob/63e7dc1e5c71b70c80ed9eda230991edb00811e2/src/node_file.cc#L987-L1005 27 | /** 28 | * @param {string} path 29 | * @returns {number} 0 = file, 1 = dir, negative = error 30 | */ 31 | function internalModuleStat(path) { 32 | const stat = fs.statSync(path, { throwIfNoEntry: false }); 33 | if(!stat) return -1; 34 | if(stat.isFile()) return 0; 35 | if(stat.isDirectory()) return 1; 36 | } 37 | 38 | /** 39 | * @param {string} path 40 | * @returns {number} 0 = file, 1 = dir, negative = error 41 | */ 42 | function internalModuleStatInefficient(path) { 43 | try { 44 | const stat = fs.statSync(path); 45 | if(stat.isFile()) return 0; 46 | if(stat.isDirectory()) return 1; 47 | } catch(e) { 48 | return -e.errno || -1; 49 | } 50 | } 51 | 52 | const statSupportsThrowIfNoEntry = versionGteLt(process.versions.node, '15.3.0') || 53 | versionGteLt(process.versions.node, '14.17.0', '15.0.0'); 54 | 55 | module.exports = { 56 | internalModuleReadJSON, 57 | internalModuleStat: statSupportsThrowIfNoEntry ? internalModuleStat : internalModuleStatInefficient 58 | }; 59 | -------------------------------------------------------------------------------- /dist-raw/node-nativemodule.js: -------------------------------------------------------------------------------- 1 | 2 | // Node imports this from 'internal/bootstrap/loaders' 3 | const Module = require('module'); 4 | const NativeModule = { 5 | canBeRequiredByUsers(specifier) { 6 | return Module.builtinModules.includes(specifier) 7 | } 8 | }; 9 | exports.NativeModule = NativeModule; 10 | -------------------------------------------------------------------------------- /dist-raw/runmain-hack.js: -------------------------------------------------------------------------------- 1 | const {pathToFileURL} = require('url'); 2 | 3 | // Hack to avoid Module.runMain on node 18.6.0 4 | // Keeping it simple for now, isolated in this file. 5 | // Could theoretically probe `getFormat` impl to determine if `import()` or `Module._load()` is best 6 | // Note that I attempted a try-catch around `Module._load`, but it poisons some sort of cache such that subsequent `import()` is impossible. 7 | exports.run = function(entryPointPath) { 8 | import(pathToFileURL(entryPointPath)); 9 | } 10 | -------------------------------------------------------------------------------- /dprint.json: -------------------------------------------------------------------------------- 1 | { 2 | "incremental": true, 3 | "lineWidth": 120, 4 | "prettier": { 5 | "associations": [ 6 | "**/*.{ts,tsx,js,mjs,cjs,jsx,json,md}" 7 | ], 8 | "singleQuote": true 9 | }, 10 | // Run `dprint output-file-paths` to see which files are being matched 11 | "includes": [ 12 | "/*.{js,mjs}", 13 | "/esm/**", 14 | "/register/**", 15 | "/scripts/**", 16 | "/src/**", 17 | "/tests/**", 18 | "/website/**" 19 | ], 20 | "excludes": [ 21 | "/website/.docusaurus", 22 | "/website/build", 23 | "/website/docs", 24 | "/website/readme-sources", 25 | "/website/static", 26 | "tests/main-realpath/symlink/tsconfig.json", 27 | "tests/throw error.ts", 28 | "tests/throw error react tsx.tsx", 29 | "tests/esm/throw error.ts", 30 | "tests/legacy-source-map-support-interop/index.ts", 31 | "tests/main-realpath/symlink/symlink.tsx", 32 | "tests/tmp" 33 | ], 34 | "plugins": [ 35 | "https://plugins.dprint.dev/prettier-0.6.2.exe-plugin@36dd4f8b9710ab323c471017ecd00a20cf1dca2728c12242c7dabb8dfacad0e2" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /esm-usage-example/README.md: -------------------------------------------------------------------------------- 1 | To run the experiment: 2 | 3 | ``` 4 | cd ./esm-usage-example # Must be in this directory 5 | node -v # Must be using node v13 6 | 7 | # Install the github branch via npm 8 | npm install 9 | node --loader ts-node/esm ./index.js 10 | 11 | # Or if you're hacking locally 12 | node --loader ../esm.mjs ./index 13 | 14 | ``` 15 | -------------------------------------------------------------------------------- /esm-usage-example/bar.ts: -------------------------------------------------------------------------------- 1 | export const bar = 123; 2 | -------------------------------------------------------------------------------- /esm-usage-example/foo.ts: -------------------------------------------------------------------------------- 1 | export const foo = 123; 2 | export {bar} from './bar'; 3 | 4 | -------------------------------------------------------------------------------- /esm-usage-example/index.js: -------------------------------------------------------------------------------- 1 | async function main() { 2 | const fooModule = await import('./foo.ts'); 3 | console.dir({foo: fooModule}) 4 | } 5 | main() 6 | -------------------------------------------------------------------------------- /esm-usage-example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "dependencies": { 4 | "ts-node": "github:TypeStrong/ts-node#main", 5 | "typescript": "^3.8.3" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /esm-usage-example/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /esm.mjs: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'url'; 2 | import { createRequire } from 'module'; 3 | const require = createRequire(fileURLToPath(import.meta.url)); 4 | 5 | /** @type {import('./dist/esm')} */ 6 | const esm = require('./dist/esm'); 7 | export const { resolve, load, getFormat, transformSource } = esm.registerAndCreateEsmHooks(); 8 | -------------------------------------------------------------------------------- /esm/transpile-only.mjs: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'url'; 2 | import { createRequire } from 'module'; 3 | const require = createRequire(fileURLToPath(import.meta.url)); 4 | 5 | /** @type {import('../dist/esm')} */ 6 | const esm = require('../dist/esm'); 7 | export const { resolve, load, getFormat, transformSource } = esm.registerAndCreateEsmHooks({ 8 | transpileOnly: true, 9 | }); 10 | -------------------------------------------------------------------------------- /node10/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node10/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /node12/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node12/tsconfig.json", 3 | } 4 | -------------------------------------------------------------------------------- /node14/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node14/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /node16/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node16/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /node18/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node18/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /node20/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node20/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /nyc.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | all: true, 3 | include: ['tests/node_modules/ts-node/**'], 4 | exclude: ['**/*.d.ts', 'tests/node_modules/ts-node/node_modules/**'], 5 | // Very important that nyc does not add additional `require.extensions` hooks. 6 | // It affects module resolution behavior under test 7 | extension: ['.js'], 8 | excludeNodeModules: false, 9 | excludeAfterRemap: false, 10 | }; 11 | -------------------------------------------------------------------------------- /raw/README.md: -------------------------------------------------------------------------------- 1 | See the README.md in `dist-raw` 2 | -------------------------------------------------------------------------------- /raw/node-internal-errors-b533fb3508009e5f567cc776daba8fbf665386a6-stripped.js: -------------------------------------------------------------------------------- 1 | // Copied from https://github.com/nodejs/node/blob/b533fb3508009e5f567cc776daba8fbf665386a6/lib/internal/errors.js 2 | 3 | 'use strict'; 4 | 5 | // Utility function for registering the error codes. Only used here. Exported 6 | // *only* to allow for testing. 7 | function E(sym, val, def, ...otherClasses) { 8 | // Special case for SystemError that formats the error message differently 9 | // The SystemErrors only have SystemError as their base classes. 10 | messages.set(sym, val); 11 | if (def === SystemError) { 12 | def = makeSystemErrorWithCode(sym); 13 | } else { 14 | def = makeNodeErrorWithCode(def, sym); 15 | } 16 | 17 | if (otherClasses.length !== 0) { 18 | otherClasses.forEach((clazz) => { 19 | def[clazz.name] = makeNodeErrorWithCode(clazz, sym); 20 | }); 21 | } 22 | codes[sym] = def; 23 | } 24 | 25 | E('ERR_REQUIRE_ESM', 26 | (filename, parentPath = null, packageJsonPath = null) => { 27 | let msg = `Must use import to load ES Module: ${filename}`; 28 | if (parentPath && packageJsonPath) { 29 | const path = require('path'); 30 | const basename = path.basename(filename) === path.basename(parentPath) ? 31 | filename : path.basename(filename); 32 | msg += 33 | '\nrequire() of ES modules is not supported.\nrequire() of ' + 34 | `${filename} ${parentPath ? `from ${parentPath} ` : ''}` + 35 | 'is an ES module file as it is a .js file whose nearest parent ' + 36 | 'package.json contains "type": "module" which defines all .js ' + 37 | 'files in that package scope as ES modules.\nInstead rename ' + 38 | `${basename} to end in .cjs, change the requiring code to use ` + 39 | 'import(), or remove "type": "module" from ' + 40 | `${packageJsonPath}.\n`; 41 | return msg; 42 | } 43 | return msg; 44 | }, Error); 45 | -------------------------------------------------------------------------------- /raw/node-internal-modules-package_json_reader-v15.3.0.js: -------------------------------------------------------------------------------- 1 | // Copied from https://github.com/nodejs/node/blob/v15.3.0/lib/internal/modules/package_json_reader.js 2 | 3 | 'use strict'; 4 | 5 | const { SafeMap } = primordials; 6 | const { internalModuleReadJSON } = internalBinding('fs'); 7 | const { pathToFileURL } = require('url'); 8 | const { toNamespacedPath } = require('path'); 9 | 10 | const cache = new SafeMap(); 11 | 12 | let manifest; 13 | 14 | /** 15 | * 16 | * @param {string} jsonPath 17 | */ 18 | function read(jsonPath) { 19 | if (cache.has(jsonPath)) { 20 | return cache.get(jsonPath); 21 | } 22 | 23 | const [string, containsKeys] = internalModuleReadJSON( 24 | toNamespacedPath(jsonPath) 25 | ); 26 | const result = { string, containsKeys }; 27 | const { getOptionValue } = require('internal/options'); 28 | if (string !== undefined) { 29 | if (manifest === undefined) { 30 | manifest = getOptionValue('--experimental-policy') ? 31 | require('internal/process/policy').manifest : 32 | null; 33 | } 34 | if (manifest !== null) { 35 | const jsonURL = pathToFileURL(jsonPath); 36 | manifest.assertIntegrity(jsonURL, string); 37 | } 38 | } 39 | cache.set(jsonPath, result); 40 | return result; 41 | } 42 | 43 | module.exports = { read }; 44 | -------------------------------------------------------------------------------- /register/files.js: -------------------------------------------------------------------------------- 1 | require('../dist').register({ 2 | files: true, 3 | }); 4 | -------------------------------------------------------------------------------- /register/index.js: -------------------------------------------------------------------------------- 1 | require('../').register(); 2 | -------------------------------------------------------------------------------- /register/transpile-only.js: -------------------------------------------------------------------------------- 1 | require('../').register({ 2 | transpileOnly: true, 3 | }); 4 | -------------------------------------------------------------------------------- /register/type-check.js: -------------------------------------------------------------------------------- 1 | require('../').register({ 2 | typeCheck: true, 3 | }); 4 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/screenshot.png -------------------------------------------------------------------------------- /scripts/build-manifest.mjs: -------------------------------------------------------------------------------- 1 | import { readFileSync, writeFileSync } from 'fs'; 2 | import { fileURLToPath } from 'url'; 3 | import { resolve } from 'path'; 4 | 5 | // NOTE: could be replaced with using https://npm.im/yarpm 6 | 7 | const manifestPath = resolve(fileURLToPath(import.meta.url), '../../package.json'); 8 | const pkg = JSON.parse(readFileSync(manifestPath, 'utf8')); 9 | 10 | // Fully splat the "prepack" script so that it does not contain references to a package manager, neither `yarn` nor `npm` 11 | let before; 12 | let prepack = pkg.scripts.__prepack_template__; 13 | while (before !== prepack) { 14 | before = prepack; 15 | prepack = prepack.replace(/yarn (\S+)/g, ($0, $1) => pkg.scripts[$1]); 16 | } 17 | pkg.scripts['prepack-worker'] = prepack; 18 | 19 | writeFileSync(manifestPath, JSON.stringify(pkg, null, 2) + '\n'); 20 | -------------------------------------------------------------------------------- /scripts/build-pack.js: -------------------------------------------------------------------------------- 1 | // Written in JS to support Windows 2 | // Would otherwise be written as inline bash in package.json script 3 | 4 | const { exec } = require('child_process'); 5 | const { join } = require('path'); 6 | 7 | const rootDir = join(__dirname, '..'); 8 | const testDir = join(__dirname, '../tests'); 9 | const tarballPath = join(testDir, 'ts-node-packed.tgz'); 10 | 11 | const env = { 12 | ...process.env, 13 | TS_NODE_SKIP_PREPACK: 'true', 14 | }; 15 | 16 | exec(`yarn pack --out "${tarballPath}"`, { cwd: rootDir, env }, (err, stdout) => { 17 | if (err) { 18 | console.error(err); 19 | process.exit(1); 20 | } 21 | }); 22 | -------------------------------------------------------------------------------- /scripts/node-nightly.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Hacky script to grab node nightly and plonk it into node_modules/.bin, for 4 | # locally testing against nightly builds. 5 | 6 | set -euo pipefail 7 | shopt -s inherit_errexit 8 | __dirname="$(CDPATH= cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 9 | cd "$__dirname/.." 10 | 11 | set -x 12 | 13 | mkdir -p tmp 14 | 15 | version=$(curl https://nodejs.org/download/nightly/index.json | jq -r '.[0].version') 16 | [ -e "tmp/$version.tar.xz" ] || \ 17 | curl -o "tmp/$version.tar.xz" "https://nodejs.org/download/nightly/$version/node-$version-linux-x64.tar.xz" 18 | 19 | [ -e "tmp/$version.tar" ] || \ 20 | unxz "tmp/$version.tar.xz" 21 | 22 | { 23 | cd tmp 24 | tar -xvf "$version.tar" 25 | } 26 | 27 | ln -s "../../tmp/node-$version-linux-x64/bin/node" ./node_modules/.bin/node 28 | -------------------------------------------------------------------------------- /scripts/prepack.mjs: -------------------------------------------------------------------------------- 1 | const { npm_execpath } = process.env; 2 | 3 | // prepack is executed by user's package manager when they install from git 4 | // So cannot assume yarn 5 | 6 | if (process.env.TS_NODE_SKIP_PREPACK == null) { 7 | const crossSpawn = await import('cross-spawn'); 8 | const result = crossSpawn.sync(npm_execpath, ['run', 'prepack-worker'], { 9 | stdio: 'inherit', 10 | }); 11 | process.exit(result.status); 12 | } 13 | -------------------------------------------------------------------------------- /src/bin-cwd.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { main } from './bin'; 4 | 5 | main(undefined, { '--cwdMode': true }); 6 | -------------------------------------------------------------------------------- /src/bin-esm.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { main } from './bin'; 4 | 5 | main(undefined, { '--esm': true }); 6 | -------------------------------------------------------------------------------- /src/bin-script.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { main } from './bin'; 4 | 5 | main(undefined, { '--scriptMode': true }); 6 | -------------------------------------------------------------------------------- /src/bin-transpile.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import { main } from './bin'; 4 | 5 | main(undefined, { '--transpileOnly': true }); 6 | -------------------------------------------------------------------------------- /src/child/argv-payload.ts: -------------------------------------------------------------------------------- 1 | import { brotliCompressSync, brotliDecompressSync, constants } from 'zlib'; 2 | 3 | /** @internal */ 4 | export const argPrefix = '--brotli-base64-config='; 5 | 6 | /** @internal */ 7 | export function compress(object: any) { 8 | return brotliCompressSync(Buffer.from(JSON.stringify(object), 'utf8'), { 9 | [constants.BROTLI_PARAM_QUALITY]: constants.BROTLI_MIN_QUALITY, 10 | }).toString('base64'); 11 | } 12 | 13 | /** @internal */ 14 | export function decompress(str: string) { 15 | return JSON.parse(brotliDecompressSync(Buffer.from(str, 'base64')).toString()); 16 | } 17 | -------------------------------------------------------------------------------- /src/child/child-entrypoint.ts: -------------------------------------------------------------------------------- 1 | import { BootstrapState, bootstrap } from '../bin'; 2 | import { argPrefix, compress, decompress } from './argv-payload'; 3 | 4 | const base64ConfigArg = process.argv[2]; 5 | if (!base64ConfigArg.startsWith(argPrefix)) throw new Error('unexpected argv'); 6 | const base64Payload = base64ConfigArg.slice(argPrefix.length); 7 | const state = decompress(base64Payload) as BootstrapState; 8 | 9 | state.isInChildProcess = true; 10 | state.tsNodeScript = __filename; 11 | state.parseArgvResult.argv = process.argv; 12 | state.parseArgvResult.restArgs = process.argv.slice(3); 13 | 14 | // Modify and re-compress the payload delivered to subsequent child processes. 15 | // This logic may be refactored into bin.ts by https://github.com/TypeStrong/ts-node/issues/1831 16 | if (state.isCli) { 17 | const stateForChildren: BootstrapState = { 18 | ...state, 19 | isCli: false, 20 | }; 21 | state.parseArgvResult.argv[2] = `${argPrefix}${compress(stateForChildren)}`; 22 | } 23 | 24 | bootstrap(state); 25 | -------------------------------------------------------------------------------- /src/child/child-loader.ts: -------------------------------------------------------------------------------- 1 | import type { NodeLoaderHooksAPI1, NodeLoaderHooksAPI2 } from '..'; 2 | import { filterHooksByAPIVersion } from '../esm'; 3 | 4 | let hooks: NodeLoaderHooksAPI1 & NodeLoaderHooksAPI2; 5 | 6 | /** @internal */ 7 | export function lateBindHooks(_hooks: NodeLoaderHooksAPI1 | NodeLoaderHooksAPI2) { 8 | hooks = _hooks as NodeLoaderHooksAPI1 & NodeLoaderHooksAPI2; 9 | } 10 | 11 | const proxy: NodeLoaderHooksAPI1 & NodeLoaderHooksAPI2 = { 12 | resolve(...args: Parameters) { 13 | return (hooks?.resolve ?? args[2])(...args); 14 | }, 15 | load(...args: Parameters) { 16 | return (hooks?.load ?? args[2])(...args); 17 | }, 18 | getFormat(...args: Parameters) { 19 | return (hooks?.getFormat ?? args[2])(...args); 20 | }, 21 | transformSource(...args: Parameters) { 22 | return (hooks?.transformSource ?? args[2])(...args); 23 | }, 24 | }; 25 | 26 | /** @internal */ 27 | export const { resolve, load, getFormat, transformSource } = filterHooksByAPIVersion(proxy) as NodeLoaderHooksAPI1 & 28 | NodeLoaderHooksAPI2; 29 | -------------------------------------------------------------------------------- /src/child/child-require.ts: -------------------------------------------------------------------------------- 1 | interface EventEmitterInternals { 2 | _events: Record>; 3 | } 4 | const _process = process as any as EventEmitterInternals; 5 | 6 | // Not shown here: Additional logic to correctly interact with process's events, either using this direct manipulation, or via the API 7 | 8 | let originalOnWarning: Function | undefined; 9 | if (Array.isArray(_process._events.warning)) { 10 | originalOnWarning = _process._events.warning[0]; 11 | _process._events.warning[0] = onWarning; 12 | } else { 13 | originalOnWarning = _process._events.warning; 14 | _process._events.warning = onWarning; 15 | } 16 | 17 | const messageMatch = /(?:--(?:experimental-)?loader\b|\bCustom ESM Loaders\b)/; 18 | function onWarning(this: any, warning: Error, ...rest: any[]) { 19 | // Suppress warning about how `--loader` is experimental 20 | if (warning?.name === 'ExperimentalWarning' && messageMatch.test(warning?.message)) return; 21 | // Will be undefined if `--no-warnings` 22 | return originalOnWarning?.call(this, warning, ...rest); 23 | } 24 | -------------------------------------------------------------------------------- /src/child/spawn-child.ts: -------------------------------------------------------------------------------- 1 | import type { BootstrapState } from '../bin'; 2 | import { spawn } from 'child_process'; 3 | import { pathToFileURL } from 'url'; 4 | import { argPrefix, compress } from './argv-payload'; 5 | 6 | /** 7 | * @internal 8 | * @param state Bootstrap state to be transferred into the child process. 9 | * @param targetCwd Working directory to be preserved when transitioning to 10 | * the child process. 11 | */ 12 | export function callInChild(state: BootstrapState) { 13 | const child = spawn( 14 | process.execPath, 15 | [ 16 | '--require', 17 | require.resolve('./child-require.js'), 18 | '--loader', 19 | // Node on Windows doesn't like `c:\` absolute paths here; must be `file:///c:/` 20 | pathToFileURL(require.resolve('../../child-loader.mjs')).toString(), 21 | require.resolve('./child-entrypoint.js'), 22 | `${argPrefix}${compress(state)}`, 23 | ...state.parseArgvResult.restArgs, 24 | ], 25 | { 26 | stdio: 'inherit', 27 | argv0: process.argv0, 28 | } 29 | ); 30 | child.on('error', (error) => { 31 | console.error(error); 32 | process.exit(1); 33 | }); 34 | child.on('exit', (code) => { 35 | child.removeAllListeners(); 36 | process.off('SIGINT', sendSignalToChild); 37 | process.off('SIGTERM', sendSignalToChild); 38 | process.exitCode = code === null ? 1 : code; 39 | }); 40 | // Ignore sigint and sigterm in parent; pass them to child 41 | process.on('SIGINT', sendSignalToChild); 42 | process.on('SIGTERM', sendSignalToChild); 43 | function sendSignalToChild(signal: string) { 44 | process.kill(child.pid, signal); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/cjs-resolve-hooks.ts: -------------------------------------------------------------------------------- 1 | import type Module = require('module'); 2 | import type { Service } from '.'; 3 | 4 | /** @internal */ 5 | export type ModuleConstructorWithInternals = typeof Module & { 6 | _resolveFilename( 7 | request: string, 8 | parent?: Module, 9 | isMain?: boolean, 10 | options?: ModuleResolveFilenameOptions, 11 | ...rest: any[] 12 | ): string; 13 | _preloadModules(requests?: string[]): void; 14 | _findPath(request: string, paths: string[], isMain: boolean): string; 15 | }; 16 | 17 | interface ModuleResolveFilenameOptions { 18 | paths?: Array; 19 | } 20 | 21 | /** 22 | * @internal 23 | */ 24 | export function installCommonjsResolveHooksIfNecessary(tsNodeService: Service) { 25 | const Module = require('module') as ModuleConstructorWithInternals; 26 | const originalResolveFilename = Module._resolveFilename; 27 | const originalFindPath = Module._findPath; 28 | const shouldInstallHook = tsNodeService.options.experimentalResolver; 29 | if (shouldInstallHook) { 30 | const { Module_findPath, Module_resolveFilename } = tsNodeService.getNodeCjsLoader(); 31 | Module._resolveFilename = _resolveFilename; 32 | Module._findPath = _findPath; 33 | function _resolveFilename( 34 | this: any, 35 | request: string, 36 | parent?: Module, 37 | isMain?: boolean, 38 | options?: ModuleResolveFilenameOptions, 39 | ...rest: [] 40 | ): string { 41 | if (!tsNodeService.enabled()) 42 | return originalResolveFilename.call(this, request, parent, isMain, options, ...rest); 43 | 44 | return Module_resolveFilename.call(this, request, parent, isMain, options, ...rest); 45 | } 46 | function _findPath(this: any): string { 47 | if (!tsNodeService.enabled()) return originalFindPath.apply(this, arguments as any); 48 | return Module_findPath.apply(this, arguments as any); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/node-module-type-classifier.ts: -------------------------------------------------------------------------------- 1 | import { readPackageScope } from '../dist-raw/node-internal-modules-cjs-loader'; 2 | 3 | /** 4 | * Determine how to emit a module based on tsconfig "module" and package.json "type" 5 | * 6 | * Supports module=nodenext/node16 with transpileOnly, where we cannot ask the 7 | * TS typechecker to tell us if a file is CJS or ESM. 8 | * 9 | * Return values indicate: 10 | * - cjs 11 | * - esm 12 | * - nodecjs == node-flavored cjs where dynamic imports are *not* transformed into `require()` 13 | * - undefined == emit according to tsconfig `module` config, whatever that is 14 | * @internal 15 | */ 16 | export function classifyModule( 17 | nativeFilename: string, 18 | isNodeModuleType: boolean 19 | ): 'nodecjs' | 'cjs' | 'esm' | 'nodeesm' | undefined { 20 | // [MUST_UPDATE_FOR_NEW_FILE_EXTENSIONS] 21 | const lastDotIndex = nativeFilename.lastIndexOf('.'); 22 | const ext = lastDotIndex >= 0 ? nativeFilename.slice(lastDotIndex) : ''; 23 | switch (ext) { 24 | case '.cjs': 25 | case '.cts': 26 | return isNodeModuleType ? 'nodecjs' : 'cjs'; 27 | case '.mjs': 28 | case '.mts': 29 | return isNodeModuleType ? 'nodeesm' : 'esm'; 30 | } 31 | if (isNodeModuleType) { 32 | const packageScope = readPackageScope(nativeFilename); 33 | if (packageScope && packageScope.data.type === 'module') return 'nodeesm'; 34 | return 'nodecjs'; 35 | } 36 | return undefined; 37 | } 38 | -------------------------------------------------------------------------------- /src/test/ci-node-and-ts-versions.spec.ts: -------------------------------------------------------------------------------- 1 | // When running on CI, double-check that we are testing against the versions of node 2 | // and typescript in the test matrix. 3 | 4 | import { execSync } from 'child_process'; 5 | import semver = require('semver'); 6 | import { ctxTsNode, ts } from './helpers'; 7 | import { context, expect } from './testlib'; 8 | 9 | const test = context(ctxTsNode); 10 | test.suite('Confirm node and typescript versions on CI', (test) => { 11 | test.if(!!process.env.CI); 12 | test('node version is correct', async (t) => { 13 | const expectedVersion = process.env.TEST_MATRIX_NODE_VERSION!; 14 | const actualVersion = process.versions.node; 15 | t.log({ expectedVersion, actualVersion }); 16 | expect(expectedVersion).toBeDefined(); 17 | const major = expectedVersion.match(/^(\d+)-nightly$/)?.[1]; 18 | if (major != null) { 19 | expect(actualVersion).toMatch(new RegExp('^' + major)); 20 | expect(actualVersion).toMatch('-nightly'); 21 | } else { 22 | expect(semver.satisfies(actualVersion, expectedVersion)).toBe(true); 23 | } 24 | }); 25 | test('typescript version is correct', async (t) => { 26 | let expectedVersion = process.env.TEST_MATRIX_TYPESCRIPT_VERSION!; 27 | const actualVersion = ts.version; 28 | t.log({ expectedVersion, actualVersion }); 29 | expect(expectedVersion).toBeDefined(); 30 | if (expectedVersion === 'next' || expectedVersion === 'latest') { 31 | const stdout = execSync(`npm view typescript@${expectedVersion} version --json`, { 32 | encoding: 'utf8', 33 | }); 34 | t.log({ stdout }); 35 | expectedVersion = JSON.parse(stdout); 36 | expect(ts.version).toBe(expectedVersion); 37 | } else { 38 | expect(semver.satisfies(ts.version, expectedVersion)).toBe(true); 39 | } 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /src/test/configuration/resolution.spec.ts: -------------------------------------------------------------------------------- 1 | import { lstatSync } from 'fs'; 2 | import { join } from 'path'; 3 | import { BIN_CWD_PATH, BIN_PATH, BIN_SCRIPT_PATH, createExec, ctxTsNode, TEST_DIR } from '../helpers'; 4 | import { context, expect } from '../testlib'; 5 | 6 | const exec = createExec({ 7 | cwd: TEST_DIR, 8 | }); 9 | 10 | const test = context(ctxTsNode); 11 | 12 | test('should locate tsconfig relative to entry-point by default', async () => { 13 | const r = await exec(`${BIN_PATH} ../a/index`, { 14 | cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), 15 | }); 16 | expect(r.err).toBe(null); 17 | expect(r.stdout).toMatch(/plugin-a/); 18 | }); 19 | test('should locate tsconfig relative to entry-point via ts-node-script', async () => { 20 | const r = await exec(`${BIN_SCRIPT_PATH} ../a/index`, { 21 | cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), 22 | }); 23 | expect(r.err).toBe(null); 24 | expect(r.stdout).toMatch(/plugin-a/); 25 | }); 26 | test('should locate tsconfig relative to entry-point with --script-mode', async () => { 27 | const r = await exec(`${BIN_PATH} --script-mode ../a/index`, { 28 | cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), 29 | }); 30 | expect(r.err).toBe(null); 31 | expect(r.stdout).toMatch(/plugin-a/); 32 | }); 33 | test('should locate tsconfig relative to cwd via ts-node-cwd', async () => { 34 | const r = await exec(`${BIN_CWD_PATH} ../a/index`, { 35 | cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), 36 | }); 37 | expect(r.err).toBe(null); 38 | expect(r.stdout).toMatch(/plugin-b/); 39 | }); 40 | test('should locate tsconfig relative to cwd in --cwd-mode', async () => { 41 | const r = await exec(`${BIN_PATH} --cwd-mode ../a/index`, { 42 | cwd: join(TEST_DIR, 'cwd-and-script-mode/b'), 43 | }); 44 | expect(r.err).toBe(null); 45 | expect(r.stdout).toMatch(/plugin-b/); 46 | }); 47 | test('should locate tsconfig relative to realpath, not symlink, when entrypoint is a symlink', async (t) => { 48 | if (lstatSync(join(TEST_DIR, 'main-realpath/symlink/symlink.tsx')).isSymbolicLink()) { 49 | const r = await exec(`${BIN_PATH} main-realpath/symlink/symlink.tsx`); 50 | expect(r.err).toBe(null); 51 | expect(r.stdout).toBe(''); 52 | } else { 53 | t.log('Skipping'); 54 | return; 55 | } 56 | }); 57 | -------------------------------------------------------------------------------- /src/test/create.spec.ts: -------------------------------------------------------------------------------- 1 | import { ctxTsNode } from './helpers'; 2 | import { context, expect } from './testlib'; 3 | 4 | const test = context(ctxTsNode); 5 | 6 | test.suite('create', ({ contextEach }) => { 7 | const test = contextEach(async (t) => { 8 | return { 9 | service: t.context.tsNodeUnderTest.create({ 10 | compilerOptions: { target: 'es5' }, 11 | skipProject: true, 12 | }), 13 | }; 14 | }); 15 | 16 | test('should create generic compiler instances', (t) => { 17 | const output = t.context.service.compile('const x = 10', 'test.ts'); 18 | expect(output).toMatch('var x = 10;'); 19 | }); 20 | 21 | test.suite('should get type information', (test) => { 22 | test('given position of identifier', (t) => { 23 | expect(t.context.service.getTypeInfo('/**jsdoc here*/const x = 10', 'test.ts', 21)).toEqual({ 24 | comment: 'jsdoc here', 25 | name: 'const x: 10', 26 | }); 27 | }); 28 | test('given position that does not point to an identifier', (t) => { 29 | expect(t.context.service.getTypeInfo('/**jsdoc here*/const x = 10', 'test.ts', 0)).toEqual({ 30 | comment: '', 31 | name: '', 32 | }); 33 | }); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /src/test/diagnostics.spec.ts: -------------------------------------------------------------------------------- 1 | import type { TSError } from '..'; 2 | import { ctxTsNode, ts } from './helpers'; 3 | import { context, expect } from './testlib'; 4 | import * as semver from 'semver'; 5 | import { once } from 'lodash'; 6 | const test = context(ctxTsNode); 7 | 8 | test.suite('TSError diagnostics', ({ context }) => { 9 | const test = context(async (t) => { 10 | // Locking to es2020, because: 11 | // 1) es2022 -- default in @tsconfig/bases for node18 -- changes this diagnostic 12 | // to be a composite "No overload matches this call." 13 | // 2) TS 4.2 doesn't support es2021 or higher 14 | const service = t.context.tsNodeUnderTest.create({ 15 | compilerOptions: { target: 'es5', lib: ['es2020'] }, 16 | skipProject: true, 17 | }); 18 | try { 19 | service.compile('new Error(123)', 'test.ts'); 20 | } catch (err) { 21 | return { err: err as TSError }; 22 | } 23 | return { err: undefined }; 24 | }); 25 | 26 | const diagnosticCode = 2345; 27 | const diagnosticMessage = /Argument of type '.*?' is not assignable to parameter of type 'string( \| undefined)?'./; 28 | const diagnosticErrorMessage = 29 | /TS2345: Argument of type '.*?' is not assignable to parameter of type 'string( \| undefined)?'./; 30 | 31 | test('should throw errors', (t) => { 32 | const { err } = t.context; 33 | expect(err).toBeDefined(); 34 | expect(err!).toMatchObject({ 35 | message: expect.stringMatching(diagnosticErrorMessage), 36 | diagnosticText: expect.stringMatching(diagnosticErrorMessage), 37 | diagnosticCodes: [diagnosticCode], 38 | diagnostics: [ 39 | { 40 | code: diagnosticCode, 41 | start: 10, 42 | length: 3, 43 | messageText: expect.stringMatching(diagnosticMessage), 44 | }, 45 | ], 46 | }); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /src/test/helpers/command-lines.ts: -------------------------------------------------------------------------------- 1 | // Command lines 2 | 3 | import { BIN_PATH, PROJECT, PROJECT_TRANSPILE_ONLY } from './paths'; 4 | 5 | /** Default `ts-node --project` invocation */ 6 | export const CMD_TS_NODE_WITH_PROJECT_FLAG = `"${BIN_PATH}" --project "${PROJECT}"`; 7 | /** Default `ts-node --project` invocation with transpile-only */ 8 | export const CMD_TS_NODE_WITH_PROJECT_TRANSPILE_ONLY_FLAG = `"${BIN_PATH}" --project "${PROJECT_TRANSPILE_ONLY}"`; 9 | /** Default `ts-node` invocation without `--project` */ 10 | export const CMD_TS_NODE_WITHOUT_PROJECT_FLAG = `"${BIN_PATH}"`; 11 | export const CMD_ESM_LOADER_WITHOUT_PROJECT = `node --loader ts-node/esm`; 12 | //#endregion 13 | -------------------------------------------------------------------------------- /src/test/helpers/ctx-tmp-dir.ts: -------------------------------------------------------------------------------- 1 | import { tmpdir } from 'os'; 2 | import type { ExecutionContext } from '../testlib'; 3 | import { tempdirProject } from '@TypeStrong/fs-fixture-builder'; 4 | 5 | /** 6 | * This helpers gives you an empty directory in the OS temp directory, *outside* 7 | * of the git clone. 8 | * 9 | * Some tests must run in a directory that is *outside* of the git clone. 10 | * When TS and ts-node search for a tsconfig, they traverse up the filesystem. 11 | * If they run inside our git clone, they will find the root tsconfig.json, and 12 | * we do not always want that. 13 | */ 14 | export async function ctxTmpDirOutsideCheckout(t: ExecutionContext) { 15 | const fixture = tempdirProject({ 16 | name: 'ts-node-spec', 17 | rootDir: tmpdir(), 18 | }); 19 | return { 20 | tmpDir: fixture.cwd, 21 | fixture, 22 | }; 23 | } 24 | export namespace ctxTmpDirOutsideCheckout { 25 | export type Ctx = Awaited>; 26 | export type T = ExecutionContext; 27 | } 28 | 29 | export async function ctxTmpDir(t: ExecutionContext) { 30 | const fixture = tempdirProject('ts-node-spec'); 31 | return { 32 | fixture, 33 | tmpDir: fixture.cwd, 34 | }; 35 | } 36 | export namespace ctxTmpDir { 37 | export type Ctx = Awaited>; 38 | export type T = ExecutionContext; 39 | } 40 | -------------------------------------------------------------------------------- /src/test/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from './misc'; 2 | export * from './ctx-tmp-dir'; 3 | export * from './ctx-ts-node'; 4 | export * from './paths'; 5 | export * from './command-lines'; 6 | export * from './reset-node-environment'; 7 | export * from './version-checks'; 8 | export * from './exec'; 9 | -------------------------------------------------------------------------------- /src/test/helpers/misc.ts: -------------------------------------------------------------------------------- 1 | /** types from ts-node under test */ 2 | import type * as tsNodeTypes from '../../index'; 3 | import { TEST_DIR } from './paths'; 4 | import { join } from 'path'; 5 | import { promisify } from 'util'; 6 | import { createRequire } from 'module'; 7 | export { tsNodeTypes }; 8 | 9 | export const testsDirRequire = createRequire(join(TEST_DIR, 'index.js')); 10 | 11 | export const ts = testsDirRequire('typescript') as typeof import('typescript'); 12 | 13 | export const delay = promisify(setTimeout); 14 | 15 | /** Essentially Array:includes, but with tweaked types for checks on enums */ 16 | export function isOneOf(value: V, arrayOfPossibilities: ReadonlyArray) { 17 | return arrayOfPossibilities.includes(value as any); 18 | } 19 | -------------------------------------------------------------------------------- /src/test/helpers/paths.ts: -------------------------------------------------------------------------------- 1 | import { setFixturesRootDir } from '@TypeStrong/fs-fixture-builder'; 2 | import { join, resolve } from 'path'; 3 | 4 | //#region Paths 5 | export const ROOT_DIR = resolve(__dirname, '../../..'); 6 | export const DIST_DIR = resolve(__dirname, '../..'); 7 | export const TEST_DIR = join(__dirname, '../../../tests'); 8 | export const PROJECT = join(TEST_DIR, 'tsconfig.json'); 9 | export const PROJECT_TRANSPILE_ONLY = join(TEST_DIR, 'tsconfig-transpile-only.json'); 10 | export const BIN_PATH = join(TEST_DIR, 'node_modules/.bin/ts-node'); 11 | export const BIN_PATH_JS = join(TEST_DIR, 'node_modules/ts-node/dist/bin.js'); 12 | export const BIN_SCRIPT_PATH = join(TEST_DIR, 'node_modules/.bin/ts-node-script'); 13 | export const BIN_CWD_PATH = join(TEST_DIR, 'node_modules/.bin/ts-node-cwd'); 14 | export const BIN_ESM_PATH = join(TEST_DIR, 'node_modules/.bin/ts-node-esm'); 15 | 16 | process.chdir(TEST_DIR); 17 | setFixturesRootDir(TEST_DIR); 18 | //#endregion 19 | -------------------------------------------------------------------------------- /src/test/module-node/1778.spec.ts: -------------------------------------------------------------------------------- 1 | import { createExec } from '../helpers/exec'; 2 | import { ctxTsNode, TEST_DIR, tsSupportsStableNodeNextNode16, CMD_TS_NODE_WITHOUT_PROJECT_FLAG } from '../helpers'; 3 | import { context, expect } from '../testlib'; 4 | import { join } from 'path'; 5 | 6 | const exec = createExec({ 7 | cwd: TEST_DIR, 8 | }); 9 | 10 | const test = context(ctxTsNode); 11 | 12 | test.suite( 13 | 'Issue #1778: typechecker resolver should take importer\'s module type -- cjs or esm -- into account when resolving package.json "exports"', 14 | (test) => { 15 | test.if(tsSupportsStableNodeNextNode16); 16 | test('test', async () => { 17 | const r = await exec(`${CMD_TS_NODE_WITHOUT_PROJECT_FLAG} ./index.ts`, { 18 | cwd: join(TEST_DIR, '1778'), 19 | }); 20 | expect(r.err).toBe(null); 21 | expect(r.stdout).toBe('{ esm: true }\n'); 22 | }); 23 | } 24 | ); 25 | -------------------------------------------------------------------------------- /src/test/reminders.spec.ts: -------------------------------------------------------------------------------- 1 | // Reminders about chores to stay up-to-date with the ecosystem 2 | 3 | import { ts, tsSupportsStableNodeNextNode16 } from './helpers'; 4 | import { expect, test } from './testlib'; 5 | 6 | test('Detect when typescript adds new ModuleKind values; flag as a failure so we can update our code flagged [MUST_UPDATE_FOR_NEW_MODULEKIND]', async () => { 7 | // We have marked a few places in our code with MUST_UPDATE_FOR_NEW_MODULEKIND to make it easier to update them when TS adds new ModuleKinds 8 | const foundKeys: string[] = []; 9 | function check(value: number, name: string, required: boolean) { 10 | if (required) expect(ts.ModuleKind[name as any]).toBe(value); 11 | if (ts.ModuleKind[value] === undefined) { 12 | expect(ts.ModuleKind[name as any]).toBeUndefined(); 13 | } else { 14 | expect(ts.ModuleKind[value]).toBe(name); 15 | foundKeys.push(name, `${value}`); 16 | } 17 | } 18 | check(0, 'None', true); 19 | check(1, 'CommonJS', true); 20 | check(2, 'AMD', true); 21 | check(3, 'UMD', true); 22 | check(4, 'System', true); 23 | check(5, 'ES2015', true); 24 | try { 25 | check(6, 'ES2020', false); 26 | check(99, 'ESNext', true); 27 | } catch { 28 | // the value changed: is `99` now, but was `6` in TS 2.7 29 | check(6, 'ESNext', true); 30 | expect(ts.ModuleKind[99]).toBeUndefined(); 31 | } 32 | check(7, 'ES2022', false); 33 | if (tsSupportsStableNodeNextNode16) { 34 | check(100, 'Node16', true); 35 | } else { 36 | check(100, 'Node12', false); 37 | } 38 | check(199, 'NodeNext', false); 39 | const actualKeys = Object.keys(ts.ModuleKind); 40 | actualKeys.sort(); 41 | foundKeys.sort(); 42 | expect(actualKeys).toEqual(foundKeys); 43 | }); 44 | -------------------------------------------------------------------------------- /src/test/remove-env-var-force-color.js: -------------------------------------------------------------------------------- 1 | // Eagerly load `expect` so it picks up the env var 2 | require('expect'); 3 | delete process.env.FORCE_COLOR; 4 | -------------------------------------------------------------------------------- /src/test/repl/helpers/macros.ts: -------------------------------------------------------------------------------- 1 | import type { ctxRepl, ExecuteInReplOptions } from './ctx-repl'; 2 | import { expect, test } from '../../testlib'; 3 | 4 | export const macroReplNoErrorsAndStdoutContains = test.macro( 5 | (script: string, contains: string, options?: Partial) => async (t: ctxRepl.T) => { 6 | macroReplInternal(t, script, contains, undefined, contains, options); 7 | } 8 | ); 9 | export const macroReplStderrContains = test.macro( 10 | (script: string, errorContains: string, options?: Partial) => async (t: ctxRepl.T) => { 11 | macroReplInternal(t, script, undefined, errorContains, errorContains, options); 12 | } 13 | ); 14 | 15 | async function macroReplInternal( 16 | t: ctxRepl.T, 17 | script: string, 18 | stdoutContains: string | undefined, 19 | stderrContains: string | undefined, 20 | waitPattern: string, 21 | options?: Partial 22 | ) { 23 | const r = await t.context.executeInRepl(script, { 24 | registerHooks: true, 25 | startInternalOptions: { useGlobal: false }, 26 | waitPattern, 27 | ...options, 28 | }); 29 | if (stderrContains) expect(r.stderr).toContain(stderrContains); 30 | else expect(r.stderr).toBe(''); 31 | if (stdoutContains) expect(r.stdout).toContain(stdoutContains); 32 | } 33 | -------------------------------------------------------------------------------- /src/test/repl/helpers/misc.ts: -------------------------------------------------------------------------------- 1 | import { tsNodeTypes, tsSupportsMtsCtsExtensions } from '../../helpers'; 2 | 3 | export const replFile = tsSupportsMtsCtsExtensions ? '.cts' : '.ts'; 4 | -------------------------------------------------------------------------------- /src/test/sourcemaps.spec.ts: -------------------------------------------------------------------------------- 1 | import * as expect from 'expect'; 2 | import { createExec, createExecTester, CMD_TS_NODE_WITH_PROJECT_FLAG, ctxTsNode, TEST_DIR } from './helpers'; 3 | import { context } from './testlib'; 4 | const test = context(ctxTsNode); 5 | 6 | const exec = createExecTester({ 7 | cmd: CMD_TS_NODE_WITH_PROJECT_FLAG, 8 | exec: createExec({ 9 | cwd: TEST_DIR, 10 | }), 11 | }); 12 | 13 | test('Redirects source-map-support to @cspotcode/source-map-support so that third-party libraries get correct source-mapped locations', async () => { 14 | const r = await exec({ 15 | flags: `./legacy-source-map-support-interop/index.ts`, 16 | }); 17 | expect(r.err).toBeNull(); 18 | expect(r.stdout.split('\n')).toMatchObject([ 19 | expect.stringContaining('.ts:2 '), 20 | 'true', 21 | 'true', 22 | expect.stringContaining('.ts:100:'), 23 | expect.stringContaining('.ts:101 '), 24 | '', 25 | ]); 26 | }); 27 | -------------------------------------------------------------------------------- /src/test/test-loader.d.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | declare global { 3 | namespace NodeJS { 4 | interface Process { 5 | __test_setloader__(hooks: any): void; 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/test/test-loader.mjs: -------------------------------------------------------------------------------- 1 | // Grant ourselves the ability to install ESM loader behaviors in-process during tests 2 | import semver from 'semver'; 3 | 4 | const newHooksAPI = semver.gte(process.versions.node, '16.12.0'); 5 | 6 | let hooks = undefined; 7 | process.__test_setloader__ = function (_hooks) { 8 | hooks = _hooks; 9 | }; 10 | function createHook(name) { 11 | return function (a, b, c) { 12 | const target = (hooks && hooks[name]) || c; 13 | return target(...arguments); 14 | }; 15 | } 16 | export const resolve = createHook('resolve'); 17 | export const load = newHooksAPI ? createHook('load') : null; 18 | export const getFormat = !newHooksAPI ? createHook('getFormat') : null; 19 | export const transformSource = !newHooksAPI ? createHook('transformSource') : null; 20 | -------------------------------------------------------------------------------- /src/test/testlib.ts: -------------------------------------------------------------------------------- 1 | // HACK ensure ts-node-specific bootstrapping is executed 2 | import './helpers'; 3 | 4 | export * from '@cspotcode/ava-lib'; 5 | -------------------------------------------------------------------------------- /src/test/transpile-only.spec.ts: -------------------------------------------------------------------------------- 1 | import { createExec } from './helpers/exec'; 2 | import { ctxTsNode, tsSupportsVerbatimModuleSyntax } from './helpers'; 3 | import { CMD_TS_NODE_WITH_PROJECT_FLAG } from './helpers/command-lines'; 4 | import { TEST_DIR } from './helpers/paths'; 5 | import { expect, context } from './testlib'; 6 | 7 | const test = context(ctxTsNode); 8 | 9 | const exec = createExec({ 10 | cwd: TEST_DIR, 11 | }); 12 | 13 | test('should support transpile only mode', async () => { 14 | const r = await exec(`${CMD_TS_NODE_WITH_PROJECT_FLAG} --transpile-only -pe "x"`); 15 | if (r.err === null) { 16 | throw new Error('Command was expected to fail, but it succeeded.'); 17 | } 18 | 19 | expect(r.err.message).toMatch('ReferenceError: x is not defined'); 20 | }); 21 | 22 | test('should throw error even in transpileOnly mode', async () => { 23 | const r = await exec(`${CMD_TS_NODE_WITH_PROJECT_FLAG} --transpile-only -pe "console."`); 24 | if (r.err === null) { 25 | throw new Error('Command was expected to fail, but it succeeded.'); 26 | } 27 | 28 | expect(r.err.message).toMatch('error TS1003: Identifier expected'); 29 | }); 30 | 31 | test.suite('verbatimModuleSyntax w/transpileOnly should not raise configuration diagnostic', (test) => { 32 | test.if(tsSupportsVerbatimModuleSyntax); 33 | test('test', async (t) => { 34 | // Mixing verbatimModuleSyntax w/transpileOnly 35 | // https://github.com/TypeStrong/ts-node/issues/1971 36 | // We should *not* get: 37 | // "error TS5104: Option 'isolatedModules' is redundant and cannot be specified with option 'verbatimModuleSyntax'." 38 | const service = t.context.tsNodeUnderTest.create({ 39 | transpileOnly: true, 40 | compilerOptions: { verbatimModuleSyntax: true }, 41 | }); 42 | service.compile('const foo: string = 123', 'module.ts'); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /src/test/ts-import-specifiers.spec.ts: -------------------------------------------------------------------------------- 1 | import { context } from './testlib'; 2 | import * as expect from 'expect'; 3 | import { createExec } from './helpers/exec'; 4 | import { TEST_DIR, ctxTsNode, CMD_TS_NODE_WITHOUT_PROJECT_FLAG, tsSupportsAllowImportingTsExtensions } from './helpers'; 5 | import { project as fsProject } from '@TypeStrong/fs-fixture-builder'; 6 | import { outdent as o } from 'outdent'; 7 | 8 | const exec = createExec({ 9 | cwd: TEST_DIR, 10 | }); 11 | 12 | const test = context(ctxTsNode); 13 | 14 | test('Supports .ts extensions in import specifiers with typechecking, even though older versions of TS checker do not', async () => { 15 | const p = fsProject('ts-import-specifiers'); 16 | p.rm(); 17 | p.addFile( 18 | 'index.ts', 19 | o` 20 | import { foo } from './foo.ts'; 21 | import { bar } from './bar.jsx'; 22 | console.log({ foo, bar }); 23 | ` 24 | ); 25 | p.addFile( 26 | 'foo.ts', 27 | o` 28 | export const foo = true; 29 | ` 30 | ); 31 | p.addFile( 32 | 'bar.tsx', 33 | o` 34 | export const bar = true; 35 | ` 36 | ); 37 | p.addJsonFile('tsconfig.json', { 38 | 'ts-node': { 39 | // Can eventually make this a stable feature. For now, `experimental` flag allows me to iterate quickly 40 | experimentalTsImportSpecifiers: true, 41 | experimentalResolver: true, 42 | }, 43 | compilerOptions: { 44 | jsx: 'react', 45 | allowImportingTsExtensions: tsSupportsAllowImportingTsExtensions ? true : undefined, 46 | }, 47 | }); 48 | p.write(); 49 | 50 | const r = await exec(`${CMD_TS_NODE_WITHOUT_PROJECT_FLAG} ./index.ts`, { 51 | cwd: p.cwd, 52 | }); 53 | expect(r.err).toBe(null); 54 | expect(r.stdout.trim()).toBe('{ foo: true, bar: true }'); 55 | }); 56 | -------------------------------------------------------------------------------- /src/transpilers/types.ts: -------------------------------------------------------------------------------- 1 | import type * as ts from 'typescript'; 2 | import type { NodeModuleEmitKind, Service } from '../index'; 3 | import type { ProjectLocalResolveHelper } from '../util'; 4 | 5 | /** 6 | * Third-party transpilers are implemented as a CommonJS module with a 7 | * named export "create" 8 | * 9 | * @category Transpiler 10 | */ 11 | export interface TranspilerModule { 12 | create: TranspilerFactory; 13 | } 14 | /** 15 | * Called by ts-node to create a custom transpiler. 16 | * 17 | * @category Transpiler 18 | */ 19 | export type TranspilerFactory = (options: CreateTranspilerOptions) => Transpiler; 20 | /** @category Transpiler */ 21 | export interface CreateTranspilerOptions { 22 | // TODO this is confusing because its only a partial Service. Rename? 23 | // Careful: must avoid stripInternal breakage by guarding with Extract<> 24 | service: Pick>; 25 | /** 26 | * If `"transpiler"` option is declared in an "extends" tsconfig, this path might be different than 27 | * the `projectLocalResolveHelper` 28 | * 29 | * @internal 30 | */ 31 | transpilerConfigLocalResolveHelper: ProjectLocalResolveHelper; 32 | /** 33 | * When using `module: nodenext` or `module: node12`, there are two possible styles of emit: 34 | * - CommonJS with dynamic imports preserved (not transformed into `require()` calls) 35 | * - ECMAScript modules with `import foo = require()` transformed into `require = createRequire(); const foo = require()` 36 | * @internal 37 | */ 38 | nodeModuleEmitKind?: NodeModuleEmitKind; 39 | } 40 | /** @category Transpiler */ 41 | export interface Transpiler { 42 | // TODOs 43 | // Create spec for returning diagnostics? Currently transpilers are allowed to 44 | // throw an error but that's it. 45 | transpile(input: string, options: TranspileOptions): TranspileOutput; 46 | } 47 | /** @category Transpiler */ 48 | export interface TranspileOptions { 49 | fileName: string; 50 | } 51 | /** @category Transpiler */ 52 | export interface TranspileOutput { 53 | outputText: string; 54 | diagnostics?: ts.Diagnostic[]; 55 | sourceMapText?: string; 56 | } 57 | -------------------------------------------------------------------------------- /src/tsconfig-schema.ts: -------------------------------------------------------------------------------- 1 | import type { TsConfigOptions } from './index'; 2 | 3 | /* 4 | * This interface exists solely for generating a JSON schema for tsconfig.json. 5 | * We do *not* extend the compiler's tsconfig interface. Instead we handle that 6 | * on a schema level, via "allOf", so we pull in the same schema that VSCode 7 | * already uses. 8 | */ 9 | /** 10 | * tsconfig schema which includes "ts-node" options. 11 | * @allOf [{"$ref": "https://schemastore.azurewebsites.net/schemas/json/tsconfig.json"}] 12 | */ 13 | export interface TsConfigSchema { 14 | /** 15 | * ts-node options. See also: https://typestrong.org/ts-node/docs/configuration 16 | * 17 | * ts-node offers TypeScript execution and REPL for node.js, with source map support. 18 | */ 19 | 'ts-node': TsConfigOptions; 20 | } 21 | -------------------------------------------------------------------------------- /src/tsconfigs.ts: -------------------------------------------------------------------------------- 1 | import type { TSCommon, TSInternal } from './ts-compiler-types'; 2 | 3 | const nodeMajor = parseInt(process.versions.node.split('.')[0], 10); 4 | /** 5 | * return parsed JSON of the bundled @tsconfig/bases config appropriate for the 6 | * running version of nodejs 7 | * @internal 8 | */ 9 | export function getDefaultTsconfigJsonForNodeVersion(ts: TSCommon): any { 10 | const tsInternal = ts as any as TSInternal; 11 | if (nodeMajor >= 20) { 12 | const config = require('@tsconfig/node20/tsconfig.json'); 13 | if (configCompatible(config)) return config; 14 | } 15 | if (nodeMajor >= 18) { 16 | const config = require('@tsconfig/node18/tsconfig.json'); 17 | if (configCompatible(config)) return config; 18 | } 19 | if (nodeMajor >= 16) { 20 | const config = require('@tsconfig/node16/tsconfig.json'); 21 | if (configCompatible(config)) return config; 22 | } 23 | { 24 | const config = require('@tsconfig/node14/tsconfig.json'); 25 | if (configCompatible(config)) return config; 26 | } 27 | // Old TypeScript compilers may be incompatible with *all* @tsconfig/node* configs, 28 | // so fallback to nothing 29 | return {}; 30 | 31 | // Verify that tsconfig target and lib options are compatible with TypeScript compiler 32 | function configCompatible(config: { 33 | compilerOptions: { 34 | lib: string[]; 35 | target: string; 36 | module: string; 37 | moduleResolution: string; 38 | }; 39 | }) { 40 | const results = ts.parseJsonConfigFileContent( 41 | { 42 | compilerOptions: config.compilerOptions, 43 | files: ['foo.ts'], 44 | }, 45 | parseConfigHost, 46 | '' 47 | ); 48 | return results.errors.length === 0; 49 | } 50 | } 51 | 52 | const parseConfigHost = { 53 | useCaseSensitiveFileNames: false, 54 | readDirectory( 55 | rootDir: string, 56 | extensions: readonly string[], 57 | excludes: readonly string[] | undefined, 58 | includes: readonly string[], 59 | depth?: number 60 | ) { 61 | return []; 62 | }, 63 | fileExists(path: string) { 64 | return false; 65 | }, 66 | readFile(path: string) { 67 | return ''; 68 | }, 69 | }; 70 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | !from-node-modules/node_modules/ 2 | package-lock.json 3 | ts-node-packed.tgz 4 | /tmp 5 | -------------------------------------------------------------------------------- /tests/.yarnrc.yml: -------------------------------------------------------------------------------- 1 | enableGlobalCache: false 2 | enableMirror: false 3 | 4 | nmMode: hardlinks-global 5 | 6 | nodeLinker: node-modules 7 | 8 | plugins: 9 | - path: ../.yarn/plugins/@yarnpkg/plugin-compat.cjs 10 | spec: ../.yarn/plugins/@yarnpkg/plugin-compat.cjs 11 | 12 | yarnPath: ../.yarn/releases/yarn-3.4.1.cjs 13 | 14 | nmHoistingLimits: workspaces 15 | -------------------------------------------------------------------------------- /tests/1488/index.js: -------------------------------------------------------------------------------- 1 | console.log('foo'); 2 | -------------------------------------------------------------------------------- /tests/1488/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /tests/1488/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true 4 | }, 5 | "ts-node": { 6 | "skipIgnore": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/1778/index.ts: -------------------------------------------------------------------------------- 1 | import foo from 'foo'; 2 | 3 | // This file is ESM, so if typechecker's resolver is working correctly, will 4 | // resolve to the foo's package.json "exports" mapping for "default", not "require" 5 | const bar: { esm: true } = foo; 6 | console.log(bar); 7 | -------------------------------------------------------------------------------- /tests/1778/node_modules/foo/cjs/index.d.ts: -------------------------------------------------------------------------------- 1 | declare const foo: {cjs: true} 2 | export default foo 3 | -------------------------------------------------------------------------------- /tests/1778/node_modules/foo/cjs/index.js: -------------------------------------------------------------------------------- 1 | module.exports = {cjs: true} 2 | -------------------------------------------------------------------------------- /tests/1778/node_modules/foo/cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "commonjs" 3 | } 4 | -------------------------------------------------------------------------------- /tests/1778/node_modules/foo/esm/index.d.ts: -------------------------------------------------------------------------------- 1 | declare const foo: {esm: true} 2 | export default foo 3 | -------------------------------------------------------------------------------- /tests/1778/node_modules/foo/esm/index.js: -------------------------------------------------------------------------------- 1 | export default {esm: true} 2 | -------------------------------------------------------------------------------- /tests/1778/node_modules/foo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "exports": { 4 | ".": { 5 | "require": "./cjs/index.js", 6 | "default": "./esm/index.js" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/1778/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/1778/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "esm": true 4 | }, 5 | "compilerOptions": { 6 | "module": "NodeNext", 7 | "noEmit": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/1996/empty.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | -------------------------------------------------------------------------------- /tests/1996/index.ts: -------------------------------------------------------------------------------- 1 | import * as empty from './empty'; 2 | empty; 3 | console.log('#1996 regression test.'); 4 | -------------------------------------------------------------------------------- /tests/1996/transpiler.js: -------------------------------------------------------------------------------- 1 | // A custom transpiler that returns `undefined` instead of a sourcemap, which is 2 | // allowed according to our typedefs. 3 | 4 | exports.create = function () { 5 | return { 6 | transpile(input, options) { 7 | return { 8 | outputText: 'console.log("#1996 regression test with custom transpiler.")', 9 | sourceMapText: undefined, 10 | }; 11 | }, 12 | }; 13 | }; 14 | -------------------------------------------------------------------------------- /tests/1996/tsconfig.custom-transpiler.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "transpileOnly": true, 4 | "transpiler": "./transpiler.js" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/1996/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "swc": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/2076/node_modules/custom-tsconfig/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": {} 3 | } 4 | -------------------------------------------------------------------------------- /tests/2076/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "custom-tsconfig/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /tests/allow-js/run.js: -------------------------------------------------------------------------------- 1 | export function main() { 2 | return 'hello world'; 3 | } 4 | -------------------------------------------------------------------------------- /tests/allow-js/with-jsx.jsx: -------------------------------------------------------------------------------- 1 | export class Foo2 { 2 | static sayHi() { 3 | return 'hello world'; 4 | } 5 | 6 | render() { 7 | return
; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/child-process.ts: -------------------------------------------------------------------------------- 1 | import { join } from 'path'; 2 | import { fork } from 'child_process'; 3 | 4 | fork(join(__dirname, 'hello-world.ts')); 5 | -------------------------------------------------------------------------------- /tests/compiler-error.ts: -------------------------------------------------------------------------------- 1 | function upper(str: string) { 2 | return str.toUpperCase(); 3 | } 4 | 5 | upper(10); 6 | -------------------------------------------------------------------------------- /tests/complex/example.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./foo').text; 2 | -------------------------------------------------------------------------------- /tests/complex/foo.ts: -------------------------------------------------------------------------------- 1 | export const text = 'example'; 2 | -------------------------------------------------------------------------------- /tests/complex/index.ts: -------------------------------------------------------------------------------- 1 | declare function require(module: string): any; 2 | 3 | export function example() { 4 | return require('./example'); 5 | } 6 | -------------------------------------------------------------------------------- /tests/custom-types.ts: -------------------------------------------------------------------------------- 1 | import { foobar } from 'does-not-exist'; 2 | 3 | console.log(foobar); 4 | -------------------------------------------------------------------------------- /tests/cwd-and-script-mode/a/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | // Type assertion to please TS 2.7 3 | const register = process[(Symbol as any).for('ts-node.register.instance')]; 4 | console.log( 5 | JSON.stringify({ 6 | options: register.options, 7 | config: register.config, 8 | }) 9 | ); 10 | -------------------------------------------------------------------------------- /tests/cwd-and-script-mode/a/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "transpileOnly": true 4 | }, 5 | "compilerOptions": { 6 | "plugins": [ 7 | { 8 | "name": "plugin-a" 9 | } 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/cwd-and-script-mode/b/index.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | // Type assertion to please TS 2.7 3 | const register = process[(Symbol as any).for('ts-node.register.instance')]; 4 | console.log( 5 | JSON.stringify({ 6 | options: register.options, 7 | config: register.config, 8 | }) 9 | ); 10 | -------------------------------------------------------------------------------- /tests/cwd-and-script-mode/b/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "transpileOnly": true 4 | }, 5 | "compilerOptions": { 6 | "plugins": [ 7 | { 8 | "name": "plugin-b" 9 | } 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/emit-compiled.ts: -------------------------------------------------------------------------------- 1 | const extensions = ['.tsx']; 2 | 3 | extensions.forEach((ext) => { 4 | const old = require.extensions[ext]; 5 | 6 | require.extensions[ext] = (m, path) => { 7 | const _compile = (m as any)._compile; 8 | 9 | (m as any)._compile = (code, path) => { 10 | console.error(code); 11 | return _compile.call(this, code, path); 12 | }; 13 | 14 | return old(m, path); 15 | }; 16 | }); 17 | -------------------------------------------------------------------------------- /tests/emit-skipped-fallback/outside-rootDir/foo.js: -------------------------------------------------------------------------------- 1 | // This file causes TS to return emitSkipped because it's outside of rootDir and 2 | // it's .js. I assume this happens because the emit path is the same as the 3 | // input path, and perhaps also because the file is classified "external" 4 | 5 | const decorator = () => {}; 6 | 7 | class Foo { 8 | // Using a decorator to prove this .js file is getting compiled 9 | @decorator 10 | method() { 11 | return 'foo'; 12 | } 13 | } 14 | 15 | console.log(new Foo().method()); 16 | -------------------------------------------------------------------------------- /tests/emit-skipped-fallback/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "experimentalDecorators": true, 5 | "rootDir": "rootDir" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/empty.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/tests/empty.ts -------------------------------------------------------------------------------- /tests/env.ts: -------------------------------------------------------------------------------- 1 | console.log(typeof (process as any)[Symbol.for('ts-node.register.instance')]); 2 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-js/index.ts: -------------------------------------------------------------------------------- 1 | import { fork } from 'child_process'; 2 | import { dirname } from 'path'; 3 | import { fileURLToPath } from 'url'; 4 | 5 | // Initially set the exit code to non-zero. We only set it to `0` when the 6 | // worker process finishes properly with the expected stdout message. 7 | process.exitCode = 1; 8 | 9 | process.chdir(dirname(fileURLToPath(import.meta.url))); 10 | 11 | const workerProcess = fork('./worker.js', [], { 12 | stdio: 'pipe', 13 | }); 14 | 15 | let stdout = ''; 16 | 17 | workerProcess.stdout.on('data', (chunk) => (stdout += chunk.toString('utf8'))); 18 | workerProcess.on('error', () => (process.exitCode = 1)); 19 | workerProcess.on('close', (status, signal) => { 20 | if (status === 0 && signal === null && stdout.trim() === 'Works') { 21 | console.log('Passing: from main'); 22 | process.exitCode = 0; 23 | } 24 | }); 25 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-js/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext" 4 | }, 5 | "ts-node": { 6 | "swc": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-js/worker.js: -------------------------------------------------------------------------------- 1 | console.log('Works'); 2 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-ts-abs/index.ts: -------------------------------------------------------------------------------- 1 | import { fork } from 'child_process'; 2 | import { dirname, join } from 'path'; 3 | import { fileURLToPath } from 'url'; 4 | 5 | // Initially set the exit code to non-zero. We only set it to `0` when the 6 | // worker process finishes properly with the expected stdout message. 7 | process.exitCode = 1; 8 | 9 | const workerProcess = fork(join(dirname(fileURLToPath(import.meta.url)), 'subfolder/worker.ts'), [], { 10 | stdio: 'pipe', 11 | }); 12 | 13 | let stdout = ''; 14 | 15 | workerProcess.stdout.on('data', (chunk) => (stdout += chunk.toString('utf8'))); 16 | workerProcess.on('error', () => (process.exitCode = 1)); 17 | workerProcess.on('close', (status, signal) => { 18 | if (status === 0 && signal === null && stdout.trim() === 'Works') { 19 | console.log('Passing: from main'); 20 | process.exitCode = 0; 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-ts-abs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-ts-abs/subfolder/worker.ts: -------------------------------------------------------------------------------- 1 | const message: string = 'Works'; 2 | 3 | console.log(message); 4 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-ts-abs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext" 4 | }, 5 | "ts-node": { 6 | "swc": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-ts/index.ts: -------------------------------------------------------------------------------- 1 | import { fork } from 'child_process'; 2 | import { dirname, join } from 'path'; 3 | import { fileURLToPath } from 'url'; 4 | 5 | // Initially set the exit code to non-zero. We only set it to `0` when the 6 | // worker process finishes properly with the expected stdout message. 7 | process.exitCode = 1; 8 | 9 | process.chdir(join(dirname(fileURLToPath(import.meta.url)), 'subfolder')); 10 | 11 | const workerProcess = fork('./worker.ts', [], { 12 | stdio: 'pipe', 13 | }); 14 | 15 | let stdout = ''; 16 | 17 | workerProcess.stdout.on('data', (chunk) => (stdout += chunk.toString('utf8'))); 18 | workerProcess.on('error', () => (process.exitCode = 1)); 19 | workerProcess.on('close', (status, signal) => { 20 | if (status === 0 && signal === null && stdout.trim() === 'Works') { 21 | console.log('Passing: from main'); 22 | process.exitCode = 0; 23 | } 24 | }); 25 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-ts/subfolder/worker.ts: -------------------------------------------------------------------------------- 1 | const message: string = 'Works'; 2 | 3 | console.log(message); 4 | -------------------------------------------------------------------------------- /tests/esm-child-process/process-forking-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext" 4 | }, 5 | "ts-node": { 6 | "swc": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/esm-child-process/via-flag/index.ts: -------------------------------------------------------------------------------- 1 | import { strictEqual } from 'assert'; 2 | strictEqual(import.meta.url.includes('index.ts'), true); 3 | console.log(`CLI args: ${process.argv.slice(2).join(' ')}`); 4 | -------------------------------------------------------------------------------- /tests/esm-child-process/via-flag/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm-child-process/via-flag/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "esModuleInterop": true 5 | }, 6 | "ts-node": { 7 | "swc": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/esm-child-process/via-tsconfig/index.ts: -------------------------------------------------------------------------------- 1 | import { strictEqual } from 'assert'; 2 | strictEqual(import.meta.url.includes('index.ts'), true); 3 | console.log(`CLI args: ${process.argv.slice(2).join(' ')}`); 4 | -------------------------------------------------------------------------------- /tests/esm-child-process/via-tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm-child-process/via-tsconfig/sleep.ts: -------------------------------------------------------------------------------- 1 | setTimeout(function () { 2 | console.log('Slept 30 seconds'); 3 | process.exit(456); 4 | }, 30e3); 5 | process.on('SIGTERM', onSignal); 6 | process.on('SIGINT', onSignal); 7 | console.log('child registered signal handlers'); 8 | function onSignal(signal: string) { 9 | console.log(`child received signal: ${signal}`); 10 | setTimeout(() => { 11 | console.log(`child exiting`); 12 | process.exit(123); 13 | }, 1e3); 14 | } 15 | -------------------------------------------------------------------------------- /tests/esm-child-process/via-tsconfig/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "esModuleInterop": true 5 | }, 6 | "ts-node": { 7 | "esm": true, 8 | "swc": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/esm-custom-loader/index.ts: -------------------------------------------------------------------------------- 1 | export function abc() { 2 | let unusedVar: string; 3 | return true; 4 | } 5 | -------------------------------------------------------------------------------- /tests/esm-custom-loader/loader.mjs: -------------------------------------------------------------------------------- 1 | import { fileURLToPath } from 'url'; 2 | import { createRequire } from 'module'; 3 | const require = createRequire(fileURLToPath(import.meta.url)); 4 | 5 | /** @type {import('../../dist')} **/ 6 | const { createEsmHooks, register } = require('ts-node'); 7 | 8 | const tsNodeInstance = register({ 9 | compilerOptions: { 10 | noUnusedLocals: true, 11 | }, 12 | }); 13 | 14 | export const { resolve, getFormat, transformSource, load } = createEsmHooks(tsNodeInstance); 15 | -------------------------------------------------------------------------------- /tests/esm-custom-loader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm-custom-loader/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "moduleResolution": "node", 5 | "noUnusedLocals": false 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/esm-err-require-esm/esm-package/loaded-as.ts: -------------------------------------------------------------------------------- 1 | // Log if this file is loaded as ESM or CommonJS 2 | if (typeof module !== 'undefined') console.log('CommonJS'); 3 | else console.log('ESM'); 4 | -------------------------------------------------------------------------------- /tests/esm-err-require-esm/esm-package/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm-err-require-esm/index.js: -------------------------------------------------------------------------------- 1 | require('./esm-package/loaded-as'); 2 | -------------------------------------------------------------------------------- /tests/esm-import-assertions/car.json: -------------------------------------------------------------------------------- 1 | { 2 | "color": "fuchsia", 3 | "doors": "open", 4 | "seats": 2 5 | } 6 | -------------------------------------------------------------------------------- /tests/esm-import-assertions/importJson.ts: -------------------------------------------------------------------------------- 1 | import carData from './car.json' assert { type: 'json' }; 2 | 3 | if (carData.color !== 'fuchsia') throw new Error('failed to import json'); 4 | 5 | const { default: dynamicCarData } = await import('./car.json', { 6 | assert: { type: 'json' }, 7 | }); 8 | 9 | if (dynamicCarData.doors !== 'open') throw new Error('failed to dynamically import json'); 10 | 11 | console.log(`A ${carData.color} car has ${carData.seats} seats and the doors are ${dynamicCarData.doors}.`); 12 | 13 | // Test that omitting the assertion causes node to throw an error 14 | await import('./car.json').then( 15 | () => { 16 | throw new Error('should have thrown'); 17 | }, 18 | (error: any) => { 19 | if (error.code !== 'ERR_IMPORT_ASSERTION_TYPE_MISSING') { 20 | throw error; 21 | } 22 | /* error is expected */ 23 | } 24 | ); 25 | console.log('Done!'); 26 | -------------------------------------------------------------------------------- /tests/esm-import-assertions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm-import-assertions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "transpileOnly": true 4 | }, 5 | "compilerOptions": { 6 | "module": "ESNext", 7 | "target": "ESNext", 8 | "resolveJsonModule": true, 9 | "allowJs": true, 10 | "moduleResolution": "node", 11 | "allowSyntheticDefaultImports": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/esm-import-cache/index.ts: -------------------------------------------------------------------------------- 1 | import './log1.js'; 2 | import './log1.js'; 3 | import './log2.js'; 4 | import './log2.js?bust'; 5 | -------------------------------------------------------------------------------- /tests/esm-import-cache/log1.ts: -------------------------------------------------------------------------------- 1 | console.log('log1'); 2 | -------------------------------------------------------------------------------- /tests/esm-import-cache/log2.ts: -------------------------------------------------------------------------------- 1 | console.log('log2'); 2 | -------------------------------------------------------------------------------- /tests/esm-import-cache/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm-import-cache/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "allowJs": true, 5 | "moduleResolution": "node" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/esm-import-http-url/index.mjs: -------------------------------------------------------------------------------- 1 | import 'http://example.com/this-url-should-be-ignored-by-our-esm-loader.js'; 2 | -------------------------------------------------------------------------------- /tests/esm-loader-context/index.mjs: -------------------------------------------------------------------------------- 1 | import * as moduleA from './moduleA.mjs'; 2 | import * as moduleB from './moduleB.mjs' assert { foo: 'bar' }; 3 | import * as jsonModule from './jsonModuleA.json' assert { type: 'json' }; 4 | 5 | await import('./moduleC.mjs'); 6 | await import('./moduleD.mjs', { foo: 'bar' }); 7 | await import('./jsonModuleB.json', { assert: { type: 'json' } }); 8 | -------------------------------------------------------------------------------- /tests/esm-loader-context/jsonModuleA.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /tests/esm-loader-context/jsonModuleB.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /tests/esm-loader-context/loader.mjs: -------------------------------------------------------------------------------- 1 | export function resolve(specifier, context, defaultResolve) { 2 | console.log(JSON.stringify({ resolveContextKeys: Object.keys(context) })); 3 | return defaultResolve(specifier, context); 4 | } 5 | export function load(url, context, defaultLoad) { 6 | console.log(JSON.stringify({ loadContextKeys: Object.keys(context) })); 7 | return defaultLoad(url, context); 8 | } 9 | -------------------------------------------------------------------------------- /tests/esm-loader-context/moduleA.mjs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/tests/esm-loader-context/moduleA.mjs -------------------------------------------------------------------------------- /tests/esm-loader-context/moduleB.mjs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/tests/esm-loader-context/moduleB.mjs -------------------------------------------------------------------------------- /tests/esm-loader-context/moduleC.mjs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/tests/esm-loader-context/moduleC.mjs -------------------------------------------------------------------------------- /tests/esm-loader-context/moduleD.mjs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/tests/esm-loader-context/moduleD.mjs -------------------------------------------------------------------------------- /tests/esm-loader-entrypoint-cjs-fallback/extensionless-entrypoint: -------------------------------------------------------------------------------- 1 | console.log('Hello world!'); 2 | -------------------------------------------------------------------------------- /tests/esm-loader-entrypoint-cjs-fallback/relies-upon-cjs-resolution/index.js: -------------------------------------------------------------------------------- 1 | console.log('Hello world!'); 2 | -------------------------------------------------------------------------------- /tests/esm-node-resolver/bar/index.ts: -------------------------------------------------------------------------------- 1 | export const bar: string = 'bar'; 2 | 3 | if (typeof module !== 'undefined') throw new Error('module should not exist in ESM'); 4 | -------------------------------------------------------------------------------- /tests/esm-node-resolver/baz.js: -------------------------------------------------------------------------------- 1 | export const baz = 'baz'; 2 | 3 | if (typeof module !== 'undefined') throw new Error('module should not exist in ESM'); 4 | -------------------------------------------------------------------------------- /tests/esm-node-resolver/biff.jsx: -------------------------------------------------------------------------------- 1 | export const biff = 'biff'; 2 | 3 | const React = { 4 | createElement() {}, 5 | }; 6 | const div =
; 7 | 8 | if (typeof module !== 'undefined') throw new Error('module should not exist in ESM'); 9 | -------------------------------------------------------------------------------- /tests/esm-node-resolver/foo.ts: -------------------------------------------------------------------------------- 1 | export const foo: string = 'foo'; 2 | 3 | if (typeof module !== 'undefined') throw new Error('module should not exist in ESM'); 4 | -------------------------------------------------------------------------------- /tests/esm-node-resolver/index.ts: -------------------------------------------------------------------------------- 1 | import { foo } from './foo'; 2 | import { bar } from './bar'; 3 | import { baz } from './baz'; 4 | import { biff } from './biff'; 5 | import { libfoo } from 'libfoo'; 6 | 7 | // Test import builtin modules 8 | import { readFileSync } from 'fs'; 9 | if (typeof readFileSync !== 'function') throw new Error('failed to import builtin module'); 10 | 11 | if (typeof module !== 'undefined') throw new Error('module should not exist in ESM'); 12 | 13 | console.log(`${foo} ${bar} ${baz} ${biff} ${libfoo}`); 14 | -------------------------------------------------------------------------------- /tests/esm-node-resolver/node_modules/libfoo/entrypoint.js: -------------------------------------------------------------------------------- 1 | export const libfoo = 'libfoo' 2 | -------------------------------------------------------------------------------- /tests/esm-node-resolver/node_modules/libfoo/index.d.ts: -------------------------------------------------------------------------------- 1 | // TypeScript does not yet support package.json "exports" 2 | export const libfoo: string 3 | -------------------------------------------------------------------------------- /tests/esm-node-resolver/node_modules/libfoo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "exports": { 4 | "import": "./entrypoint.js" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/esm-node-resolver/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm-node-resolver/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "allowJs": true, 5 | "jsx": "react", 6 | "moduleResolution": "node" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/esm-transpile-only/index.ts: -------------------------------------------------------------------------------- 1 | if (typeof module !== 'undefined') throw new Error('module should not exist in ESM'); 2 | 3 | // intentional type errors to check transpile-only ESM loader skips type checking 4 | parseInt(1101, 2); 5 | const x: number = 'hello world'; 6 | -------------------------------------------------------------------------------- /tests/esm-transpile-only/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm-transpile-only/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "allowJs": true, 5 | "jsx": "react" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/esm/bar.ts: -------------------------------------------------------------------------------- 1 | export const bar: string = 'bar'; 2 | 3 | if (typeof module !== 'undefined') throw new Error('module should not exist in ESM'); 4 | -------------------------------------------------------------------------------- /tests/esm/baz.js: -------------------------------------------------------------------------------- 1 | export const baz = 'baz'; 2 | 3 | if (typeof module !== 'undefined') throw new Error('module should not exist in ESM'); 4 | -------------------------------------------------------------------------------- /tests/esm/biff.jsx: -------------------------------------------------------------------------------- 1 | export const biff = 'biff'; 2 | 3 | const React = { 4 | createElement() {}, 5 | }; 6 | const div =
; 7 | 8 | if (typeof module !== 'undefined') throw new Error('module should not exist in ESM'); 9 | -------------------------------------------------------------------------------- /tests/esm/foo.ts: -------------------------------------------------------------------------------- 1 | export const foo: string = 'foo'; 2 | 3 | if (typeof module !== 'undefined') throw new Error('module should not exist in ESM'); 4 | -------------------------------------------------------------------------------- /tests/esm/index.ts: -------------------------------------------------------------------------------- 1 | import { foo } from './foo.js'; 2 | import { bar } from './bar.js'; 3 | import { baz } from './baz.js'; 4 | import { biff } from './biff.js'; 5 | import { libfoo } from 'libfoo'; 6 | 7 | // Test import builtin modules 8 | import { readFileSync } from 'fs'; 9 | if (typeof readFileSync !== 'function') throw new Error('failed to import builtin module'); 10 | 11 | if (typeof module !== 'undefined') throw new Error('module should not exist in ESM'); 12 | 13 | console.log(`${foo} ${bar} ${baz} ${biff} ${libfoo}`); 14 | -------------------------------------------------------------------------------- /tests/esm/node_modules/libfoo/entrypoint.js: -------------------------------------------------------------------------------- 1 | export const libfoo = 'libfoo' 2 | -------------------------------------------------------------------------------- /tests/esm/node_modules/libfoo/index.d.ts: -------------------------------------------------------------------------------- 1 | // TypeScript does not yet support package.json "exports" 2 | export const libfoo: string 3 | -------------------------------------------------------------------------------- /tests/esm/node_modules/libfoo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "exports": { 4 | "import": "./entrypoint.js" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/esm/throw error.ts: -------------------------------------------------------------------------------- 1 | // intentional whitespace to prove that sourcemaps are working. Throw should happen on line 100. 2 | // 100 lines is meant to be far more space than the helper functions would take. 3 | 4 | // Space in filename is intentional to ensure we handle this correctly when providing sourcemaps 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | class Foo { 97 | constructor() { 98 | this.bar(); 99 | } 100 | bar() { throw new Error('this is a demo'); } 101 | } 102 | new Foo(); 103 | export {}; 104 | -------------------------------------------------------------------------------- /tests/esm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext", 4 | "allowJs": true, 5 | "jsx": "react", 6 | "moduleResolution": "node" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/from-node-modules/from-node-modules.ts: -------------------------------------------------------------------------------- 1 | // These files are resolved by the typechecker 2 | import * as tsmie from 'external/typescript-module-imported-externally'; 3 | import * as jsmie from 'external/javascript-module-imported-externally'; 4 | // These files are unknown to the compiler until required. 5 | const tsmre = require('external/typescript-module-required-externally'); 6 | const jsmre = require('external/javascript-module-required-externally'); 7 | 8 | import * as external from 'external'; 9 | 10 | console.log(JSON.stringify({ external, tsmie, jsmie, tsmre, jsmre }, null, 2)); 11 | -------------------------------------------------------------------------------- /tests/from-node-modules/node_modules/external/index.ts: -------------------------------------------------------------------------------- 1 | // These files are resolved by the typechecker 2 | import * as tsmii from './typescript-module-imported-internally' 3 | export {tsmii} 4 | import * as jsmii from './javascript-module-imported-internally' 5 | export {jsmii} 6 | // These files are unknown to the compiler until required. 7 | export const tsmri = require('./typescript-module-required-internally') 8 | export const jsmri = require('./javascript-module-required-internally') 9 | -------------------------------------------------------------------------------- /tests/from-node-modules/node_modules/external/javascript-module-imported-externally/index.ts: -------------------------------------------------------------------------------- 1 | import {basename} from 'path' 2 | export const name = basename(__dirname) 3 | -------------------------------------------------------------------------------- /tests/from-node-modules/node_modules/external/javascript-module-imported-internally/index.ts: -------------------------------------------------------------------------------- 1 | import {basename} from 'path' 2 | export const name = basename(__dirname) 3 | -------------------------------------------------------------------------------- /tests/from-node-modules/node_modules/external/javascript-module-required-externally/index.ts: -------------------------------------------------------------------------------- 1 | import {basename} from 'path' 2 | export const name = basename(__dirname) 3 | -------------------------------------------------------------------------------- /tests/from-node-modules/node_modules/external/javascript-module-required-internally/index.ts: -------------------------------------------------------------------------------- 1 | import {basename} from 'path' 2 | export const name = basename(__dirname) 3 | -------------------------------------------------------------------------------- /tests/from-node-modules/node_modules/external/typescript-module-imported-externally/index.ts: -------------------------------------------------------------------------------- 1 | import {basename} from 'path' 2 | export const name = basename(__dirname) 3 | -------------------------------------------------------------------------------- /tests/from-node-modules/node_modules/external/typescript-module-imported-internally/index.ts: -------------------------------------------------------------------------------- 1 | import {basename} from 'path' 2 | export const name = basename(__dirname) 3 | -------------------------------------------------------------------------------- /tests/from-node-modules/node_modules/external/typescript-module-required-externally/index.ts: -------------------------------------------------------------------------------- 1 | import {basename} from 'path' 2 | export const name = basename(__dirname) 3 | -------------------------------------------------------------------------------- /tests/from-node-modules/node_modules/external/typescript-module-required-internally/index.ts: -------------------------------------------------------------------------------- 1 | import {basename} from 'path' 2 | export const name = basename(__dirname) 3 | -------------------------------------------------------------------------------- /tests/from-node-modules/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "ignore": [] 4 | }, 5 | "compilerOptions": { 6 | "allowJs": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/hello-world.ts: -------------------------------------------------------------------------------- 1 | console.log('Hello, world!'); 2 | -------------------------------------------------------------------------------- /tests/import-order/compiled.js: -------------------------------------------------------------------------------- 1 | console.log('Hello, JavaScript!'); 2 | -------------------------------------------------------------------------------- /tests/import-order/compiled.ts: -------------------------------------------------------------------------------- 1 | console.log('Hello, TypeScript!'); 2 | -------------------------------------------------------------------------------- /tests/import-order/defined.d.ts: -------------------------------------------------------------------------------- 1 | declare const v = 'Hello, World!'; 2 | 3 | export default v; 4 | -------------------------------------------------------------------------------- /tests/import-order/defined.js: -------------------------------------------------------------------------------- 1 | module.exports = 'Hello, World!'; 2 | -------------------------------------------------------------------------------- /tests/import-order/importer.ts: -------------------------------------------------------------------------------- 1 | const v = require('./defined'); 2 | 3 | console.log(v); 4 | -------------------------------------------------------------------------------- /tests/issue-884/index-2.ts: -------------------------------------------------------------------------------- 1 | export {}; 2 | 3 | const timeout = setTimeout(() => {}, 0); 4 | 5 | if (timeout.unref) { 6 | timeout.unref(); 7 | } 8 | -------------------------------------------------------------------------------- /tests/issue-884/index.ts: -------------------------------------------------------------------------------- 1 | // 2x index files required so that memory cache is populated with all build-in lib and @types 2 | // declarations *before* this require() call. 3 | require('./index-2'); 4 | -------------------------------------------------------------------------------- /tests/issue-884/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "umd", 4 | "target": "esnext", 5 | "sourceMap": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "noImplicitReturns": true, 8 | "noImplicitAny": true, 9 | "skipLibCheck": true, 10 | "moduleResolution": "node", 11 | "allowSyntheticDefaultImports": false, 12 | "declaration": true, 13 | "strict": true, 14 | "noUnusedParameters": true, 15 | "noUnusedLocals": true, 16 | "lib": ["es2015", "es2017.object", "dom"] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/issue-986/index.ts: -------------------------------------------------------------------------------- 1 | console.log(TEST); 2 | -------------------------------------------------------------------------------- /tests/issue-986/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "CommonJS" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/issue-986/types.ts: -------------------------------------------------------------------------------- 1 | declare const TEST: string; 2 | -------------------------------------------------------------------------------- /tests/jsx-react.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | 3 | const Component = (props) => { 4 | return
; 5 | }; 6 | 7 | export default Component; 8 | -------------------------------------------------------------------------------- /tests/legacy-source-map-support-interop/index.ts: -------------------------------------------------------------------------------- 1 | import { Logger } from 'tslog'; 2 | new Logger().info('hi'); 3 | console.log(require.resolve('source-map-support') === require.resolve('@cspotcode/source-map-support')); 4 | console.log(require.resolve('source-map-support/register') === require.resolve('@cspotcode/source-map-support/register')); 5 | /* 6 | tslog uses `require('source-map-support').wrapCallSite` directly. 7 | Without redirection to @cspotcode/source-map-support it does not have access to the sourcemap information we provide. 8 | */ 9 | interface Foo { 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | } 100 | console.log(new Error().stack!.split('\n')[1]); 101 | new Logger().info('hi'); 102 | -------------------------------------------------------------------------------- /tests/local-types-node/node_modules/@types/node/index.d.ts: -------------------------------------------------------------------------------- 1 | declare const process: LocalNodeTypes_Process; 2 | declare interface LocalNodeTypes_Process { 3 | /* empty */ 4 | } 5 | -------------------------------------------------------------------------------- /tests/local-types-node/node_modules/@types/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@types/node" 3 | } 4 | -------------------------------------------------------------------------------- /tests/main-realpath/symlink/symlink.tsx: -------------------------------------------------------------------------------- 1 | ../target/target.tsx -------------------------------------------------------------------------------- /tests/main-realpath/symlink/tsconfig.json: -------------------------------------------------------------------------------- 1 | this tsconfig is intentionally invalid, to confirm that ts-node does *not* attempt to parse it 2 | -------------------------------------------------------------------------------- /tests/main-realpath/target/target.tsx: -------------------------------------------------------------------------------- 1 | // Will throw a compiler error unless ./tsconfig.json is parsed, which enables JSX 2 | function foo() { 3 |
; 4 | } 5 | -------------------------------------------------------------------------------- /tests/main-realpath/target/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "transpileOnly": true 4 | }, 5 | "compilerOptions": { 6 | "jsx": "react" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth-scoped/index.ts: -------------------------------------------------------------------------------- 1 | // Import as values, forcing internal classification. All files are typechecked 2 | import { foo as a_foo, bar as a_bar } from '@scoped/a'; 3 | // Values are not used, so classification remains external. Obeys maxNodeModulesJsDepth 4 | import { foo as b_foo, bar as b_bar } from '@scoped/b'; 5 | 6 | // We must have two .ts files, one without type errors. 7 | // Otherwise, type errors would prevent imports from executing, so external modules would not be reclassified as internal. 8 | a_foo; 9 | 10 | import './other'; 11 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth-scoped/node_modules/@scoped/a/has-semantic-error.js: -------------------------------------------------------------------------------- 1 | // Due to allowJs and skipIgnore, this file is typechecked because it is reclassified as internal 2 | 3 | /** @type {string} */ 4 | export const bar = 123 5 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth-scoped/node_modules/@scoped/a/index.js: -------------------------------------------------------------------------------- 1 | export {bar} from './has-semantic-error' 2 | 3 | /** @type {string} */ 4 | export const foo = 'foo' 5 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth-scoped/node_modules/@scoped/b/has-semantic-error.js: -------------------------------------------------------------------------------- 1 | // Due to maxNodeModuleJsDepth of 1, this file is not typechecked 2 | 3 | /** @type {string} */ 4 | export const bar = 123 5 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth-scoped/node_modules/@scoped/b/index.js: -------------------------------------------------------------------------------- 1 | export {bar} from './has-semantic-error' 2 | 3 | /** @type {string} */ 4 | export const foo = 'foo' 5 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth-scoped/other.ts: -------------------------------------------------------------------------------- 1 | // Import as values, forcing internal classification. All files are typechecked 2 | import { foo as a_foo, bar as a_bar } from '@scoped/a'; 3 | // Values are not used, so classification remains external. Obeys maxNodeModulesJsDepth 4 | import { foo as b_foo, bar as b_bar } from '@scoped/b'; 5 | 6 | // `a_bar` has type information because it has been reclassified as internal 7 | const shouldBeBoolean2: boolean = a_bar; 8 | 9 | // `b_bar` is missing type information, so this is not an error 10 | const shouldBeBoolean4: boolean = null as typeof b_bar; 11 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth-scoped/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | // Force transpilation of node_modules 4 | "skipIgnore": true 5 | }, 6 | "compilerOptions": { 7 | "allowJs": true, 8 | "maxNodeModuleJsDepth": 1, 9 | "moduleResolution": "node" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth/index.ts: -------------------------------------------------------------------------------- 1 | import { foo, bar } from 'external'; 2 | import './other'; 3 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth/node_modules/external/has-semantic-error.js: -------------------------------------------------------------------------------- 1 | // Due to maxNodeModuleJsDepth of 1, this file is not typechecked 2 | 3 | /** @type {string} */ 4 | exports.bar = 123 5 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth/node_modules/external/index.js: -------------------------------------------------------------------------------- 1 | const hasSemanticError = require('./has-semantic-error'); 2 | exports.bar = hasSemanticError.bar; 3 | 4 | /** @type {string} */ 5 | exports.foo = 'foo' 6 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth/other.ts: -------------------------------------------------------------------------------- 1 | import { foo, bar } from 'external'; 2 | 3 | // `foo` has type information so this is an error 4 | const shouldBeBoolean: boolean = foo; 5 | 6 | // `bar` is missing type information, so this is not an error 7 | const shouldBeBoolean2: boolean = bar; 8 | -------------------------------------------------------------------------------- /tests/maxnodemodulesjsdepth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "maxNodeModuleJsDepth": 1, 5 | "moduleResolution": "node" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/module-types/override-to-cjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/module-types/override-to-cjs/src/cjs-subdir/esm-exception.ts: -------------------------------------------------------------------------------- 1 | declare const require: any; 2 | export const requireType = typeof require; 3 | -------------------------------------------------------------------------------- /tests/module-types/override-to-cjs/src/cjs-subdir/index.ts: -------------------------------------------------------------------------------- 1 | declare const require: any; 2 | export const requireType = typeof require; 3 | -------------------------------------------------------------------------------- /tests/module-types/override-to-cjs/src/should-be-esm.ts: -------------------------------------------------------------------------------- 1 | export const a: string = 'b'; 2 | declare const require: any; 3 | export const requireType = typeof require; 4 | -------------------------------------------------------------------------------- /tests/module-types/override-to-cjs/test-webpack-config.cjs: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | assert(require('./webpack.config').hello === 'world'); 4 | -------------------------------------------------------------------------------- /tests/module-types/override-to-cjs/test.cjs: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | const wpc = require('./webpack.config.ts'); 4 | assert(wpc.hello === 'world'); 5 | 6 | let failures = 0; 7 | 8 | try { 9 | require('./src/should-be-esm.ts'); 10 | failures++; 11 | } catch (e) { 12 | // good 13 | } 14 | 15 | const cjsSubdir = require('./src/cjs-subdir'); 16 | assert(cjsSubdir.requireType === 'function'); 17 | 18 | try { 19 | require('./src/cjs-subdir/esm-exception.ts'); 20 | failures++; 21 | } catch (e) { 22 | // good 23 | } 24 | 25 | console.log(`Failures: ${failures}`); 26 | -------------------------------------------------------------------------------- /tests/module-types/override-to-cjs/test.mjs: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | 3 | import webpackConfig from './webpack.config.ts'; 4 | import * as shouldBeEsm from './src/should-be-esm.ts'; 5 | import subdirCjs from './src/cjs-subdir/index.ts'; 6 | import * as subdirEsm from './src/cjs-subdir/esm-exception.ts'; 7 | 8 | assert(webpackConfig.hello === 'world'); 9 | assert(shouldBeEsm.requireType === 'undefined'); 10 | assert(subdirCjs.requireType === 'function'); 11 | assert(subdirEsm.requireType === 'undefined'); 12 | 13 | console.log(`Failures: 0`); 14 | -------------------------------------------------------------------------------- /tests/module-types/override-to-cjs/tsconfig-swc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "ts-node": { 4 | "swc": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/module-types/override-to-cjs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "moduleTypes": { 4 | "webpack.config.ts": "cjs", 5 | // Test that subsequent patterns override earlier ones 6 | "src/cjs-subdir/**/*": "esm", 7 | "src/cjs-subdir": "cjs", 8 | "src/cjs-subdir/esm-exception.ts": "esm" 9 | } 10 | }, 11 | "compilerOptions": { 12 | "module": "ES2015" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/module-types/override-to-cjs/webpack.config.ts: -------------------------------------------------------------------------------- 1 | export const hello: string = 'world'; 2 | -------------------------------------------------------------------------------- /tests/module-types/override-to-esm/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /tests/module-types/override-to-esm/src/esm-subdir/cjs-exception.ts: -------------------------------------------------------------------------------- 1 | declare const require: any; 2 | export const requireType = typeof require; 3 | -------------------------------------------------------------------------------- /tests/module-types/override-to-esm/src/esm-subdir/index.ts: -------------------------------------------------------------------------------- 1 | declare const require: any; 2 | export const requireType = typeof require; 3 | -------------------------------------------------------------------------------- /tests/module-types/override-to-esm/src/should-be-cjs.ts: -------------------------------------------------------------------------------- 1 | export const a: string = 'b'; 2 | declare const require: any; 3 | export const requireType = typeof require; 4 | -------------------------------------------------------------------------------- /tests/module-types/override-to-esm/test.cjs: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | 3 | let failures = 0; 4 | 5 | const shouldBeCjs = require('./src/should-be-cjs.ts'); 6 | assert(shouldBeCjs.requireType === 'function'); 7 | 8 | try { 9 | require('./src/esm-subdir'); 10 | failures++; 11 | } catch (e) { 12 | // good 13 | } 14 | 15 | const cjsException = require('./src/esm-subdir/cjs-exception.ts'); 16 | assert(cjsException.requireType === 'function'); 17 | 18 | console.log(`Failures: ${failures}`); 19 | -------------------------------------------------------------------------------- /tests/module-types/override-to-esm/test.mjs: -------------------------------------------------------------------------------- 1 | import assert from 'assert'; 2 | 3 | import shouldBeCjs from './src/should-be-cjs.ts'; 4 | import * as subdirEsm from './src/esm-subdir/index.ts'; 5 | import subdirCjs from './src/esm-subdir/cjs-exception.ts'; 6 | 7 | assert(shouldBeCjs.requireType === 'function'); 8 | assert(subdirEsm.requireType === 'undefined'); 9 | assert(subdirCjs.requireType === 'function'); 10 | 11 | console.log(`Failures: 0`); 12 | -------------------------------------------------------------------------------- /tests/module-types/override-to-esm/tsconfig-swc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "ts-node": { 4 | "swc": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/module-types/override-to-esm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "moduleTypes": { 4 | // Test that subsequent patterns override earlier ones 5 | "src/esm-subdir/**/*": "cjs", 6 | "src/esm-subdir": "esm", 7 | "src/esm-subdir/cjs-exception.ts": "cjs" 8 | } 9 | }, 10 | "compilerOptions": { 11 | "module": "CommonJS" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/module.ts: -------------------------------------------------------------------------------- 1 | export function example(foo: string) { 2 | return foo.toUpperCase(); 3 | } 4 | -------------------------------------------------------------------------------- /tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@swc/core": "latest", 4 | "ts-node": "file:ts-node-packed.tgz", 5 | "tslog": "3.2.2" 6 | }, 7 | "volta": { 8 | "extends": "../package.json" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/@swc/core/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transformSync() { 3 | return { code: 'emit from root @swc/core', map: '{}' }; 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/@swc/wasm/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transformSync() { 3 | return { code: 'emit from root @swc/wasm', map: '{}' }; 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/custom-compiler/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ...require('typescript'), 3 | transpileModule() { 4 | return { 5 | outputText: 'emit from root custom compiler', 6 | sourceMapText: '{}', 7 | }; 8 | }, 9 | createProgram() { 10 | throw 'emit from root custom compiler'; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/custom-swc/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transformSync() { 3 | return { code: 'emit from root custom swc backend', map: '{}' }; 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/custom-transpiler/index.js: -------------------------------------------------------------------------------- 1 | module.exports.create = function () { 2 | return { 3 | transpile() { 4 | return { 5 | outputText: 'emit from root custom transpiler', 6 | sourceMapText: '{}', 7 | }; 8 | }, 9 | }; 10 | }; 11 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/shared-config/node_modules/@swc/core/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transformSync() { 3 | return { code: 'emit from shared-config @swc/core', map: '{}' }; 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/shared-config/node_modules/@swc/wasm/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transformSync() { 3 | return { code: 'emit from shared-config @swc/wasm', map: '{}' }; 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/shared-config/node_modules/custom-compiler/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ...require('typescript'), 3 | transpileModule() { 4 | return { 5 | outputText: 'emit from shared-config custom compiler', 6 | sourceMapText: '{}', 7 | }; 8 | }, 9 | createProgram() { 10 | throw 'emit from shared-config custom compiler'; 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/shared-config/node_modules/custom-swc/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transformSync() { 3 | return { code: 'emit from shared-config custom swc backend', map: '{}' }; 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/shared-config/node_modules/custom-transpiler/index.js: -------------------------------------------------------------------------------- 1 | module.exports.create = function () { 2 | return { 3 | transpile() { 4 | return { 5 | outputText: 'emit from shared-config custom transpiler', 6 | sourceMapText: '{}', 7 | }; 8 | }, 9 | }; 10 | }; 11 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/shared-config/tsconfig-custom-compiler.json: -------------------------------------------------------------------------------- 1 | {"ts-node":{"transpileOnly":true,"compiler":"custom-compiler"}} 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/shared-config/tsconfig-custom-transpiler.json: -------------------------------------------------------------------------------- 1 | {"ts-node":{"transpileOnly":true,"transpiler":"custom-transpiler"}} 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/shared-config/tsconfig-swc-core.json: -------------------------------------------------------------------------------- 1 | {"ts-node":{"transpileOnly":true,"transpiler":["ts-node/transpilers/swc",{"swc":"@swc/core"}]}} 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/shared-config/tsconfig-swc-custom-backend.json: -------------------------------------------------------------------------------- 1 | {"ts-node":{"transpileOnly":true,"transpiler":["ts-node/transpilers/swc",{"swc":"custom-swc"}]}} 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/shared-config/tsconfig-swc-wasm.json: -------------------------------------------------------------------------------- 1 | {"ts-node":{"transpileOnly":true,"transpiler":["ts-node/transpilers/swc",{"swc":"@swc/wasm"}]}} 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/node_modules/shared-config/tsconfig-swc.json: -------------------------------------------------------------------------------- 1 | {"ts-node":{"swc":true}} 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-custom-compiler.json: -------------------------------------------------------------------------------- 1 | { "ts-node": { "transpileOnly": true, "compiler": "custom-compiler" } } 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-custom-transpiler.json: -------------------------------------------------------------------------------- 1 | { "ts-node": { "transpileOnly": true, "transpiler": "custom-transpiler" } } 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-extend-custom-compiler.json: -------------------------------------------------------------------------------- 1 | { "extends": "shared-config/tsconfig-custom-compiler.json" } 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-extend-custom-transpiler.json: -------------------------------------------------------------------------------- 1 | { "extends": "shared-config/tsconfig-custom-transpiler.json" } 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-extend-swc-core.json: -------------------------------------------------------------------------------- 1 | { "extends": "shared-config/tsconfig-swc-core.json" } 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-extend-swc-custom-backend.json: -------------------------------------------------------------------------------- 1 | { "extends": "shared-config/tsconfig-swc-custom-backend.json" } 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-extend-swc-wasm.json: -------------------------------------------------------------------------------- 1 | { "extends": "shared-config/tsconfig-swc-wasm.json" } 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-extend-swc.json: -------------------------------------------------------------------------------- 1 | { "extends": "shared-config/tsconfig-swc.json" } 2 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-swc-core.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "transpileOnly": true, 4 | "transpiler": ["ts-node/transpilers/swc", { "swc": "@swc/core" }] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-swc-custom-backend.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "transpileOnly": true, 4 | "transpiler": ["ts-node/transpilers/swc", { "swc": "custom-swc" }] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-swc-wasm.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "transpileOnly": true, 4 | "transpiler": ["ts-node/transpilers/swc", { "swc": "@swc/wasm" }] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/pluggable-dep-resolution/tsconfig-swc.json: -------------------------------------------------------------------------------- 1 | { "ts-node": { "swc": true } } 2 | -------------------------------------------------------------------------------- /tests/recursive-fork/index.ts: -------------------------------------------------------------------------------- 1 | import { fork } from 'child_process'; 2 | 3 | // Type syntax to prove its compiled, though the import above should also 4 | // prove the same 5 | const a = null as any; 6 | 7 | console.log(JSON.stringify({ execArgv: process.execArgv, argv: process.argv })); 8 | if (process.env.generation !== 'grandchild') { 9 | const nextGeneration = process.env.generation === 'child' ? 'grandchild' : 'child'; 10 | fork(__filename, process.argv.slice(2), { 11 | env: { ...process.env, generation: nextGeneration }, 12 | stdio: 'inherit', 13 | }); 14 | } 15 | -------------------------------------------------------------------------------- /tests/recursive-fork/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /tests/recursive-fork/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/repl-ignored-diagnostics/index.ts: -------------------------------------------------------------------------------- 1 | // This script triggers a diagnostic that is ignored in the virtual file but 2 | // *not* in files such as this one. 3 | // When this file is required by the REPL, the diagnostic *should* be logged. 4 | export {}; 5 | function foo() {} 6 | function foo() {} 7 | -------------------------------------------------------------------------------- /tests/repl-in-esm-package/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/repl-in-esm-package/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "nodenext" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/repl/script.js: -------------------------------------------------------------------------------- 1 | console.log( 2 | JSON.stringify({ 3 | stdinReport: typeof stdinReport !== 'undefined' && stdinReport, 4 | evalReport: typeof evalReport !== 'undefined' && evalReport, 5 | replReport: typeof replReport !== 'undefined' && replReport, 6 | }) 7 | ); 8 | -------------------------------------------------------------------------------- /tests/repl/tla-import.ts: -------------------------------------------------------------------------------- 1 | export const foo: string = 1; 2 | -------------------------------------------------------------------------------- /tests/require-cache.ts: -------------------------------------------------------------------------------- 1 | const moduleName = require.resolve('./module'); 2 | 3 | const { example: example1 } = require(moduleName); 4 | delete require.cache[moduleName]; 5 | const { example: example2 } = require(moduleName); 6 | 7 | export { example1, example2 }; 8 | -------------------------------------------------------------------------------- /tests/resolver/README.md: -------------------------------------------------------------------------------- 1 | TODO must require explicit rootDir; do not allow to be inferred. 2 | TODO resolve JSON if resolveJsonModules?? 3 | 4 | Test a bunch of permutations of: 5 | 6 | config permutations: 7 | 8 | - allowJs 9 | - not allowJs 10 | 11 | - preferSrc 12 | - not preferSrc 13 | 14 | import permutations: 15 | 16 | - Relative import of file 17 | - Relative import of index 18 | - rootless library import of main 19 | - rootless library import of index 20 | - rootless library import of exports sub-path 21 | - rootless self-import of main 22 | - rootless self-import of index 23 | - rootless self-import of exports sub-path 24 | 25 | - Require with extension 26 | - Require without extension 27 | 28 | - Require from dist to dist 29 | - Require from dist to src 30 | - Require from src to dist 31 | - Require from src to src 32 | 33 | lib permutations: 34 | 35 | - module exists in both src and dist (precompilation ran) 36 | - module exists in only dist (came from elsewhere) 37 | - module exists only in src (did not precompile) 38 | 39 | - .ts / .js extension 40 | - .tsx / .js extension 41 | - .cts / .cjs extension 42 | - .mts / .mjs extension 43 | - .js / .js extension 44 | - .jsx / .js extension 45 | - .cjs / .cjs extension 46 | - .mjs / .mjs extension 47 | -------------------------------------------------------------------------------- /tests/resolver/package.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /tests/resolver/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | 4 | cd project-preferSrc-typeModule 5 | -------------------------------------------------------------------------------- /tests/scope/a/index.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | export const ext = path.extname(__filename); 4 | -------------------------------------------------------------------------------- /tests/scope/a/log.ts: -------------------------------------------------------------------------------- 1 | import { ext } from './index'; 2 | 3 | console.log(ext); 4 | -------------------------------------------------------------------------------- /tests/scope/a/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/scope/b/index.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | export const ext = path.extname(__filename); 4 | -------------------------------------------------------------------------------- /tests/scope/b/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/scope/c/config/index.ts: -------------------------------------------------------------------------------- 1 | export const a: string = 'value'; 2 | -------------------------------------------------------------------------------- /tests/scope/c/config/scopedir/index.ts: -------------------------------------------------------------------------------- 1 | export const a: string = 'value'; 2 | -------------------------------------------------------------------------------- /tests/scope/c/config/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "scope": true, 4 | "scopeDir": "./scopedir" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/scope/c/index.js: -------------------------------------------------------------------------------- 1 | let failures = 0; 2 | try { 3 | // This should fail with an error because it is outside scopedir 4 | require('./scopedir/index'); 5 | failures++; 6 | } catch (e) { 7 | // good 8 | } 9 | 10 | try { 11 | // This should fail with an error because it is outside scopedir 12 | require('./config/index'); 13 | failures++; 14 | } catch (e) { 15 | // good 16 | } 17 | 18 | try { 19 | // this should succeed 20 | console.log(require('./config/scopedir/index').a); 21 | } catch (e) { 22 | // bad 23 | failures++; 24 | } 25 | 26 | console.log(`Failures: ${failures}`); 27 | -------------------------------------------------------------------------------- /tests/scope/c/scopedir/index.ts: -------------------------------------------------------------------------------- 1 | export const a: string = 'value'; 2 | -------------------------------------------------------------------------------- /tests/signals.ts: -------------------------------------------------------------------------------- 1 | process.on('SIGINT', () => { 2 | process.stdout.write('exited'); 3 | setTimeout(() => { 4 | process.stdout.write(' fine'); 5 | 6 | // Needed to make sure what we wrote has time 7 | // to be written 8 | process.nextTick(() => process.exit()); 9 | }, 500); 10 | }); 11 | 12 | setInterval(() => console.log('should not be reached'), 3000); 13 | -------------------------------------------------------------------------------- /tests/spy-swc-transpiler.js: -------------------------------------------------------------------------------- 1 | // Spy on the swc transpiler so that tests can prove it was used rather than 2 | // TypeScript's `transpileModule`. 3 | const swcTranspiler = require('ts-node/transpilers/swc'); 4 | 5 | global.swcTranspilerCalls = 0; 6 | 7 | const wrappedCreate = swcTranspiler.create; 8 | swcTranspiler.create = function (...args) { 9 | const transpiler = wrappedCreate(...args); 10 | const wrappedTranspile = transpiler.transpile; 11 | transpiler.transpile = function (...args) { 12 | global.swcTranspilerCalls++; 13 | return wrappedTranspile.call(this, ...args); 14 | }; 15 | return transpiler; 16 | }; 17 | -------------------------------------------------------------------------------- /tests/throw error react tsx.tsx: -------------------------------------------------------------------------------- 1 | // intentional whitespace to prove that sourcemaps are working. Throw should happen on line 100. 2 | // 100 lines is meant to be far more space than the helper functions would take. 3 | 4 | // Space in filename is intentional to ensure we handle this correctly when providing sourcemaps 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | const React = { createElement: (...args: any[]) => null }; 96 | class Foo { 97 | constructor() { 98 | this.bar(); 99 | } 100 | bar() { throw new Error('this is a demo'); } 101 | someJsx() { 102 | return
; 103 | } 104 | } 105 | new Foo(); 106 | export {}; 107 | -------------------------------------------------------------------------------- /tests/throw error.ts: -------------------------------------------------------------------------------- 1 | // intentional whitespace to prove that sourcemaps are working. Throw should happen on line 100. 2 | // 100 lines is meant to be far more space than the helper functions would take. 3 | 4 | // Space in filename is intentional to ensure we handle this correctly when providing sourcemaps 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | class Foo { 97 | constructor() { 98 | this.bar(); 99 | } 100 | bar() { throw new Error('this is a demo'); } 101 | } 102 | new Foo(); 103 | export {}; 104 | -------------------------------------------------------------------------------- /tests/transpile-only-swc-native-esm/index.ts: -------------------------------------------------------------------------------- 1 | const x: number = `Hello ${import.meta.url.slice(0, 7)}!`; 2 | console.log(x); 3 | -------------------------------------------------------------------------------- /tests/transpile-only-swc-native-esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/transpile-only-swc-native-esm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "transpileOnly": true, 4 | "transpiler": "ts-node/transpilers/swc-experimental" 5 | }, 6 | "compilerOptions": { 7 | "target": "ES2018", 8 | "module": "ESNext", 9 | "allowJs": true, 10 | "jsx": "react", 11 | "experimentalDecorators": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/transpile-only-swc-shorthand-via-tsconfig/index.ts: -------------------------------------------------------------------------------- 1 | // Test for #1343 2 | const Decorator = function () {}; 3 | @Decorator 4 | class World {} 5 | 6 | // intentional type errors to check transpile-only ESM loader skips type checking 7 | parseInt(1101, 2); 8 | const x: number = `Hello ${World.name}! swc transpiler invocation count: ${global.swcTranspilerCalls}`; 9 | console.log(x); 10 | 11 | // test module type emit 12 | import { readFileSync } from 'fs'; 13 | readFileSync; 14 | -------------------------------------------------------------------------------- /tests/transpile-only-swc-shorthand-via-tsconfig/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "swc": true 4 | }, 5 | "compilerOptions": { 6 | "target": "ES2018", 7 | "module": "CommonJS", 8 | "allowJs": true, 9 | "jsx": "react", 10 | "experimentalDecorators": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/transpile-only-swc-via-tsconfig/index.ts: -------------------------------------------------------------------------------- 1 | // Test for #1343 2 | const Decorator = function () {}; 3 | @Decorator 4 | class World {} 5 | 6 | // intentional type errors to check transpile-only ESM loader skips type checking 7 | parseInt(1101, 2); 8 | const x: number = `Hello ${World.name}! swc transpiler invocation count: ${global.swcTranspilerCalls}`; 9 | console.log(x); 10 | 11 | // test module type emit 12 | import { readFileSync } from 'fs'; 13 | readFileSync; 14 | -------------------------------------------------------------------------------- /tests/transpile-only-swc-via-tsconfig/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "transpileOnly": true, 4 | "transpiler": "ts-node/transpilers/swc" 5 | }, 6 | "compilerOptions": { 7 | "target": "ES2018", 8 | "module": "CommonJS", 9 | "allowJs": true, 10 | "jsx": "react", 11 | "experimentalDecorators": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/transpile-only-swc/index.ts: -------------------------------------------------------------------------------- 1 | // Test for #1343 2 | const Decorator = function () {}; 3 | @Decorator 4 | class World {} 5 | 6 | // intentional type errors to check transpile-only ESM loader skips type checking 7 | parseInt(1101, 2); 8 | const x: number = `Hello ${World.name}! swc transpiler invocation count: ${global.swcTranspilerCalls}`; 9 | console.log(x); 10 | 11 | // test module type emit 12 | import { readFileSync } from 'fs'; 13 | readFileSync; 14 | -------------------------------------------------------------------------------- /tests/transpile-only-swc/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "CommonJS", 5 | "allowJs": true, 6 | "jsx": "react", 7 | "experimentalDecorators": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/ts45-ext/ext-cts/index.cts: -------------------------------------------------------------------------------- 1 | export function main() { 2 | return 'hello world'; 3 | } 4 | -------------------------------------------------------------------------------- /tests/ts45-ext/ext-cts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "experimentalResolver": true 4 | }, 5 | "compilerOptions": { 6 | "module": "CommonJS" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/ts45-ext/ext-mts/entrypoint.mjs: -------------------------------------------------------------------------------- 1 | import { main } from './index.mjs'; 2 | console.log(main()); 3 | -------------------------------------------------------------------------------- /tests/ts45-ext/ext-mts/index.mts: -------------------------------------------------------------------------------- 1 | export function main() { 2 | return 'hello world'; 3 | } 4 | -------------------------------------------------------------------------------- /tests/ts45-ext/ext-mts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "esm": true, 4 | "experimentalResolver": true 5 | }, 6 | "compilerOptions": { 7 | "module": "ESNext" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/tsconfig-bases/node14/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "ts-node/node14/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /tests/tsconfig-bases/node16/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "ts-node/node16/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /tests/tsconfig-bases/node18/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "ts-node/node18/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /tests/tsconfig-bases/node20/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "ts-node/node20/tsconfig.json" 3 | } 4 | -------------------------------------------------------------------------------- /tests/tsconfig-extends-multiple/a/require-hook-from-a.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/tests/tsconfig-extends-multiple/a/require-hook-from-a.js -------------------------------------------------------------------------------- /tests/tsconfig-extends-multiple/a/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../b/tsconfig.json", 3 | "ts-node": { 4 | "require": ["./require-hook-from-a"], 5 | "scopeDir": "./scopedir-from-a" 6 | }, 7 | "compilerOptions": { 8 | "target": "ES2015" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/tsconfig-extends-multiple/b/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "ignore": ["ignore-pattern-from-b"], 4 | "transpiler": "transpiler-from-b", 5 | "transpileOnly": true, 6 | "scopeDir": "./scopedir-from-b", 7 | "moduleTypes": { "module-types-from-b": "cjs" } 8 | }, 9 | "compilerOptions": { 10 | "target": "ES2016" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/tsconfig-extends-multiple/c/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../d/tsconfig.json", 3 | "ts-node": { 4 | "transpiler": "transpiler-from-c", 5 | "transpileOnly": true 6 | }, 7 | "compilerOptions": { 8 | "target": "ES2017" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/tsconfig-extends-multiple/d/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "ignore": ["ignore-pattern-from-d"] 4 | }, 5 | "compilerOptions": { 6 | "target": "ES2018" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/tsconfig-extends-multiple/empty.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/tests/tsconfig-extends-multiple/empty.ts -------------------------------------------------------------------------------- /tests/tsconfig-extends-multiple/node_modules/transpiler-from-c/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/tests/tsconfig-extends-multiple/node_modules/transpiler-from-c/index.js -------------------------------------------------------------------------------- /tests/tsconfig-extends-multiple/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["./a/tsconfig.json", "./c/tsconfig.json"], 3 | "ts-node": { 4 | "preferTsExts": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/tsconfig-extends/other/require-hook.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/tests/tsconfig-extends/other/require-hook.js -------------------------------------------------------------------------------- /tests/tsconfig-extends/other/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "require": ["./require-hook"], 4 | "scopeDir": "./scopedir" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/tsconfig-extends/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./other/tsconfig.json", 3 | "ts-node": { 4 | "preferTsExts": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/tsconfig-options/log-options1.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | assert(process.required1); 3 | const register = process[Symbol.for('ts-node.register.instance')]; 4 | console.log( 5 | JSON.stringify({ 6 | options: register.options, 7 | config: register.config, 8 | }) 9 | ); 10 | -------------------------------------------------------------------------------- /tests/tsconfig-options/log-options2.js: -------------------------------------------------------------------------------- 1 | const assert = require('assert'); 2 | require('./log-options1'); 3 | assert(process.required2); 4 | -------------------------------------------------------------------------------- /tests/tsconfig-options/required1.js: -------------------------------------------------------------------------------- 1 | process.required1 = true; 2 | -------------------------------------------------------------------------------- /tests/tsconfig-options/required2.js: -------------------------------------------------------------------------------- 1 | require('assert')(process.required1); 2 | process.required2 = true; 3 | -------------------------------------------------------------------------------- /tests/tsconfig-options/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "ts-node": { 4 | "compilerOptions": { 5 | "types": ["tsconfig-tsnode-types"] 6 | }, 7 | "transpileOnly": true, 8 | "require": ["./required1"], 9 | "skipIgnore": false 10 | }, 11 | "compilerOptions": { 12 | "typeRoots": ["tsconfig-typeroots"], 13 | "types": ["tsconfig-types"] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/tsconfig-transpile-only.json: -------------------------------------------------------------------------------- 1 | { 2 | "ts-node": { 3 | "transpileOnly": true 4 | }, 5 | "compilerOptions": { 6 | "target": "es2015", 7 | "jsx": "react", 8 | "noEmit": true, 9 | "strict": true, 10 | // Global type definitions. 11 | "typeRoots": ["./typings", "../node_modules/@types"] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2015", 4 | "jsx": "react", 5 | "noEmit": true, 6 | "strict": true, 7 | // Global type definitions. 8 | "typeRoots": ["./typings", "../node_modules/@types"] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/typings/does-not-exist/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'does-not-exist' { 2 | export const foobar = 'test'; 3 | } 4 | -------------------------------------------------------------------------------- /tests/with-jsx.tsx: -------------------------------------------------------------------------------- 1 | class Foo2 { 2 | render() { 3 | return
; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/working-dir/cjs/index.ts: -------------------------------------------------------------------------------- 1 | import { strictEqual } from 'assert'; 2 | import { normalize, dirname } from 'path'; 3 | 4 | // Expect the working directory to be the parent directory. 5 | strictEqual(normalize(process.cwd()), normalize(dirname(__dirname))); 6 | 7 | console.log('Passing'); 8 | -------------------------------------------------------------------------------- /tests/working-dir/esm/index.ts: -------------------------------------------------------------------------------- 1 | import { strictEqual } from 'assert'; 2 | import { normalize, dirname } from 'path'; 3 | import { fileURLToPath } from 'url'; 4 | 5 | // Expect the working directory to be the parent directory. 6 | strictEqual(normalize(process.cwd()), normalize(dirname(dirname(fileURLToPath(import.meta.url))))); 7 | 8 | console.log('Passing'); 9 | -------------------------------------------------------------------------------- /tests/working-dir/esm/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module" 3 | } 4 | -------------------------------------------------------------------------------- /tests/working-dir/esm/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "ESNext" 4 | }, 5 | "ts-node": { 6 | "swc": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/working-dir/forking/index.ts: -------------------------------------------------------------------------------- 1 | import { fork } from 'child_process'; 2 | import { join } from 'path'; 3 | 4 | // Initially set the exit code to non-zero. We only set it to `0` when the 5 | // worker process finishes properly with the expected stdout message. 6 | process.exitCode = 1; 7 | 8 | const workerProcess = fork('./worker.ts', [], { 9 | stdio: 'pipe', 10 | cwd: join(__dirname, 'subfolder'), 11 | }); 12 | 13 | let stdout = ''; 14 | 15 | workerProcess.stdout!.on('data', (chunk) => (stdout += chunk.toString('utf8'))); 16 | workerProcess.on('error', () => (process.exitCode = 1)); 17 | workerProcess.on('close', (status, signal) => { 18 | if (status === 0 && signal === null && stdout.trim() === 'Works') { 19 | console.log('Passing: from main'); 20 | process.exitCode = 0; 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /tests/working-dir/forking/subfolder/worker.ts: -------------------------------------------------------------------------------- 1 | const message: string = 'Works'; 2 | 3 | console.log(message); 4 | -------------------------------------------------------------------------------- /tests/working-dir/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "ts-node": { 4 | "transpileOnly": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/yarn.lock: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/tests/yarn.lock -------------------------------------------------------------------------------- /transpilers/swc-experimental.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../dist/transpilers/swc') 2 | -------------------------------------------------------------------------------- /transpilers/swc.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../dist/transpilers/swc') 2 | -------------------------------------------------------------------------------- /tsconfig.build-dist-raw.json: -------------------------------------------------------------------------------- 1 | // This tsconfig.json is referenced by tsconfig.build-dist.json, a little trick to keep tsc happy. 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "composite": true, 6 | "allowJs": true, 7 | "checkJs": false, 8 | "noResolve": true, 9 | "declaration": true, 10 | "noEmit": false, 11 | "emitDeclarationOnly": true, 12 | "rootDir": "dist-raw", 13 | "outDir": "temp/dist-raw" 14 | }, 15 | "include": [ 16 | "dist-raw/**/*" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.build-dist.json: -------------------------------------------------------------------------------- 1 | // This tsconfig.json drives compiling the src/ directory into the dist/ directory 2 | { 3 | "extends": "./tsconfig.json", 4 | "references": [{ 5 | "path": "./tsconfig.build-dist-raw.json" 6 | }], 7 | "compilerOptions": { 8 | "noEmit": false, 9 | "rootDir": "src", 10 | "outDir": "dist", 11 | "tsBuildInfoFile": "temp/tsconfig.build-dist.tsbuildinfo", 12 | "allowJs": false, 13 | "rootDirs": ["temp", "."] 14 | }, 15 | "include": [ 16 | "src/**/*" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.build-schema.json: -------------------------------------------------------------------------------- 1 | // This tsconfig.json is used when we generate the tsconfig JSON schema 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "incremental": false, 6 | "tsBuildInfoFile": null, 7 | "noEmit": false, 8 | "allowJs": true, 9 | "checkJs": false, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | // This tsconfig.json drives Intellisense 2 | { 3 | "$schema": "./tsconfig.schemastore-schema.json", 4 | "compilerOptions": { 5 | // `target` and `lib` match @tsconfig/bases for node14, since that's the oldest node LTS, so it's the oldest node we support 6 | "target": "es2020", 7 | "lib": ["es2020"], 8 | "rootDir": ".", 9 | "outDir": "temp", 10 | "tsBuildInfoFile": "temp/tsconfig.tsbuildinfo", 11 | "noEmit": true, 12 | "module": "commonjs", 13 | "moduleResolution": "node", 14 | "strict": true, 15 | "declaration": true, 16 | "sourceMap": true, 17 | "inlineSources": true, 18 | "types": ["node"], 19 | "stripInternal": true, 20 | "incremental": true, 21 | "skipLibCheck": true, 22 | "importsNotUsedAsValues": "error", 23 | "allowJs": true, 24 | 25 | // Enable to assist in sanity-checking your changes to JS files, but note you will see many unrelated type errors! 26 | // "checkJs": true, 27 | // "noImplicitAny": false 28 | }, 29 | "include": [ 30 | "src/**/*" 31 | ], 32 | "typedocOptions": { 33 | "entryPoints": ["./src/index.ts"], 34 | "readme": "none", 35 | "out": "website/static/api", 36 | "excludeTags": ["allof"], 37 | "categorizeByGroup": false, 38 | "categoryOrder": ["Basic", "REPL", "Transpiler", "ESM Loader", "Other"], 39 | "defaultCategory": "Other" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", 3 | 4 | "supportForTags": { 5 | // Indicate that the custom tag is supported by your tooling. (Without this, warnings may 6 | // be reported saying that the tag is unsupported.) 7 | "@default": true, 8 | "@allOf": true, 9 | "@see": true, 10 | "@deprecated": true, 11 | "@category": true 12 | }, 13 | 14 | "tagDefinitions": [ 15 | { 16 | "tagName": "@default", 17 | "syntaxKind": "block", 18 | "allowMultiple": false 19 | }, 20 | { 21 | "tagName": "@allOf", 22 | "syntaxKind": "block", 23 | "allowMultiple": false 24 | }, 25 | { 26 | "tagName": "@category", 27 | "syntaxKind": "inline", 28 | "allowMultiple": false 29 | } 30 | ] 31 | } 32 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. 4 | 5 | ## Installation 6 | 7 | ```console 8 | yarn install 9 | ``` 10 | 11 | ## Local Development 12 | 13 | ```console 14 | yarn start 15 | ``` 16 | 17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ## Build 20 | 21 | ```console 22 | yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ## Deployment 28 | 29 | ```console 30 | GIT_USER= USE_SSH=true yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /website/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /website/docs/api.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: API 3 | --- 4 | 5 | ts-node's complete API is documented here: [API Docs](https://typestrong.org/ts-node/api/) 6 | 7 | Here are a few highlights of what you can accomplish: 8 | 9 | - [`create()`](https://typestrong.org/ts-node/api/index.html#create) creates ts-node's compiler service without 10 | registering any hooks. 11 | - [`createRepl()`](https://typestrong.org/ts-node/api/index.html#createRepl) creates an instance of our REPL service, so 12 | you can create your own TypeScript-powered REPLs. 13 | - [`createEsmHooks()`](https://typestrong.org/ts-node/api/index.html#createEsmHooks) creates our ESM loader hooks, 14 | suitable for composing with other loaders or augmenting with additional features. 15 | -------------------------------------------------------------------------------- /website/docs/compilers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Third-party compilers 3 | --- 4 | 5 | Some projects require a patched typescript compiler which adds additional features. For example, [`ttypescript`](https://github.com/cevek/ttypescript/tree/master/packages/ttypescript) and [`ts-patch`](https://github.com/nonara/ts-patch#readme) 6 | add the ability to configure custom transformers. These are drop-in replacements for the vanilla `typescript` module and 7 | implement the same API. 8 | 9 | For example, to use `ttypescript` and `ts-transformer-keys`, add this to your `tsconfig.json`: 10 | 11 | ```json title="tsconfig.json" 12 | { 13 | "ts-node": { 14 | // This can be omitted when using ts-patch 15 | "compiler": "ttypescript" 16 | }, 17 | "compilerOptions": { 18 | // plugin configuration is the same for both ts-patch and ttypescript 19 | "plugins": [ 20 | { "transform": "ts-transformer-keys/transformer" } 21 | ] 22 | } 23 | } 24 | ``` 25 | -------------------------------------------------------------------------------- /website/docs/how-it-works.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How it works 3 | --- 4 | 5 | ts-node works by registering hooks for `.ts`, `.tsx`, `.js`, and/or `.jsx` extensions. 6 | 7 | Vanilla `node` loads `.js` by reading code from disk and executing it. Our hook runs in the middle, transforming code from TypeScript to JavaScript and passing the result to `node` for execution. This transformation will respect your `tsconfig.json` as if you had compiled via `tsc`. 8 | 9 | We also register a few other hooks to apply sourcemaps to stack traces and remap from `.js` imports to `.ts`. 10 | -------------------------------------------------------------------------------- /website/docs/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installation 3 | --- 4 | 5 | ```shell 6 | # Locally in your project. 7 | npm install -D typescript 8 | npm install -D ts-node 9 | 10 | # Or globally with TypeScript. 11 | npm install -g typescript 12 | npm install -g ts-node 13 | 14 | # Depending on configuration, you may also need these 15 | npm install -D tslib @types/node 16 | ``` 17 | 18 | **Tip:** Installing modules locally allows you to control and share the versions through `package.json`. ts-node will always resolve the compiler from `cwd` before checking relative to its own installation. 19 | -------------------------------------------------------------------------------- /website/docs/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overview 3 | slug: / 4 | --- 5 | 6 | ts-node is a TypeScript execution engine and REPL for Node.js. 7 | 8 | It JIT transforms TypeScript into JavaScript, enabling you to directly execute TypeScript on Node.js without precompiling. 9 | This is accomplished by hooking node's module loading APIs, enabling it to be used seamlessly alongside other Node.js 10 | tools and libraries. 11 | 12 | ## Features 13 | 14 | * Automatic sourcemaps in stack traces 15 | * Automatic `tsconfig.json` parsing 16 | * Automatic defaults to match your node version 17 | * Typechecking (optional) 18 | * REPL 19 | * Write standalone scripts 20 | * Native ESM loader 21 | * Use third-party transpilers 22 | * Use custom transformers 23 | * Integrate with test runners, debuggers, and CLI tools 24 | * Compatible with pre-compilation for production 25 | 26 | ![TypeScript REPL](/img/screenshot.png) 27 | -------------------------------------------------------------------------------- /website/docs/paths.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: | 3 | paths and baseUrl 4 | --- 5 | 6 | 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`. 7 | 8 | ```json title="tsconfig.json" 9 | { 10 | "ts-node": { 11 | // Do not forget to `npm i -D tsconfig-paths` 12 | "require": ["tsconfig-paths/register"] 13 | } 14 | } 15 | ``` 16 | 17 | ## Why is this not built-in to ts-node? 18 | 19 | The official TypeScript Handbook explains the intended purpose for `"paths"` in ["Additional module resolution flags"](https://www.typescriptlang.org/docs/handbook/module-resolution.html#additional-module-resolution-flags). 20 | 21 | > The TypeScript compiler has a set of additional flags to *inform* the compiler of transformations that are expected to happen to the sources to generate the final output. 22 | > 23 | > It is important to note that the compiler will not perform any of these transformations; it just uses these pieces of information to guide the process of resolving a module import to its definition file. 24 | 25 | This means `"paths"` are intended to describe mappings that the build tool or runtime *already* performs, not to tell the build tool or 26 | runtime how to resolve modules. In other words, they intend us to write our imports in a way `node` already understands. For this reason, ts-node does not modify `node`'s module resolution behavior to implement `"paths"` mappings. 27 | -------------------------------------------------------------------------------- /website/docs/performance.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Performance 3 | --- 4 | 5 | These tricks will make ts-node faster. 6 | 7 | ## Skip typechecking 8 | 9 | It is often better to typecheck as part of your tests or linting. You can run `tsc --noEmit` to do this. In these cases, ts-node can skip typechecking, making it much faster. 10 | 11 | To skip typechecking in ts-node, do one of the following: 12 | 13 | * Enable [swc](./swc.md) 14 | * This is by far the fastest option 15 | * Enable [`transpileOnly`](./options.md#transpileonly) to skip typechecking without swc 16 | 17 | ## With typechecking 18 | 19 | If you absolutely must typecheck in ts-node: 20 | 21 | * Avoid dynamic `require()` which may trigger repeated typechecking; prefer `import` 22 | * Try with and without `--files`; one may be faster depending on your project 23 | * Check `tsc --showConfig`; make sure all executed files are included 24 | * Enable [`skipLibCheck`](https://www.typescriptlang.org/tsconfig#skipLibCheck) 25 | * Set a [`types`](https://www.typescriptlang.org/tsconfig#types) array to avoid loading unnecessary `@types` 26 | -------------------------------------------------------------------------------- /website/docs/recipes/ava.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: AVA 3 | --- 4 | 5 | Assuming you are configuring AVA via your `package.json`, add one of the following configurations. 6 | 7 | ## CommonJS 8 | 9 | Use this configuration if your `package.json` does not have `"type": "module"`. 10 | 11 | ```json title="package.json" 12 | { 13 | "ava": { 14 | "extensions": [ 15 | "ts" 16 | ], 17 | "require": [ 18 | "ts-node/register" 19 | ] 20 | } 21 | } 22 | ``` 23 | 24 | ## Native ECMAScript modules 25 | 26 | This configuration is necessary if your `package.json` has `"type": "module"`. 27 | 28 | ```json title="package.json" 29 | { 30 | "ava": { 31 | "extensions": { 32 | "ts": "module" 33 | }, 34 | "nonSemVerExperiments": { 35 | "configurableModuleFormat": true 36 | }, 37 | "nodeArguments": [ 38 | "--loader=ts-node/esm" 39 | ] 40 | } 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /website/docs/recipes/gulp.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Gulp 3 | --- 4 | 5 | ts-node support is built-in to gulp. 6 | 7 | ```sh 8 | # Create a `gulpfile.ts` and run `gulp`. 9 | gulp 10 | ``` 11 | 12 | See also: https://gulpjs.com/docs/en/getting-started/javascript-and-gulpfiles#transpilation 13 | -------------------------------------------------------------------------------- /website/docs/recipes/intellij.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "IntelliJ and Webstorm" 3 | --- 4 | 5 | Create a new Node.js configuration and add `-r ts-node/register` to "Node parameters." 6 | 7 | **Note:** If you are using the `--project ` command line argument as per the [Configuration Options](../configuration.md), and want to apply this same behavior when launching in IntelliJ, specify under "Environment Variables": `TS_NODE_PROJECT=`. 8 | -------------------------------------------------------------------------------- /website/docs/recipes/mocha.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mocha 3 | --- 4 | 5 | ## Mocha 7 and newer 6 | 7 | ```shell 8 | mocha --require ts-node/register --extensions ts,tsx --watch --watch-files src 'tests/**/*.{ts,tsx}' [...args] 9 | ``` 10 | 11 | Or specify options via your mocha config file. 12 | 13 | ```json title=".mocharc.json" 14 | { 15 | // Specify "require" for CommonJS 16 | "require": "ts-node/register", 17 | // Specify "loader" for native ESM 18 | "loader": "ts-node/esm", 19 | "extensions": ["ts", "tsx"], 20 | "spec": [ 21 | "tests/**/*.spec.*" 22 | ], 23 | "watch-files": [ 24 | "src" 25 | ] 26 | } 27 | ``` 28 | 29 | See also: https://mochajs.org/#configuring-mocha-nodejs 30 | 31 | ## Mocha <=6 32 | 33 | ```shell 34 | mocha --require ts-node/register --watch-extensions ts,tsx "test/**/*.{ts,tsx}" [...args] 35 | ``` 36 | 37 | **Note:** `--watch-extensions` is only used in `--watch` mode. 38 | -------------------------------------------------------------------------------- /website/docs/recipes/npx-and-yarn-dlx.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: npx and yarn dlx 3 | --- 4 | 5 | Using [`npx`](https://docs.npmjs.com/cli/v8/commands/npx) or [`yarn dlx`](https://yarnpkg.com/cli/dlx) is a great ways to publish reusable TypeScript tools to GitHub without precompiling or packaging. 6 | 7 | Check out our working example: [TypeStrong/ts-node-npx-example](https://github.com/TypeStrong/ts-node-npx-example) 8 | 9 | ```shell 10 | npx typestrong/ts-node-npx-example --help 11 | npx typestrong/ts-node-npx-example --first Arthur --last Dent 12 | ``` 13 | 14 | TODO publish demo and link to it 15 | TODO test demo: 16 | - uninstall global ts-node 17 | - try running demo 18 | - does ts-node need to be installed globally? 19 | 20 | This boilerplate is a good starting point: 21 | 22 | ```json title="package.json" 23 | { 24 | "bin": "./cli.ts", 25 | "dependencies": { 26 | "ts-node": "latest", 27 | "@swc/core": "latest", 28 | "@swc/helpers": "latest", 29 | "@tsconfig/node16": "latest" 30 | } 31 | } 32 | ``` 33 | 34 | ```json title="tsconfig.json" 35 | { 36 | "extends": "@tsconfig/node16/tsconfig.json", 37 | "ts-node": { 38 | "swc": true 39 | } 40 | } 41 | ``` 42 | 43 | ```typescript twoslash title="cli.ts" 44 | #!/usr/bin/env ts-node 45 | 46 | console.log("Hello world!") 47 | ``` 48 | 49 | If you require native ESM support, use `ts-node-esm` in your shebang and follow the configuration instructions for ESM: [Native ECMAScript modules](../commonjs-vs-native-ecmascript-modules.md#native-ecmascript-modules) 50 | 51 | ```typescript twoslash title="cli.ts" 52 | #!/usr/bin/env ts-node-esm 53 | ``` 54 | -------------------------------------------------------------------------------- /website/docs/recipes/other.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Other 3 | --- 4 | 5 | In many cases, setting [`NODE_OPTIONS`](https://nodejs.org/api/cli.html#cli_node_options_options) will enable `ts-node` within other node tools, child processes, and worker threads. 6 | 7 | ```shell 8 | NODE_OPTIONS="-r ts-node/register" 9 | ``` 10 | 11 | Or, if you require native ESM support: 12 | 13 | ```shell 14 | NODE_OPTIONS="--loader ts-node/esm" 15 | ``` 16 | 17 | This tells any node processes which receive this environment variable to install `ts-node`'s hooks before executing other code. 18 | -------------------------------------------------------------------------------- /website/docs/recipes/tape.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Tape 3 | --- 4 | 5 | ```shell 6 | ts-node node_modules/tape/bin/tape [...args] 7 | ``` 8 | -------------------------------------------------------------------------------- /website/docs/recipes/visual-studio-code.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Visual Studio Code 3 | --- 4 | 5 | Create a new Node.js debug configuration, add `-r ts-node/register` to node args and move the `program` to the `args` list (so VS Code doesn't look for `outFiles`). 6 | 7 | ```json title=".vscode/launch.json" 8 | { 9 | "configurations": [{ 10 | "type": "node", 11 | "request": "launch", 12 | "name": "Launch Program", 13 | "runtimeArgs": [ 14 | "-r", 15 | "ts-node/register" 16 | ], 17 | "args": [ 18 | "${workspaceFolder}/src/index.ts" 19 | ] 20 | }], 21 | } 22 | ``` 23 | 24 | **Note:** If you are using the `--project ` command line argument as per the [Configuration Options](../configuration.md), and want to apply this same behavior when launching in VS Code, add an "env" key into the launch configuration: `"env": { "TS_NODE_PROJECT": "" }`. 25 | -------------------------------------------------------------------------------- /website/docs/recipes/watching-and-restarting.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Watching and restarting 3 | --- 4 | 5 | ts-node focuses on adding first-class TypeScript support to node. Watching files and code reloads are out of scope for the project. 6 | 7 | If you want to restart the `ts-node` process on file change, existing node.js tools such as [nodemon](https://github.com/remy/nodemon), [onchange](https://github.com/Qard/onchange) and [node-dev](https://github.com/fgnass/node-dev) work. 8 | 9 | There's also [`ts-node-dev`](https://github.com/whitecolor/ts-node-dev), a modified version of [`node-dev`](https://github.com/fgnass/node-dev) using `ts-node` for compilation that will restart the process on file change. Note that `ts-node-dev` is incompatible with our native ESM loader. 10 | -------------------------------------------------------------------------------- /website/docs/swc.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: SWC 3 | --- 4 | 5 | SWC support is built-in via the `--swc` flag or `"swc": true` tsconfig option. 6 | 7 | [SWC](https://swc.rs) is a TypeScript-compatible transpiler implemented in Rust. This makes it an order of magnitude faster than vanilla `transpileOnly`. 8 | 9 | To use it, first install `@swc/core` or `@swc/wasm`. If using `importHelpers`, also install `@swc/helpers`. If `target` is less than "es2015" and using `async`/`await` or generator functions, also install `regenerator-runtime`. 10 | 11 | ```shell 12 | npm i -D @swc/core @swc/helpers regenerator-runtime 13 | ``` 14 | 15 | Then add the following to your `tsconfig.json`. 16 | 17 | ```json title="tsconfig.json" 18 | { 19 | "ts-node": { 20 | "swc": true 21 | } 22 | } 23 | ``` 24 | 25 | > SWC uses `@swc/helpers` instead of `tslib`. If you have enabled `importHelpers`, you must also install `@swc/helpers`. 26 | -------------------------------------------------------------------------------- /website/docs/transpilers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Transpilers 3 | --- 4 | 5 | ts-node supports third-party transpilers as plugins. Transpilers such as swc can transform TypeScript into JavaScript 6 | much faster than the TypeScript compiler. You will still benefit from ts-node's automatic `tsconfig.json` discovery, 7 | sourcemap support, and global ts-node CLI. Plugins automatically derive an appropriate configuration from your existing 8 | `tsconfig.json` which simplifies project boilerplate. 9 | 10 | > **What is the difference between a compiler and a transpiler?** 11 | > 12 | > For our purposes, a compiler implements TypeScript's API and can perform typechecking. 13 | > A third-party transpiler does not. Both transform TypeScript into JavaScript. 14 | 15 | ## Third-party plugins 16 | 17 | The `transpiler` option allows using third-party transpiler plugins with ts-node. `transpiler` must be given the 18 | name of a module which can be `require()`d. The built-in `swc` plugin is exposed as `ts-node/transpilers/swc`. 19 | 20 | For example, to use a hypothetical "@cspotcode/fast-ts-compiler", first install it into your project: `npm install @cspotcode/fast-ts-compiler` 21 | 22 | Then add the following to your tsconfig: 23 | 24 | ```json title="tsconfig.json" 25 | { 26 | "ts-node": { 27 | "transpileOnly": true, 28 | "transpiler": "@cspotcode/fast-ts-compiler" 29 | } 30 | } 31 | ``` 32 | 33 | ## Write your own plugin 34 | 35 | To write your own transpiler plugin, check our [API docs](https://typestrong.org/ts-node/api/interfaces/TranspilerModule.html). 36 | 37 | Plugins are `require()`d by ts-node, so they can be a local script or a node module published to npm. The module must 38 | export a `create` function described by our 39 | [`TranspilerModule`](https://typestrong.org/ts-node/api/interfaces/TranspilerModule.html) interface. `create` is 40 | invoked by ts-node at startup to create one or more transpiler instances. The instances are used to transform 41 | TypeScript into JavaScript. 42 | 43 | For a working example, check out out our bundled swc plugin: https://github.com/TypeStrong/ts-node/blob/main/src/transpilers/swc.ts 44 | -------------------------------------------------------------------------------- /website/docs/types.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/docs/types.md -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ts-node/website", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "serve": "docusaurus serve", 12 | "clear": "docusaurus clear", 13 | "build-readme": "./scripts/build-readme.mjs" 14 | }, 15 | "dependencies": { 16 | "@docusaurus/core": "2.0.0-beta.17", 17 | "@docusaurus/preset-classic": "2.0.0-beta.17", 18 | "@mdx-js/react": "^1.6.22", 19 | "@types/js-yaml": "^4.0.0", 20 | "clsx": "^1.1.1", 21 | "docusaurus-preset-shiki-twoslash": "^1.1.36", 22 | "js-yaml": "^4.0.0", 23 | "react": "^17.0.2", 24 | "react-dom": "^17.0.2", 25 | "remark": "^13.0.0", 26 | "remark-behead": "^2.3.3", 27 | "remark-frontmatter": "^3.0.0", 28 | "remark-preset-lint-recommended": "^5.0.0", 29 | "remark-toc": "^7.2.0", 30 | "remark-validate-links": "^10.0.4", 31 | "vfile": "^4.2.1", 32 | "vfile-reporter": "^6.0.2" 33 | }, 34 | "browserslist": { 35 | "production": [ 36 | ">0.5%", 37 | "not dead", 38 | "not op_mini all" 39 | ], 40 | "development": [ 41 | "last 1 chrome version", 42 | "last 1 firefox version", 43 | "last 1 safari version" 44 | ] 45 | }, 46 | "packageManager": "yarn@1.22.17", 47 | "volta": { 48 | "extends": "../package.json", 49 | "yarn": "1.22.17" 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /website/readme-sources/license.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: License 3 | --- 4 | 5 | ts-node is licensed under the MIT license. [MIT](https://github.com/TypeStrong/ts-node/blob/main/LICENSE) 6 | 7 | ts-node includes source code from Node.js which is licensed under the MIT license. [Node.js license information](https://raw.githubusercontent.com/nodejs/node/master/LICENSE) 8 | 9 | ts-node includes source code from the TypeScript compiler which is licensed under the Apache License 2.0. [TypeScript license information](https://github.com/microsoft/TypeScript/blob/master/LICENSE.txt) 10 | -------------------------------------------------------------------------------- /website/readme-sources/prefix.md: -------------------------------------------------------------------------------- 1 | --- 2 | omitHeaderOnMerge: true 3 | --- 4 | 5 | 16 | 17 | # [![TypeScript Node](logo.svg?sanitize=true)](https://typestrong.org/ts-node) 18 | 19 | [![NPM version](https://img.shields.io/npm/v/ts-node.svg?style=flat)](https://npmjs.org/package/ts-node) 20 | [![NPM downloads](https://img.shields.io/npm/dm/ts-node.svg?style=flat)](https://npmjs.org/package/ts-node) 21 | [![Build status](https://img.shields.io/github/actions/workflow/status/TypeStrong/ts-node/continuous-integration.yml?branch=main)](https://github.com/TypeStrong/ts-node/actions?query=workflow%3A%22Continuous+Integration%22) 22 | [![Test coverage](https://codecov.io/gh/TypeStrong/ts-node/branch/main/graph/badge.svg)](https://codecov.io/gh/TypeStrong/ts-node) 23 | 24 | > TypeScript execution and REPL for node.js, with source map and native ESM support. 25 | 26 | The latest documentation can also be found on our website: [https://typestrong.org/ts-node](https://typestrong.org/ts-node) 27 | 28 | # Table of Contents 29 | -------------------------------------------------------------------------------- /website/sidebars.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | primarySidebar: [ 3 | { 4 | type: 'category', 5 | label: 'General', 6 | collapsed: false, 7 | items: [ 8 | 'overview', 9 | 'installation', 10 | 'usage', 11 | 'configuration', 12 | 'options', 13 | 'swc', 14 | 'commonjs-vs-native-ecmascript-modules', 15 | 'troubleshooting', 16 | 'performance', 17 | ], 18 | }, 19 | { 20 | type: 'category', 21 | label: 'Advanced', 22 | collapsed: false, 23 | items: ['how-it-works', 'scope', 'paths', 'compilers', 'transpilers', 'module-type-overrides', 'api'], 24 | }, 25 | { 26 | type: 'category', 27 | label: 'Recipes', 28 | collapsed: false, 29 | items: [ 30 | 'recipes/watching-and-restarting', 31 | // 'recipes/npx-and-yarn-dlx', 32 | 'recipes/ava', 33 | 'recipes/gulp', 34 | 'recipes/intellij', 35 | 'recipes/mocha', 36 | 'recipes/tape', 37 | 'recipes/visual-studio-code', 38 | 'recipes/other', 39 | ], 40 | }, 41 | ], 42 | hiddenSidebar: [ 43 | { 44 | type: 'category', 45 | label: 'Hidden pages', 46 | collapsed: false, 47 | items: ['options-table'], 48 | }, 49 | ], 50 | }; 51 | -------------------------------------------------------------------------------- /website/src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | 3 | /** 4 | * CSS files with the .module.css suffix will be treated as CSS modules 5 | * and scoped locally. 6 | */ 7 | 8 | .heroBanner { 9 | padding: 4rem 0; 10 | text-align: center; 11 | position: relative; 12 | overflow: hidden; 13 | } 14 | 15 | @media screen and (max-width: 966px) { 16 | .heroBanner { 17 | padding: 2rem; 18 | } 19 | } 20 | 21 | .buttons { 22 | display: flex; 23 | align-items: center; 24 | justify-content: center; 25 | } 26 | 27 | .features { 28 | display: flex; 29 | align-items: center; 30 | padding: 2rem 0; 31 | width: 100%; 32 | } 33 | 34 | .featureImage { 35 | height: 200px; 36 | width: 200px; 37 | } 38 | -------------------------------------------------------------------------------- /website/src/theme/DocBreadcrumbs/index.tsx: -------------------------------------------------------------------------------- 1 | // Change: HomeBreadcrumbItem points to /docs instead of / 2 | 3 | import React, { type ReactNode } from 'react'; 4 | import { ThemeClassNames, useSidebarBreadcrumbs, useHomePageRoute } from '@docusaurus/theme-common'; 5 | import styles from './styles.module.css'; 6 | import clsx from 'clsx'; 7 | import Link from '@docusaurus/Link'; 8 | import useBaseUrl from '@docusaurus/useBaseUrl'; 9 | 10 | function BreadcrumbsItemLink({ children, href }: { children: ReactNode; href?: string }): JSX.Element { 11 | const className = clsx('breadcrumbs__link', styles.breadcrumbsItemLink); 12 | return href ? ( 13 | 14 | {children} 15 | 16 | ) : ( 17 | {children} 18 | ); 19 | } 20 | 21 | function BreadcrumbsItem({ children, active }: { children: ReactNode; active?: boolean }): JSX.Element { 22 | return ( 23 |
  • 28 | {children} 29 |
  • 30 | ); 31 | } 32 | 33 | function HomeBreadcrumbItem() { 34 | const homeHref = useBaseUrl('/docs'); 35 | return ( 36 | 37 | 🏠 38 | 39 | ); 40 | } 41 | 42 | export default function DocBreadcrumbs(): JSX.Element | null { 43 | const breadcrumbs = useSidebarBreadcrumbs(); 44 | const homePageRoute = useHomePageRoute(); 45 | 46 | if (!breadcrumbs) { 47 | return null; 48 | } 49 | 50 | return ( 51 | 61 | ); 62 | } 63 | -------------------------------------------------------------------------------- /website/src/theme/DocBreadcrumbs/styles.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .breadcrumbsContainer { 9 | margin-bottom: 0.4rem; 10 | } 11 | 12 | .breadcrumbsItemLink { 13 | --ifm-breadcrumb-size-multiplier: 0.7 !important; 14 | margin-bottom: 0.4rem; 15 | background: var(--ifm-color-gray-100); 16 | } 17 | 18 | html[data-theme='dark'] .breadcrumbsItemLink { 19 | background-color: var(--ifm-color-gray-900); 20 | } 21 | 22 | @media (min-width: 997px) { 23 | .breadcrumbsItemLink { 24 | --ifm-breadcrumb-size-multiplier: 0.8; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /website/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/.nojekyll -------------------------------------------------------------------------------- /website/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/img/favicon.ico -------------------------------------------------------------------------------- /website/static/img/favicon/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/img/favicon/android-chrome-192x192.png -------------------------------------------------------------------------------- /website/static/img/favicon/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/img/favicon/android-chrome-512x512.png -------------------------------------------------------------------------------- /website/static/img/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/img/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /website/static/img/favicon/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | #2b5797 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /website/static/img/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/img/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /website/static/img/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/img/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /website/static/img/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/img/favicon/favicon.ico -------------------------------------------------------------------------------- /website/static/img/favicon/html_code.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /website/static/img/favicon/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/img/favicon/mstile-150x150.png -------------------------------------------------------------------------------- /website/static/img/favicon/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.14, written by Peter Selinger 2001-2017 9 | 10 | 12 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /website/static/img/favicon/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "", 3 | "short_name": "", 4 | "icons": [ 5 | { 6 | "src": "/ts-node/img/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/ts-node/img/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "theme_color": "#ffffff", 17 | "background_color": "#ffffff", 18 | "display": "standalone" 19 | } 20 | -------------------------------------------------------------------------------- /website/static/img/logo-icon.svg: -------------------------------------------------------------------------------- 1 | ../../../logo-icon.svg -------------------------------------------------------------------------------- /website/static/img/opengraph.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/img/opengraph.pdn -------------------------------------------------------------------------------- /website/static/img/opengraph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/img/opengraph.png -------------------------------------------------------------------------------- /website/static/img/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TypeStrong/ts-node/ddb05ef23be92a90c3ecac5a0220435c65ebbd2a/website/static/img/screenshot.png -------------------------------------------------------------------------------- /website/types/lib_greeter.ts: -------------------------------------------------------------------------------- 1 | declare module 'lib_greeter' { 2 | /** API for saying hello to everyone. */ 3 | export class Greeter { 4 | /** Returns a friendly salutation and a remark about the weather */ 5 | sayHello(): string; 6 | } 7 | } 8 | --------------------------------------------------------------------------------