UNPKG

8.8 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.createSwcOptions = exports.targetMapping = exports.create = void 0;
4function create(createOptions) {
5 const { swc, service: { config, projectLocalResolveHelper }, transpilerConfigLocalResolveHelper, nodeModuleEmitKind, } = createOptions;
6 // Load swc compiler
7 let swcInstance;
8 // Used later in diagnostics; merely needs to be human-readable.
9 let swcDepName = 'swc';
10 if (typeof swc === 'string') {
11 swcDepName = swc;
12 swcInstance = require(transpilerConfigLocalResolveHelper(swc, true));
13 }
14 else if (swc == null) {
15 let swcResolved;
16 try {
17 swcDepName = '@swc/core';
18 swcResolved = transpilerConfigLocalResolveHelper(swcDepName, true);
19 }
20 catch (e) {
21 try {
22 swcDepName = '@swc/wasm';
23 swcResolved = transpilerConfigLocalResolveHelper(swcDepName, true);
24 }
25 catch (e) {
26 throw new Error('swc compiler requires either @swc/core or @swc/wasm to be installed as a dependency. See https://typestrong.org/ts-node/docs/transpilers');
27 }
28 }
29 swcInstance = require(swcResolved);
30 }
31 else {
32 swcInstance = swc;
33 }
34 // Prepare SWC options derived from typescript compiler options
35 const { nonTsxOptions, tsxOptions } = createSwcOptions(config.options, nodeModuleEmitKind, swcInstance, swcDepName);
36 const transpile = (input, transpileOptions) => {
37 const { fileName } = transpileOptions;
38 const swcOptions = fileName.endsWith('.tsx') || fileName.endsWith('.jsx')
39 ? tsxOptions
40 : nonTsxOptions;
41 const { code, map } = swcInstance.transformSync(input, {
42 ...swcOptions,
43 filename: fileName,
44 });
45 return { outputText: code, sourceMapText: map };
46 };
47 return {
48 transpile,
49 };
50}
51exports.create = create;
52/** @internal */
53exports.targetMapping = new Map();
54exports.targetMapping.set(/* ts.ScriptTarget.ES3 */ 0, 'es3');
55exports.targetMapping.set(/* ts.ScriptTarget.ES5 */ 1, 'es5');
56exports.targetMapping.set(/* ts.ScriptTarget.ES2015 */ 2, 'es2015');
57exports.targetMapping.set(/* ts.ScriptTarget.ES2016 */ 3, 'es2016');
58exports.targetMapping.set(/* ts.ScriptTarget.ES2017 */ 4, 'es2017');
59exports.targetMapping.set(/* ts.ScriptTarget.ES2018 */ 5, 'es2018');
60exports.targetMapping.set(/* ts.ScriptTarget.ES2019 */ 6, 'es2019');
61exports.targetMapping.set(/* ts.ScriptTarget.ES2020 */ 7, 'es2020');
62exports.targetMapping.set(/* ts.ScriptTarget.ES2021 */ 8, 'es2021');
63exports.targetMapping.set(/* ts.ScriptTarget.ES2022 */ 9, 'es2022');
64exports.targetMapping.set(/* ts.ScriptTarget.ESNext */ 99, 'es2022');
65/**
66 * @internal
67 * We use this list to downgrade to a prior target when we probe swc to detect if it supports a particular target
68 */
69const swcTargets = [
70 'es3',
71 'es5',
72 'es2015',
73 'es2016',
74 'es2017',
75 'es2018',
76 'es2019',
77 'es2020',
78 'es2021',
79 'es2022',
80];
81const ModuleKind = {
82 None: 0,
83 CommonJS: 1,
84 AMD: 2,
85 UMD: 3,
86 System: 4,
87 ES2015: 5,
88 ES2020: 6,
89 ESNext: 99,
90 Node16: 100,
91 NodeNext: 199,
92};
93const JsxEmit = {
94 ReactJSX: /* ts.JsxEmit.ReactJSX */ 4,
95 ReactJSXDev: /* ts.JsxEmit.ReactJSXDev */ 5,
96};
97/**
98 * Prepare SWC options derived from typescript compiler options.
99 * @internal exported for testing
100 */
101function createSwcOptions(compilerOptions, nodeModuleEmitKind, swcInstance, swcDepName) {
102 var _a;
103 const { esModuleInterop, sourceMap, importHelpers, experimentalDecorators, emitDecoratorMetadata, target, module, jsx, jsxFactory, jsxFragmentFactory, strict, alwaysStrict, noImplicitUseStrict, } = compilerOptions;
104 let swcTarget = (_a = exports.targetMapping.get(target)) !== null && _a !== void 0 ? _a : 'es3';
105 // Downgrade to lower target if swc does not support the selected target.
106 // Perhaps project has an older version of swc.
107 // TODO cache the results of this; slightly faster
108 let swcTargetIndex = swcTargets.indexOf(swcTarget);
109 for (; swcTargetIndex >= 0; swcTargetIndex--) {
110 try {
111 swcInstance.transformSync('', {
112 jsc: { target: swcTargets[swcTargetIndex] },
113 });
114 break;
115 }
116 catch (e) { }
117 }
118 swcTarget = swcTargets[swcTargetIndex];
119 const keepClassNames = target >= /* ts.ScriptTarget.ES2016 */ 3;
120 const isNodeModuleKind = module === ModuleKind.Node16 || module === ModuleKind.NodeNext;
121 // swc only supports these 4x module options [MUST_UPDATE_FOR_NEW_MODULEKIND]
122 const moduleType = module === ModuleKind.CommonJS
123 ? 'commonjs'
124 : module === ModuleKind.AMD
125 ? 'amd'
126 : module === ModuleKind.UMD
127 ? 'umd'
128 : isNodeModuleKind && nodeModuleEmitKind === 'nodecjs'
129 ? 'commonjs'
130 : isNodeModuleKind && nodeModuleEmitKind === 'nodeesm'
131 ? 'es6'
132 : 'es6';
133 // In swc:
134 // strictMode means `"use strict"` is *always* emitted for non-ES module, *never* for ES module where it is assumed it can be omitted.
135 // (this assumption is invalid, but that's the way swc behaves)
136 // tsc is a bit more complex:
137 // alwaysStrict will force emitting it always unless `import`/`export` syntax is emitted which implies it per the JS spec.
138 // if not alwaysStrict, will emit implicitly whenever module target is non-ES *and* transformed module syntax is emitted.
139 // For node, best option is to assume that all scripts are modules (commonjs or esm) and thus should get tsc's implicit strict behavior.
140 // Always set strictMode, *unless* alwaysStrict is disabled and noImplicitUseStrict is enabled
141 const strictMode =
142 // if `alwaysStrict` is disabled, remembering that `strict` defaults `alwaysStrict` to true
143 (alwaysStrict === false || (alwaysStrict !== true && strict !== true)) &&
144 // if noImplicitUseStrict is enabled
145 noImplicitUseStrict === true
146 ? false
147 : true;
148 const jsxRuntime = jsx === JsxEmit.ReactJSX || jsx === JsxEmit.ReactJSXDev
149 ? 'automatic'
150 : undefined;
151 const jsxDevelopment = jsx === JsxEmit.ReactJSXDev ? true : undefined;
152 const nonTsxOptions = createVariant(false);
153 const tsxOptions = createVariant(true);
154 return { nonTsxOptions, tsxOptions };
155 function createVariant(isTsx) {
156 const swcOptions = {
157 sourceMaps: sourceMap,
158 // isModule: true,
159 module: moduleType
160 ? {
161 noInterop: !esModuleInterop,
162 type: moduleType,
163 strictMode,
164 // For NodeNext and Node12, emit as CJS but do not transform dynamic imports
165 ignoreDynamic: nodeModuleEmitKind === 'nodecjs',
166 }
167 : undefined,
168 swcrc: false,
169 jsc: {
170 externalHelpers: importHelpers,
171 parser: {
172 syntax: 'typescript',
173 tsx: isTsx,
174 decorators: experimentalDecorators,
175 dynamicImport: true,
176 importAssertions: true,
177 },
178 target: swcTarget,
179 transform: {
180 decoratorMetadata: emitDecoratorMetadata,
181 legacyDecorator: true,
182 react: {
183 throwIfNamespace: false,
184 development: jsxDevelopment,
185 useBuiltins: false,
186 pragma: jsxFactory,
187 pragmaFrag: jsxFragmentFactory,
188 runtime: jsxRuntime,
189 },
190 },
191 keepClassNames,
192 experimental: {
193 keepImportAssertions: true,
194 },
195 },
196 };
197 // Throw a helpful error if swc version is old, for example, if it rejects `ignoreDynamic`
198 try {
199 swcInstance.transformSync('', swcOptions);
200 }
201 catch (e) {
202 throw new Error(`${swcDepName} threw an error when attempting to validate swc compiler options.\n` +
203 'You may be using an old version of swc which does not support the options used by ts-node.\n' +
204 'Try upgrading to the latest version of swc.\n' +
205 'Error message from swc:\n' +
206 (e === null || e === void 0 ? void 0 : e.message));
207 }
208 return swcOptions;
209 }
210}
211exports.createSwcOptions = createSwcOptions;
212//# sourceMappingURL=swc.js.map
\No newline at end of file