You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
284 lines
9.5 KiB
284 lines
9.5 KiB
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.createDependenciesMap = createDependenciesMap;
|
|
exports.createFileHash = createFileHash;
|
|
exports.hashForDependencyMap = hashForDependencyMap;
|
|
exports.isPkgMainExpoAppEntry = isPkgMainExpoAppEntry;
|
|
exports.shouldDeleteMainField = shouldDeleteMainField;
|
|
exports.updatePackageJSONAsync = updatePackageJSONAsync;
|
|
exports.updatePackageJSONDependencies = updatePackageJSONDependencies;
|
|
function _config() {
|
|
const data = require("@expo/config");
|
|
_config = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _chalk() {
|
|
const data = _interopRequireDefault(require("chalk"));
|
|
_chalk = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _crypto() {
|
|
const data = _interopRequireDefault(require("crypto"));
|
|
_crypto = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _fsExtra() {
|
|
const data = _interopRequireDefault(require("fs-extra"));
|
|
_fsExtra = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _path() {
|
|
const data = _interopRequireDefault(require("path"));
|
|
_path = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _log() {
|
|
const data = _interopRequireDefault(require("../../log"));
|
|
_log = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _ora() {
|
|
const data = require("../../utils/ora");
|
|
_ora = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _isModuleSymlinked() {
|
|
const data = require("../utils/isModuleSymlinked");
|
|
_isModuleSymlinked = function () {
|
|
return data;
|
|
};
|
|
return data;
|
|
}
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
async function updatePackageJSONAsync({
|
|
projectRoot,
|
|
tempDir,
|
|
pkg,
|
|
skipDependencyUpdate
|
|
}) {
|
|
// NOTE(brentvatne): Removing spaces between steps for now, add back when
|
|
// there is some additional context for steps
|
|
const updatingPackageJsonStep = (0, _ora().logNewSection)('Updating your package.json scripts, dependencies, and main file');
|
|
updatePackageJSONScripts({
|
|
pkg
|
|
});
|
|
const results = updatePackageJSONDependencies({
|
|
projectRoot,
|
|
pkg,
|
|
tempDir,
|
|
skipDependencyUpdate
|
|
});
|
|
const removedPkgMain = updatePackageJSONEntryPoint({
|
|
pkg
|
|
});
|
|
await _fsExtra().default.writeFile(_path().default.resolve(projectRoot, 'package.json'),
|
|
// Add new line to match the format of running yarn.
|
|
// This prevents the `package.json` from changing when running `prebuild --no-install` multiple times.
|
|
JSON.stringify(pkg, null, 2) + '\n');
|
|
updatingPackageJsonStep.succeed('Updated package.json and added index.js entry point for iOS and Android');
|
|
if (removedPkgMain) {
|
|
_log().default.log(`\u203A Removed ${_chalk().default.bold(`"main": "${removedPkgMain}"`)} from package.json because we recommend using index.js as main instead`);
|
|
_log().default.newLine();
|
|
}
|
|
return results;
|
|
}
|
|
|
|
/**
|
|
* Update package.json dependencies by combining the dependencies in the project we are ejecting
|
|
* with the dependencies in the template project. Does the same for devDependencies.
|
|
*
|
|
* - The template may have some dependencies beyond react/react-native/react-native-unimodules,
|
|
* for example RNGH and Reanimated. We should prefer the version that is already being used
|
|
* in the project for those, but swap the react/react-native/react-native-unimodules versions
|
|
* with the ones in the template.
|
|
* - The same applies to expo-updates -- since some native project configuration may depend on the
|
|
* version, we should always use the version of expo-updates in the template.
|
|
*/
|
|
function updatePackageJSONDependencies({
|
|
projectRoot,
|
|
tempDir,
|
|
pkg,
|
|
skipDependencyUpdate = []
|
|
}) {
|
|
if (!pkg.devDependencies) {
|
|
pkg.devDependencies = {};
|
|
}
|
|
const {
|
|
dependencies,
|
|
devDependencies
|
|
} = (0, _config().getPackageJson)(tempDir);
|
|
const defaultDependencies = createDependenciesMap(dependencies);
|
|
const defaultDevDependencies = createDependenciesMap(devDependencies);
|
|
const combinedDependencies = createDependenciesMap({
|
|
...defaultDependencies,
|
|
...pkg.dependencies
|
|
});
|
|
const requiredDependencies = ['react', 'react-native-unimodules', 'react-native', 'expo-updates'].filter(depKey => !!defaultDependencies[depKey]);
|
|
const symlinkedPackages = [];
|
|
for (const dependenciesKey of requiredDependencies) {
|
|
var _pkg$dependencies;
|
|
if ( // If the local package.json defined the dependency that we want to overwrite...
|
|
(_pkg$dependencies = pkg.dependencies) !== null && _pkg$dependencies !== void 0 && _pkg$dependencies[dependenciesKey]) {
|
|
if (
|
|
// Then ensure it isn't symlinked (i.e. the user has a custom version in their yarn workspace).
|
|
(0, _isModuleSymlinked().isModuleSymlinked)({
|
|
projectRoot,
|
|
moduleId: dependenciesKey,
|
|
isSilent: true
|
|
})) {
|
|
// If the package is in the project's package.json and it's symlinked, then skip overwriting it.
|
|
symlinkedPackages.push(dependenciesKey);
|
|
continue;
|
|
}
|
|
if (skipDependencyUpdate.includes(dependenciesKey)) {
|
|
continue;
|
|
}
|
|
}
|
|
combinedDependencies[dependenciesKey] = defaultDependencies[dependenciesKey];
|
|
}
|
|
if (symlinkedPackages.length) {
|
|
_log().default.log(`\u203A Using symlinked ${symlinkedPackages.map(pkg => _chalk().default.bold(pkg)).join(', ')} instead of recommended version(s).`);
|
|
}
|
|
const combinedDevDependencies = createDependenciesMap({
|
|
...defaultDevDependencies,
|
|
...pkg.devDependencies
|
|
});
|
|
|
|
// Only change the dependencies if the normalized hash changes, this helps to reduce meaningless changes.
|
|
const hasNewDependencies = hashForDependencyMap(pkg.dependencies) !== hashForDependencyMap(combinedDependencies);
|
|
const hasNewDevDependencies = hashForDependencyMap(pkg.devDependencies) !== hashForDependencyMap(combinedDevDependencies);
|
|
// Save the dependencies
|
|
if (hasNewDependencies) {
|
|
// Use Object.assign to preserve the original order of dependencies, this makes it easier to see what changed in the git diff.
|
|
pkg.dependencies = Object.assign(pkg.dependencies, combinedDependencies);
|
|
}
|
|
if (hasNewDevDependencies) {
|
|
// Same as with dependencies
|
|
pkg.devDependencies = Object.assign(pkg.devDependencies, combinedDevDependencies);
|
|
}
|
|
return {
|
|
hasNewDependencies,
|
|
hasNewDevDependencies
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create an object of type DependenciesMap a dependencies object or throw if not valid.
|
|
*
|
|
* @param dependencies - ideally an object of type {[key]: string} - if not then this will error.
|
|
*/
|
|
function createDependenciesMap(dependencies) {
|
|
if (typeof dependencies !== 'object') {
|
|
throw new Error(`Dependency map is invalid, expected object but got ${typeof dependencies}`);
|
|
} else if (!dependencies) {
|
|
return {};
|
|
}
|
|
const outputMap = {};
|
|
for (const key of Object.keys(dependencies)) {
|
|
const value = dependencies[key];
|
|
if (typeof value === 'string') {
|
|
outputMap[key] = value;
|
|
} else {
|
|
throw new Error(`Dependency for key \`${key}\` should be a \`string\`, instead got: \`{ ${key}: ${JSON.stringify(value)} }\``);
|
|
}
|
|
}
|
|
return outputMap;
|
|
}
|
|
|
|
/**
|
|
* Update package.json scripts - `npm start` should default to `react-native
|
|
* start` rather than `expo start` after ejecting, for example.
|
|
*/
|
|
function updatePackageJSONScripts({
|
|
pkg
|
|
}) {
|
|
var _pkg$scripts$start, _pkg$scripts$android, _pkg$scripts$ios;
|
|
if (!pkg.scripts) {
|
|
pkg.scripts = {};
|
|
}
|
|
if (!((_pkg$scripts$start = pkg.scripts.start) !== null && _pkg$scripts$start !== void 0 && _pkg$scripts$start.includes('--dev-client'))) {
|
|
pkg.scripts.start = 'expo start --dev-client';
|
|
}
|
|
if (!((_pkg$scripts$android = pkg.scripts.android) !== null && _pkg$scripts$android !== void 0 && _pkg$scripts$android.includes('run'))) {
|
|
pkg.scripts.android = 'expo run:android';
|
|
}
|
|
if (!((_pkg$scripts$ios = pkg.scripts.ios) !== null && _pkg$scripts$ios !== void 0 && _pkg$scripts$ios.includes('run'))) {
|
|
pkg.scripts.ios = 'expo run:ios';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add new app entry points
|
|
*/
|
|
function updatePackageJSONEntryPoint({
|
|
pkg
|
|
}) {
|
|
let removedPkgMain = false;
|
|
// Check that the pkg.main doesn't match:
|
|
// - ./node_modules/expo/AppEntry
|
|
// - ./node_modules/expo/AppEntry.js
|
|
// - node_modules/expo/AppEntry.js
|
|
// - expo/AppEntry.js
|
|
// - expo/AppEntry
|
|
if (shouldDeleteMainField(pkg.main)) {
|
|
// Save the custom
|
|
removedPkgMain = pkg.main;
|
|
delete pkg.main;
|
|
}
|
|
return removedPkgMain;
|
|
}
|
|
|
|
/**
|
|
* Returns true if the input string matches the default expo main field.
|
|
*
|
|
* - ./node_modules/expo/AppEntry
|
|
* - ./node_modules/expo/AppEntry.js
|
|
* - node_modules/expo/AppEntry.js
|
|
* - expo/AppEntry.js
|
|
* - expo/AppEntry
|
|
*
|
|
* @param input package.json main field
|
|
*/
|
|
function isPkgMainExpoAppEntry(input) {
|
|
const main = input || '';
|
|
if (main.startsWith('./')) {
|
|
return main.includes('node_modules/expo/AppEntry');
|
|
}
|
|
return main.includes('expo/AppEntry');
|
|
}
|
|
function normalizeDependencyMap(deps) {
|
|
return Object.keys(deps).map(dependency => `${dependency}@${deps[dependency]}`).sort();
|
|
}
|
|
function hashForDependencyMap(deps = {}) {
|
|
const depsList = normalizeDependencyMap(deps);
|
|
const depsString = depsList.join('\n');
|
|
return createFileHash(depsString);
|
|
}
|
|
function createFileHash(contents) {
|
|
// this doesn't need to be secure, the shorter the better.
|
|
return _crypto().default.createHash('sha1').update(contents).digest('hex');
|
|
}
|
|
function shouldDeleteMainField(main) {
|
|
if (!main || !isPkgMainExpoAppEntry(main)) {
|
|
return false;
|
|
}
|
|
return !(main !== null && main !== void 0 && main.startsWith('index.'));
|
|
}
|
|
//# sourceMappingURL=updatePackageJson.js.map
|