UNPKG

13.9 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.getTsConfigDefaults = exports.ComputeAsCommonRootOfFiles = exports.loadCompiler = exports.resolveAndLoadCompiler = exports.readConfig = exports.findAndReadConfig = void 0;
4const path_1 = require("path");
5const index_1 = require("./index");
6const ts_internals_1 = require("./ts-internals");
7const tsconfigs_1 = require("./tsconfigs");
8const util_1 = require("./util");
9/**
10 * TypeScript compiler option values required by `ts-node` which cannot be overridden.
11 */
12const TS_NODE_COMPILER_OPTIONS = {
13 sourceMap: true,
14 inlineSourceMap: false,
15 inlineSources: true,
16 declaration: false,
17 noEmit: false,
18 outDir: '.ts-node',
19};
20/*
21 * Do post-processing on config options to support `ts-node`.
22 */
23function fixConfig(ts, config) {
24 // Delete options that *should not* be passed through.
25 delete config.options.out;
26 delete config.options.outFile;
27 delete config.options.composite;
28 delete config.options.declarationDir;
29 delete config.options.declarationMap;
30 delete config.options.emitDeclarationOnly;
31 // Target ES5 output by default (instead of ES3).
32 if (config.options.target === undefined) {
33 config.options.target = ts.ScriptTarget.ES5;
34 }
35 // Target CommonJS modules by default (instead of magically switching to ES6 when the target is ES6).
36 if (config.options.module === undefined) {
37 config.options.module = ts.ModuleKind.CommonJS;
38 }
39 return config;
40}
41/** @internal */
42function findAndReadConfig(rawOptions) {
43 var _a, _b, _c, _d, _e;
44 const cwd = (0, path_1.resolve)((_c = (_b = (_a = rawOptions.cwd) !== null && _a !== void 0 ? _a : rawOptions.dir) !== null && _b !== void 0 ? _b : index_1.DEFAULTS.cwd) !== null && _c !== void 0 ? _c : process.cwd());
45 const compilerName = (_d = rawOptions.compiler) !== null && _d !== void 0 ? _d : index_1.DEFAULTS.compiler;
46 // Compute minimum options to read the config file.
47 let projectLocalResolveDir = (0, util_1.getBasePathForProjectLocalDependencyResolution)(undefined, rawOptions.projectSearchDir, rawOptions.project, cwd);
48 let { compiler, ts } = resolveAndLoadCompiler(compilerName, projectLocalResolveDir);
49 // Read config file and merge new options between env and CLI options.
50 const { configFilePath, config, tsNodeOptionsFromTsconfig, optionBasePaths } = readConfig(cwd, ts, rawOptions);
51 const options = (0, util_1.assign)({}, index_1.DEFAULTS, tsNodeOptionsFromTsconfig || {}, { optionBasePaths }, rawOptions);
52 options.require = [
53 ...(tsNodeOptionsFromTsconfig.require || []),
54 ...(rawOptions.require || []),
55 ];
56 // Re-resolve the compiler in case it has changed.
57 // Compiler is loaded relative to tsconfig.json, so tsconfig discovery may cause us to load a
58 // different compiler than we did above, even if the name has not changed.
59 if (configFilePath) {
60 projectLocalResolveDir = (0, util_1.getBasePathForProjectLocalDependencyResolution)(configFilePath, rawOptions.projectSearchDir, rawOptions.project, cwd);
61 ({ compiler } = resolveCompiler(options.compiler, (_e = optionBasePaths.compiler) !== null && _e !== void 0 ? _e : projectLocalResolveDir));
62 }
63 return {
64 options,
65 config,
66 projectLocalResolveDir,
67 optionBasePaths,
68 configFilePath,
69 cwd,
70 compiler,
71 };
72}
73exports.findAndReadConfig = findAndReadConfig;
74/**
75 * Load TypeScript configuration. Returns the parsed TypeScript config and
76 * any `ts-node` options specified in the config file.
77 *
78 * Even when a tsconfig.json is not loaded, this function still handles merging
79 * compilerOptions from various sources: API, environment variables, etc.
80 *
81 * @internal
82 */
83function readConfig(cwd, ts, rawApiOptions) {
84 var _a, _b, _c;
85 // Ordered [a, b, c] where config a extends b extends c
86 const configChain = [];
87 let config = { compilerOptions: {} };
88 let basePath = cwd;
89 let configFilePath = undefined;
90 const projectSearchDir = (0, path_1.resolve)(cwd, (_a = rawApiOptions.projectSearchDir) !== null && _a !== void 0 ? _a : cwd);
91 const { fileExists = ts.sys.fileExists, readFile = ts.sys.readFile, skipProject = index_1.DEFAULTS.skipProject, project = index_1.DEFAULTS.project, tsTrace = index_1.DEFAULTS.tsTrace, } = rawApiOptions;
92 // Read project configuration when available.
93 if (!skipProject) {
94 if (project) {
95 const resolved = (0, path_1.resolve)(cwd, project);
96 const nested = (0, path_1.join)(resolved, 'tsconfig.json');
97 configFilePath = fileExists(nested) ? nested : resolved;
98 }
99 else {
100 configFilePath = ts.findConfigFile(projectSearchDir, fileExists);
101 }
102 if (configFilePath) {
103 let pathToNextConfigInChain = configFilePath;
104 const tsInternals = (0, ts_internals_1.createTsInternals)(ts);
105 const errors = [];
106 // Follow chain of "extends"
107 while (true) {
108 const result = ts.readConfigFile(pathToNextConfigInChain, readFile);
109 // Return diagnostics.
110 if (result.error) {
111 return {
112 configFilePath,
113 config: { errors: [result.error], fileNames: [], options: {} },
114 tsNodeOptionsFromTsconfig: {},
115 optionBasePaths: {},
116 };
117 }
118 const c = result.config;
119 const bp = (0, path_1.dirname)(pathToNextConfigInChain);
120 configChain.push({
121 config: c,
122 basePath: bp,
123 configPath: pathToNextConfigInChain,
124 });
125 if (c.extends == null)
126 break;
127 const resolvedExtendedConfigPath = tsInternals.getExtendsConfigPath(c.extends, {
128 fileExists,
129 readDirectory: ts.sys.readDirectory,
130 readFile,
131 useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
132 trace: tsTrace,
133 }, bp, errors, ts.createCompilerDiagnostic);
134 if (errors.length) {
135 return {
136 configFilePath,
137 config: { errors, fileNames: [], options: {} },
138 tsNodeOptionsFromTsconfig: {},
139 optionBasePaths: {},
140 };
141 }
142 if (resolvedExtendedConfigPath == null)
143 break;
144 pathToNextConfigInChain = resolvedExtendedConfigPath;
145 }
146 ({ config, basePath } = configChain[0]);
147 }
148 }
149 // Merge and fix ts-node options that come from tsconfig.json(s)
150 const tsNodeOptionsFromTsconfig = {};
151 const optionBasePaths = {};
152 for (let i = configChain.length - 1; i >= 0; i--) {
153 const { config, basePath, configPath } = configChain[i];
154 const options = filterRecognizedTsConfigTsNodeOptions(config['ts-node']).recognized;
155 // Some options are relative to the config file, so must be converted to absolute paths here
156 if (options.require) {
157 // Modules are found relative to the tsconfig file, not the `dir` option
158 const tsconfigRelativeResolver = (0, util_1.createProjectLocalResolveHelper)((0, path_1.dirname)(configPath));
159 options.require = options.require.map((path) => tsconfigRelativeResolver(path, false));
160 }
161 if (options.scopeDir) {
162 options.scopeDir = (0, path_1.resolve)(basePath, options.scopeDir);
163 }
164 // Downstream code uses the basePath; we do not do that here.
165 if (options.moduleTypes) {
166 optionBasePaths.moduleTypes = basePath;
167 }
168 if (options.transpiler != null) {
169 optionBasePaths.transpiler = basePath;
170 }
171 if (options.compiler != null) {
172 optionBasePaths.compiler = basePath;
173 }
174 if (options.swc != null) {
175 optionBasePaths.swc = basePath;
176 }
177 (0, util_1.assign)(tsNodeOptionsFromTsconfig, options);
178 }
179 // Remove resolution of "files".
180 const files = (_c = (_b = rawApiOptions.files) !== null && _b !== void 0 ? _b : tsNodeOptionsFromTsconfig.files) !== null && _c !== void 0 ? _c : index_1.DEFAULTS.files;
181 // Only if a config file is *not* loaded, load an implicit configuration from @tsconfig/bases
182 const skipDefaultCompilerOptions = configFilePath != null;
183 const defaultCompilerOptionsForNodeVersion = skipDefaultCompilerOptions
184 ? undefined
185 : {
186 ...(0, tsconfigs_1.getDefaultTsconfigJsonForNodeVersion)(ts).compilerOptions,
187 types: ['node'],
188 };
189 // Merge compilerOptions from all sources
190 config.compilerOptions = Object.assign({},
191 // automatically-applied options from @tsconfig/bases
192 defaultCompilerOptionsForNodeVersion,
193 // tsconfig.json "compilerOptions"
194 config.compilerOptions,
195 // from env var
196 index_1.DEFAULTS.compilerOptions,
197 // tsconfig.json "ts-node": "compilerOptions"
198 tsNodeOptionsFromTsconfig.compilerOptions,
199 // passed programmatically
200 rawApiOptions.compilerOptions,
201 // overrides required by ts-node, cannot be changed
202 TS_NODE_COMPILER_OPTIONS);
203 const fixedConfig = fixConfig(ts, ts.parseJsonConfigFileContent(config, {
204 fileExists,
205 readFile,
206 // Only used for globbing "files", "include", "exclude"
207 // When `files` option disabled, we want to avoid the fs calls
208 readDirectory: files ? ts.sys.readDirectory : () => [],
209 useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
210 }, basePath, undefined, configFilePath));
211 return {
212 configFilePath,
213 config: fixedConfig,
214 tsNodeOptionsFromTsconfig,
215 optionBasePaths,
216 };
217}
218exports.readConfig = readConfig;
219/**
220 * Load the typescript compiler. It is required to load the tsconfig but might
221 * be changed by the tsconfig, so we have to do this twice.
222 * @internal
223 */
224function resolveAndLoadCompiler(name, relativeToPath) {
225 const { compiler } = resolveCompiler(name, relativeToPath);
226 const ts = loadCompiler(compiler);
227 return { compiler, ts };
228}
229exports.resolveAndLoadCompiler = resolveAndLoadCompiler;
230function resolveCompiler(name, relativeToPath) {
231 const projectLocalResolveHelper = (0, util_1.createProjectLocalResolveHelper)(relativeToPath);
232 const compiler = projectLocalResolveHelper(name || 'typescript', true);
233 return { compiler };
234}
235/** @internal */
236function loadCompiler(compiler) {
237 return (0, util_1.attemptRequireWithV8CompileCache)(require, compiler);
238}
239exports.loadCompiler = loadCompiler;
240/**
241 * Given the raw "ts-node" sub-object from a tsconfig, return an object with only the properties
242 * recognized by "ts-node"
243 */
244function filterRecognizedTsConfigTsNodeOptions(jsonObject) {
245 if (jsonObject == null)
246 return { recognized: {}, unrecognized: {} };
247 const { compiler, compilerHost, compilerOptions, emit, files, ignore, ignoreDiagnostics, logError, preferTsExts, pretty, require, skipIgnore, transpileOnly, typeCheck, transpiler, scope, scopeDir, moduleTypes, experimentalReplAwait, swc, experimentalResolver, esm, experimentalSpecifierResolution, experimentalTsImportSpecifiers, ...unrecognized } = jsonObject;
248 const filteredTsConfigOptions = {
249 compiler,
250 compilerHost,
251 compilerOptions,
252 emit,
253 experimentalReplAwait,
254 files,
255 ignore,
256 ignoreDiagnostics,
257 logError,
258 preferTsExts,
259 pretty,
260 require,
261 skipIgnore,
262 transpileOnly,
263 typeCheck,
264 transpiler,
265 scope,
266 scopeDir,
267 moduleTypes,
268 swc,
269 experimentalResolver,
270 esm,
271 experimentalSpecifierResolution,
272 experimentalTsImportSpecifiers,
273 };
274 // Use the typechecker to make sure this implementation has the correct set of properties
275 const catchExtraneousProps = null;
276 const catchMissingProps = null;
277 return { recognized: filteredTsConfigOptions, unrecognized };
278}
279/** @internal */
280exports.ComputeAsCommonRootOfFiles = Symbol();
281/**
282 * Some TS compiler options have defaults which are not provided by TS's config parsing functions.
283 * This function centralizes the logic for computing those defaults.
284 * @internal
285 */
286function getTsConfigDefaults(config, basePath, _files, _include, _exclude) {
287 const { composite = false } = config.options;
288 let rootDir = config.options.rootDir;
289 if (rootDir == null) {
290 if (composite)
291 rootDir = basePath;
292 // Return this symbol to avoid computing from `files`, which would require fs calls
293 else
294 rootDir = exports.ComputeAsCommonRootOfFiles;
295 }
296 const { outDir = rootDir } = config.options;
297 // Docs are wrong: https://www.typescriptlang.org/tsconfig#include
298 // Docs say **, but it's actually **/*; compiler throws error for **
299 const include = _files ? [] : ['**/*'];
300 const files = _files !== null && _files !== void 0 ? _files : [];
301 // Docs are misleading: https://www.typescriptlang.org/tsconfig#exclude
302 // Docs say it excludes node_modules, bower_components, jspm_packages, but actually those are excluded via behavior of "include"
303 const exclude = _exclude !== null && _exclude !== void 0 ? _exclude : [outDir]; // TODO technically, outDir is absolute path, but exclude should be relative glob pattern?
304 // TODO compute baseUrl
305 return { rootDir, outDir, include, files, exclude, composite };
306}
307exports.getTsConfigDefaults = getTsConfigDefaults;
308//# sourceMappingURL=configuration.js.map
\No newline at end of file