react-native-config/scripts/examples_postinstall.js
2020-03-18 20:43:29 -03:00

118 lines
3.8 KiB
JavaScript

#!/usr/bin/env node
/*
* Using libraries within examples and linking them within packages.json like:
* "react-native-library-name": "file:../"
* will cause problems with the metro bundler if the example will run via
* `react-native run-[ios|android]`. This will result in an error as the metro
* bundler will find multiple versions for the same module while resolving it.
* The reason for that is that if the library is installed it also copies in the
* example folder itself as well as the node_modules folder of the library
* although their are defined in .npmignore and should be ignored in theory.
*
* This postinstall script removes the node_modules folder as well as all
* entries from the libraries .npmignore file within the examples node_modules
* folder after the library was installed. This should resolve the metro
* bundler issue mentioned above.
*
* It is expected this scripts lives in the libraries root folder within a
* scripts folder. As first parameter the relative path to the libraries
* folder within the example's node_modules folder may be provided.
* This script will determine the path from this project's package.json file
* if no such relative path is provided.
* An example's package.json entry could look like:
* "postinstall": "node ../scripts/examples_postinstall.js node_modules/react-native-library-name/"
*/
'use strict';
const fs = require('fs');
const path = require('path');
/// Delete all files and directories for the given path
const removeFileDirectoryRecursively = fileDirPath => {
// Remove file
if (!fs.lstatSync(fileDirPath).isDirectory()) {
fs.unlinkSync(fileDirPath);
return;
}
// Go down the directory an remove each file / directory recursively
fs.readdirSync(fileDirPath).forEach(entry => {
const entryPath = path.join(fileDirPath, entry);
removeFileDirectoryRecursively(entryPath);
});
fs.rmdirSync(fileDirPath);
};
const removeFileDir = fileDirPath => {
try {
removeFileDirectoryRecursively(fileDirPath);
console.log(`Deleted: ${fileDirPath}`);
} catch (err) {
console.log(`Error deleting ${fileDirPath}: ${err.message}`);
}
};
/// Remove example/node_modules/react-native-library-name/node_modules directory
const removeLibraryNodeModulesPath = nodeModulesPath => {
if (!fs.existsSync(nodeModulesPath)) {
console.log(
`No node_modules found at ${nodeModulesPath}. Skipping delete.`,
);
return;
}
removeFileDir(nodeModulesPath);
};
/// Remove all entries from the .npmignore within example/node_modules/react-native-library-name/
const removeLibraryNpmIgnorePaths = (npmIgnorePath, libraryNodeModulesPath) => {
if (!fs.existsSync(npmIgnorePath)) {
console.log(
`No .npmignore found at ${npmIgnorePath}. Skipping deleting content.`,
);
return;
}
fs.readFileSync(npmIgnorePath, 'utf8')
.split(/\r?\n/)
.forEach(entry => {
if (entry.length === 0) {
return;
}
const npmIgnoreLibraryNodeModulesEntryPath = path.resolve(
libraryNodeModulesPath,
entry,
);
if (!fs.existsSync(npmIgnoreLibraryNodeModulesEntryPath)) {
return;
}
removeFileDir(npmIgnoreLibraryNodeModulesEntryPath);
});
};
// Main start sweeping process
(() => {
// Read out dir of example project
const cwd = process.cwd();
console.log(`Starting postinstall cleanup for ${cwd}`);
// Resolve the React Native library's path within the example's node_modules directory
const libraryNodeModulesPath =
process.argv.length > 2
? path.resolve(cwd, process.argv[2])
: path.resolve(cwd, 'node_modules', require('../package.json').name);
removeLibraryNodeModulesPath(
path.resolve(libraryNodeModulesPath, 'node_modules'),
);
removeLibraryNpmIgnorePaths(
path.resolve(__dirname, '../.npmignore'),
libraryNodeModulesPath,
);
})();