-
Notifications
You must be signed in to change notification settings - Fork 112
/
Copy pathcreateBabelRc.ts
134 lines (128 loc) · 5.17 KB
/
createBabelRc.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import fs from 'fs-extra';
import path from 'path';
import { v4 as uuid, validate as uuidValidate } from 'uuid';
import semver from 'semver';
import { log, readPackageJson, writePackageJson } from 'ern-core';
import { getNodeModuleVersion } from './getNodeModuleVersion';
export async function createBabelRc({
cwd,
extraPaths = [],
}: {
cwd: string;
extraPaths?: string[];
}) {
log.debug('Creating top level composite .babelrc');
const compositePackageJson = await readPackageJson(cwd);
const compositeNodeModulesPath = path.join(cwd, 'node_modules');
const compositeReactNativeVersion = await getNodeModuleVersion({
cwd,
name: 'react-native',
});
const compositeBabelRc: { plugins: any[]; presets?: string[] } = {
plugins: [],
};
const paths = [
...Object.keys(compositePackageJson.dependencies).map((d) =>
path.join(compositeNodeModulesPath, d),
),
...extraPaths,
];
// Ugly hacky way of handling module-resolver babel plugin
// At least it has some guarantees to make it safer but its just a temporary
// solution until we figure out a more proper way of handling this plugin
log.debug(
'Taking care of potential Babel module-resolver plugins used by MiniApps',
);
let moduleResolverAliases: { [k: string]: any } = {};
for (const p of paths) {
let miniAppPackageJson;
try {
miniAppPackageJson = await readPackageJson(p);
} catch (e) {
// swallow (for test. to be fixed)
continue;
}
const miniAppName = miniAppPackageJson.name;
if (miniAppPackageJson.babel) {
if (miniAppPackageJson.babel.plugins) {
for (const babelPlugin of miniAppPackageJson.babel.plugins) {
if (Array.isArray(babelPlugin)) {
if (babelPlugin.includes('module-resolver')) {
// Add unique name to this composite top level module-resolver to avoid
// it messing with other module-resolver plugin configurations that could
// be defined in the .babelrc config of individual MiniApps
// https://babeljs.io/docs/en/options#plugin-preset-merging
// Check if lastItem of babel plugin is not uuid
const lastItem = babelPlugin.slice(-1)[0];
if (typeof lastItem !== 'string' || !uuidValidate(lastItem)) {
babelPlugin.push(uuid());
}
// Copy over module-resolver plugin & config to top level composite .babelrc
log.debug(
`Taking care of module-resolver Babel plugin for ${miniAppName} MiniApp`,
);
if (compositeBabelRc.plugins.length === 0) {
// First MiniApp to add module-resolver plugin & config
// easy enough, we just copy over the plugin & config
compositeBabelRc.plugins.push(<any>babelPlugin);
for (const x of babelPlugin) {
if (x instanceof Object && x.alias) {
moduleResolverAliases = x.alias;
Object.keys(moduleResolverAliases).map((key) => {
if (!moduleResolverAliases[key].startsWith(miniAppName))
moduleResolverAliases[
key
] = `${miniAppName}/${moduleResolverAliases[
key
].replace('./', '')}`;
});
break;
}
}
} else {
// Another MiniApp has already declared module-resolver
// plugin & config. If we have conflicts for aliases, we'll just abort
// bundling as of now to avoid generating a potentially unstable bundle
for (const item of babelPlugin) {
if (item instanceof Object && item.alias) {
for (const aliasKey of Object.keys(item.alias)) {
if (
moduleResolverAliases[aliasKey] &&
moduleResolverAliases[aliasKey] !== item.alias[aliasKey]
) {
throw new Error('Babel module-resolver alias conflict');
} else if (!moduleResolverAliases[aliasKey]) {
moduleResolverAliases[aliasKey] = item.alias[aliasKey];
}
}
}
}
}
} else {
log.warn(
`Unsupported Babel plugin type ${babelPlugin.toString()} in ${miniAppName} MiniApp`,
);
}
} else {
log.warn(
`Unsupported Babel plugin type ${babelPlugin.toString()} in ${miniAppName} MiniApp`,
);
}
}
}
log.debug(
`Removing babel object from ${miniAppName} MiniApp package.json`,
);
await writePackageJson(p, miniAppPackageJson);
}
}
if (semver.gte(compositeReactNativeVersion, '0.57.0')) {
compositeBabelRc.presets = ['module:metro-react-native-babel-preset'];
} else {
compositeBabelRc.presets = ['react-native'];
}
return fs.writeFile(
path.join(cwd, '.babelrc'),
JSON.stringify(compositeBabelRc, null, 2),
);
}