UNPKG

3.19 kBJavaScriptView Raw
1/*
2 * Copyright 2021 The Backstage Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17const { createHash } = require('crypto');
18const { transform } = require('sucrase');
19const sucrasePkg = require('sucrase/package.json');
20const sucrasePluginPkg = require('@sucrase/jest-plugin/package.json');
21
22const ESM_REGEX = /\b(?:import|export)\b/;
23
24function createTransformer(config) {
25 const process = (source, filePath) => {
26 let transforms;
27
28 if (filePath.endsWith('.esm.js')) {
29 transforms = ['imports'];
30 } else if (filePath.endsWith('.js')) {
31 // This is a very rough filter to avoid transforming things that we quickly
32 // can be sure are definitely not ESM modules.
33 if (ESM_REGEX.test(source)) {
34 transforms = ['imports', 'jsx']; // JSX within .js is currently allowed
35 }
36 } else if (filePath.endsWith('.jsx')) {
37 transforms = ['jsx', 'imports'];
38 } else if (filePath.endsWith('.ts')) {
39 transforms = ['typescript', 'imports'];
40 } else if (filePath.endsWith('.tsx')) {
41 transforms = ['typescript', 'jsx', 'imports'];
42 }
43
44 // Only apply the jest transform to the test files themselves
45 if (transforms && filePath.includes('.test.')) {
46 transforms.push('jest');
47 }
48
49 if (transforms) {
50 const { code, sourceMap: map } = transform(source, {
51 transforms,
52 filePath,
53 disableESTransforms: true,
54 sourceMapOptions: {
55 compiledFilename: filePath,
56 },
57 });
58 if (config.enableSourceMaps) {
59 const b64 = Buffer.from(JSON.stringify(map), 'utf8').toString('base64');
60 const suffix = `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${b64}`;
61 // Include both inline and object source maps, as inline source maps are
62 // needed for support of some editor integrations.
63 return { code: `${code}\n${suffix}`, map };
64 }
65 // We only return the `map` result if source maps are enabled, as they
66 // have a negative impact on the coverage accuracy.
67 return code;
68 }
69
70 return source;
71 };
72
73 // TODO: contribute something like this to @sucrase/jest-plugin
74 const getCacheKey = sourceText => {
75 return createHash('md5')
76 .update(sourceText)
77 .update(Buffer.alloc(1))
78 .update(sucrasePkg.version)
79 .update(Buffer.alloc(1))
80 .update(sucrasePluginPkg.version)
81 .update(Buffer.alloc(1))
82 .update(JSON.stringify(config))
83 .update(Buffer.alloc(1))
84 .update('1') // increment whenever the transform logic in this file changes
85 .digest('hex');
86 };
87
88 return { process, getCacheKey };
89}
90
91module.exports = { createTransformer };