/
shaker.ts
94 lines (78 loc) · 2.3 KB
/
shaker.ts
1
2
3
4
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
import type { TransformOptions, PluginItem } from '@babel/core';
import type { Evaluator } from '@wyw-in-js/shared';
import { hasShakerMetadata } from './utils/ShakerMetadata';
import { getPluginKey } from './utils/getPluginKey';
const hasKeyInList = (plugin: PluginItem, list: string[]): boolean => {
const pluginKey = getPluginKey(plugin);
return pluginKey ? list.some((i) => pluginKey.includes(i)) : false;
};
const safeResolve = (id: string, paths: (string | null)[]): string | null => {
try {
return require.resolve(id, {
paths: paths.filter((i) => i !== null) as string[],
});
} catch {
return null;
}
};
export const shaker: Evaluator = (
evalConfig,
ast,
code,
{ highPriorityPlugins, ...config },
babel
) => {
const preShakePlugins =
evalConfig.plugins?.filter((i) => hasKeyInList(i, highPriorityPlugins)) ??
[];
const plugins = [
...preShakePlugins,
[require.resolve('./plugins/shaker'), config],
...(evalConfig.plugins ?? []).filter(
(i) => !hasKeyInList(i, highPriorityPlugins)
),
];
const hasCommonjsPlugin = evalConfig.plugins?.some(
(i) => getPluginKey(i) === 'transform-modules-commonjs'
);
if (!hasCommonjsPlugin) {
plugins.push(require.resolve('@babel/plugin-transform-modules-commonjs'));
}
if (
evalConfig.filename?.endsWith('.ts') ||
evalConfig.filename?.endsWith('.tsx')
) {
const hasTypescriptPlugin = evalConfig.plugins?.some(
(i) => getPluginKey(i) === 'transform-typescript'
);
if (!hasTypescriptPlugin) {
const preset = safeResolve('@babel/preset-typescript', [
evalConfig.filename,
]);
const plugin = safeResolve('@babel/plugin-transform-typescript', [
evalConfig.filename,
preset,
]);
if (plugin) {
plugins.push(plugin);
}
}
}
const transformOptions: TransformOptions = {
...evalConfig,
caller: {
name: 'wyw-in-js',
},
plugins,
};
const transformed = babel.transformFromAstSync(ast, code, transformOptions);
if (!transformed || !hasShakerMetadata(transformed.metadata)) {
throw new Error(`${evalConfig.filename} has no shaker metadata`);
}
return [
transformed.ast!,
transformed.code ?? '',
transformed.metadata.wywEvaluator.imports,
];
};
export default shaker;