Skip to content

Commit d8f5677

Browse files
committed
Add the ability to run TypeScript files from CLI
This allows `ts-node` to be used to run TypeScript files without having to compile them with `tsc` first. It also adds the necessary configs, including `tsconfig-paths` for `paths` import-alias resolution. Unfortunately, this means we have to remove the `--experimental-module-resolution=node` since `ts-node` uses its own loader and thus form of resolving modules. See: Setup * https://medium.com/@jimcraft123hd/setting-up-path-alias-in-typescript-and-tsc-build-without-error-9f1dbc0bccd2 Issues with `ts-node`, ESM, and aliases * TypeStrong/ts-node#1007 - TypeStrong/ts-node#476 - dividab/tsconfig-paths#122 (comment) - TypeStrong/ts-node#1450 (comment) * TypeStrong/ts-node#1414 * TypeStrong/ts-node#995 - TypeStrong/ts-node#639 Node issues with ESM * https://nodejs.org/api/packages.html#determining-module-system * nodejs/node#37468
1 parent 4593a5a commit d8f5677

8 files changed

+126
-83
lines changed

.npmrc

+43-5
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,49 @@ engine-strict=true
5151
# Options only include those that are valid `NODE_OPTIONS`.
5252
# See: https://nodejs.org/api/cli.html#cli_node_options_options
5353
#
54-
# Allow top-level `await` calls so that webpack.config.mjs can await CJS imports.
55-
# Allow JSON files to be imported in .mjs files.
56-
# Allow automatic extension resolution as well as importing index.js from directories like source code can (e.g. `import file from './file'` instead of './file.js', and `import Utils from './utils'` instead of './utils/index.js').
57-
# Allow the use of `import.meta.resolve` to use file paths to generate import-safe URLs (different from browser-safe URLs).
58-
node-options='--experimental-top-level-await --experimental-json-modules --experimental-specifier-resolution=node --experimental-import-meta-resolve'
54+
# Notable ones include:
55+
#
56+
# * --experimental-top-level-await
57+
# Allow top-level `await` calls so that webpack.config.mjs can await CJS imports.
58+
#
59+
#
60+
# * --experimental-json-modules
61+
# Allow JSON files to be imported in .mjs files.
62+
#
63+
#
64+
# * --experimental-import-meta-resolve
65+
# Allow the use of `import.meta.resolve` to use file paths to generate import-safe URLs (different from browser-safe URLs).
66+
#
67+
#
68+
# * --experimental-specifier-resolution=node
69+
# Allow automatic extension resolution as well as importing index.js from directories like source code can
70+
# e.g. `import file from './file'` instead of './file.js', and `import Utils from './utils'` instead of './utils/index.js'.
71+
# Note: This will cause some `npx` commands to fail if the executables don't have a file extension on them (e.g. `npx tsc`).
72+
# Relatedly, if using a different script runner/node module loader, e.g. `ts-node` to run TypeScript files, then they will
73+
# sometimes fail as well b/c they'll either be shell scripts, will need their custom module loader (which won't work b/c we
74+
# overrode it with this flag), or their loaders depending on files being translated to CommonJS before being executed (likely in RAM
75+
# by their custom loader and/or NodeJS itself).
76+
# This can be fixed in your own code by making it executable and adding a shebang, e.g.
77+
# #!/usr/bin/env -S node
78+
# #!/usr/bin/env -S npx
79+
# #!/usr/bin/env -S npx ts-node
80+
# For example, to use `ts-node` (for running TypeScript files from the CLI without having to compile them into JavaScript first),
81+
# then they recommend running via either:
82+
# 1. Using ts-node directly: `ts-node file.ts`
83+
# 2. Using normal node command: ESM: `node --loader ts-node/esm file.ts` - CJS: `node -r ts-node/register file.ts`
84+
# 3. Just run the file directly: Use a shebang like above (See: https://github.com/TypeStrong/ts-node/issues/639)
85+
# 4. Add `--loader ts-node/(register|esm)` to `node-options` here (forces all node commands to run with `ts-node`, even `npx`)
86+
# n. TL;DR - Check out this issue for a full analysis of way to run `ts-node`: https://github.com/TypeStrong/ts-node/issues/995
87+
# But since `ts-node` uses its own module loader, we cannot set `--experimental-specifier-resolution=node` in `node-options`
88+
# b/c it requires its own loader.
89+
# Finally, for `ts-node`, if package.json uses `type: module`, then `ts-node` must use `module: ESNext` as well.
90+
#
91+
#
92+
# * --no-warnings / --redirect-warnings=<file>
93+
# Removes warnings from STDERR or redirects them to <file>.
94+
# If you want to use ts-node by default for all files, then this will be necessary to reduce console noise:
95+
# --loader=ts-node/register --no-warnings
96+
node-options='--experimental-top-level-await --experimental-json-modules --experimental-import-meta-resolve'
5997

6098

6199
# For some reason, `npm run` doesn't use the default shell,

config/jest/jest.config.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import fs from 'fs';
22

33
import { defaults } from 'jest-config';
44

5-
import { Paths, FileTypeRegexes, ImportAliases } from '../utils';
5+
import { Paths, FileTypeRegexes, ImportAliases } from '../utils/index.js';
66

77
/*
88
* Note: Add the `--no-cache` CLI option during development of jest transformers

config/jest/jestAssetTransformer.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import path from 'path';
22

33
import JestCssModulesTransformer from 'jest-css-modules-transform';
44

5-
import { FileTypeRegexes } from '../utils';
5+
import { FileTypeRegexes } from '../utils/index.js';
66

77

88
/** @type {import('@jest/core/node_modules/@jest/transform/build/types').SyncTransformer} */

config/utils/ESM/index.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export * from './Imports';
1+
export * from './Imports.mjs';

config/webpack.config.mjs

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ import CopyWebpackPlugin from 'copy-webpack-plugin';
55
import TerserJSPlugin from 'terser-webpack-plugin';
66
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
77
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
8-
import MockRequestsWebpackPlugin from 'mock-requests/bin/MockRequestsWebpackPlugin';
8+
import MockRequestsWebpackPlugin from 'mock-requests/bin/MockRequestsWebpackPlugin.js';
99

10-
import AlterFilePostBuildPlugin from './AlterFilePostBuildPlugin';
10+
import AlterFilePostBuildPlugin from './AlterFilePostBuildPlugin.mjs';
1111
import {
1212
Paths,
1313
FileTypeRegexes,
1414
getOutputFileName,
1515
ImportAliases,
1616
LocalLanHostIpAddresses,
17-
} from './utils';
18-
import babelConfig from './babel.config';
17+
} from './utils/index.js';
18+
import babelConfig from './babel.config.js';
1919

2020
import packageJson from '../package.json';
2121
import manifestJson from '../src/manifest.json';

package-lock.json

+20-70
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@
109109
"shelljs": "^0.8.4",
110110
"terser-webpack-plugin": "^4.2.3",
111111
"ts-loader": "^9.2.6",
112+
"ts-node": "^10.4.0",
113+
"tsconfig-paths": "^3.12.0",
112114
"typescript": "^4.5.4",
113115
"webpack": "^5.61.0",
114116
"webpack-cli": "^4.9.1",

0 commit comments

Comments
 (0)