/
index.js
106 lines (90 loc) · 3.22 KB
/
index.js
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
// Check for symlinks in node_modules
// If found generate and use metro config.
//
// Sources:
// - https://github.com/facebook/metro/issues/1#issuecomment-346502388
// - https://github.com/facebook/metro/issues/1#issuecomment-334546083
const fs = require('fs')
const exec = require('child_process').execSync
const dedent = require('dedent-js')
const getDependencyPath = dependency =>
fs.realpathSync(`node_modules/${dependency}`)
const isSymlink = dependency =>
fs.lstatSync(`node_modules/${dependency}`).isSymbolicLink()
const getSymlinkedDependencies = () =>
fs.readdirSync(`${process.cwd()}/node_modules`).filter(isSymlink)
const mapModule = name =>
` '${name}': path.resolve(__dirname, 'node_modules/${name}')`
const mapPath = path =>
` /${path.replace(
/\//g,
'[/\\\\]',
)}[/\\\\]node_modules[/\\\\]react-native[/\\\\].*/`
const generateMetroConfig = symlinkedDependencies => {
const symlinkedDependenciesPaths = symlinkedDependencies.map(
getDependencyPath,
)
const peerDependenciesOfSymlinkedDependencies = symlinkedDependenciesPaths
.map(path => require(`${path}/package.json`).peerDependencies)
.map(
peerDependencies =>
peerDependencies ? Object.keys(peerDependencies) : [],
)
// flatten the array of arrays
.reduce(
(flatDependencies, dependencies) => [
...flatDependencies,
...dependencies,
],
[],
)
// filter to make array elements unique
.filter(
(dependency, i, dependencies) =>
dependencies.indexOf(dependency) === i,
)
const extraNodeModules = peerDependenciesOfSymlinkedDependencies
.map(mapModule)
.join(',\n')
const getBlacklistRE = symlinkedDependenciesPaths.map(mapPath).join(',\n')
const getProjectRoots = symlinkedDependenciesPaths
.map(path => ` path.resolve('${path}')`)
.join(',\n')
return dedent`
const path = require('path');
const blacklist = require('metro/src/blacklist');
module.exports = {
extraNodeModules: {
${extraNodeModules}
},
getBlacklistRE: () => blacklist([
${getBlacklistRE}
]),
getProjectRoots: () => [
// Include current package as project root
path.resolve(__dirname),
// Include symlinked packages as project roots
${getProjectRoots}
],
};
`
}
const symlinkedDependencies = getSymlinkedDependencies()
const packagesString = symlinkedDependencies
.map(
dependency => ` - ${dependency} -> ${getDependencyPath(dependency)}`,
)
.join('\n')
const config = generateMetroConfig(symlinkedDependencies)
fs.writeFileSync('metro.config.js', config)
console.log(dedent`
using metro-with-symlinks - https://github.com/MrLoh/metro-with-symlinks
Detected symlinked packages:
${packagesString}
`)
const command = process.argv[2]
const flags = process.argv.slice(3).join(' ')
exec(
`node node_modules/react-native/local-cli/cli.js ${command} --config ../../../../metro.config.js ${flags}`,
{ stdio: [0, 1, 2] },
)