Skip to content

Commit

Permalink
Code cleanup. Check all node_modules.
Browse files Browse the repository at this point in the history
  • Loading branch information
DylanVann committed May 7, 2018
1 parent b87520b commit 24d1b8e
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 93 deletions.
190 changes: 104 additions & 86 deletions index.js
@@ -1,88 +1,106 @@
/*
- check symlink in depencency and devDepency
- if found, generate rn-cli-config.js
- react-native start with rn-cli-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 getDependencyPath = (dependency) => fs.realpathSync(`node_modules/${dependency}`);

const getSymlinkedDependencies = () => {
const packageJson = require(`${process.cwd()}/package.json`);
const dependencies = [
...Object.keys(packageJson.dependencies),
...Object.keys(packageJson.devDependencies),
];
return dependencies.filter((dependency) =>
// 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 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);

fs.writeFileSync(
'metro.config.js',
`/* eslint-disable */
const path = require('path');
const blacklist = require('metro/src/blacklist');
module.exports = {
extraNodeModules: {
${peerDependenciesOfSymlinkedDependencies
.map((name) => `'${name}': path.resolve(__dirname, 'node_modules/${name}')`)
.join(',\n ')}
},
getBlacklistRE: () => blacklist([
${symlinkedDependenciesPaths
.map(
(path) =>
`/${path.replace(/\//g, '[/\\\\]')}[/\\\\]node_modules[/\\\\]react-native[/\\\\].*/`
)
.join(',\n ')}
]),
getProjectRoots: () => [
// Include current package as project root
path.resolve(__dirname),
// Include symlinked packages as project roots
${symlinkedDependenciesPaths.map((path) => `path.resolve('${path}')`).join(',\n ')}
],
};`
);
};

/* global process */

const symlinkedDependencies = getSymlinkedDependencies();
// eslint-disable-next-line no-console
console.log(`
Detected symlinked packaged:
${symlinkedDependencies
.map((dependency) => ` ${dependency} -> ${getDependencyPath(dependency)}`)
.join('\n')}
`);

generateMetroConfig(symlinkedDependencies, 'metro.config.js');
// eslint-disable-next-line no-console
console.log('Generated custom metro.config.js to support symlinks\n');

const command = process.argv[2];
const flags = process.argv.slice(3).join(' ');
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] }
);
`node node_modules/react-native/local-cli/cli.js ${command} --config ../../../../metro.config.js ${flags}`,
{ stdio: [0, 1, 2] },
)
19 changes: 12 additions & 7 deletions package.json
@@ -1,14 +1,19 @@
{
"name": "metro-with-symlinks",
"version": "1.0.5",
"description": "Extension to metro packager enabling the use of symlinks",
"repository": "https://github.com/MrLoh/metro-with-symlinks",
"main": "index.js",
"author": "@MrLoh",
"description": "Extension to metro packager enabling the use of symlinks.",
"license": "MIT",
"private": false,
"sripts": {
"publish": "npm version patch && npm publish"
"author": "@MrLoh",
"main": "index.js",
"repository": "https://github.com/MrLoh/metro-with-symlinks",
"scripts": {
"format": "prettier --write --list-different '*.js'",
"publish": "npm version patch && npm publish",
"test": "format"
},
"devDependencies": {
"dedent-js": "^1.0.1",
"prettier": "^1.12.1"
},
"peerDependencies": {
"react-native": "^0.55.3"
Expand Down
6 changes: 6 additions & 0 deletions prettier.config.js
@@ -0,0 +1,6 @@
module.exports = {
semi: false,
singleQuote: true,
trailingComma: 'all',
tabWidth: 4,
}
11 changes: 11 additions & 0 deletions yarn.lock
@@ -0,0 +1,11 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


dedent-js@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/dedent-js/-/dedent-js-1.0.1.tgz#bee5fb7c9e727d85dffa24590d10ec1ab1255305"

prettier@^1.12.1:
version "1.12.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325"

0 comments on commit 24d1b8e

Please sign in to comment.