Re-introduce lodash into src/package-install.js (#10315)

* test: add failing test for if package.json is non-existant, fix tests' beforeEach method

* Revert "fix: #10289, remove lodash dependency in src/cli/package-install.js"

This reverts commit 81fa2e22bc.

* fix: regression caused by 94b79ce402

`./nodebb setup` was no longer able to be called without arguments or env vars

* fix: .updatePackageFile() throwing if no package.json

* fix: removing unneeded code in src/cli/index.js that seemed to be used to handle cases where package.json was missing (initial install)

... However, as .updatePackageFile() now handled cases where there is no package.json, it should be ok to remove this code

* fix: handle missing package.json or node_modules/
isekai-main
Julian Lam 3 years ago committed by GitHub
parent 6e156daaf6
commit 17836f2a3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -10,31 +10,18 @@ require('../../require-main');
const packageInstall = require('./package-install'); const packageInstall = require('./package-install');
const { paths } = require('../constants'); const { paths } = require('../constants');
// check to make sure dependencies are installed
try { try {
fs.accessSync(paths.currentPackage, fs.constants.R_OK); fs.accessSync(paths.currentPackage, fs.constants.R_OK); // throw on missing package.json
} catch (e) { try { // handle missing node_modules/ directory
if (e.code === 'ENOENT') { fs.accessSync(paths.nodeModules, fs.constants.R_OK);
console.warn('package.json not found.');
console.log('Populating package.json...');
packageInstall.updatePackageFile();
packageInstall.preserveExtraneousPlugins();
try {
fs.accessSync(path.join(paths.nodeModules, 'chalk/package.json'), fs.constants.R_OK);
const chalk = require('chalk');
console.log(chalk.green('OK'));
} catch (e) { } catch (e) {
console.log('OK'); if (e.code === 'ENOENT') {
} // run package installation just to sync up node_modules/ with existing package.json
packageInstall.installAll();
} else { } else {
throw e; throw e;
} }
} }
try {
fs.accessSync(path.join(paths.nodeModules, 'semver/package.json'), fs.constants.R_OK); fs.accessSync(path.join(paths.nodeModules, 'semver/package.json'), fs.constants.R_OK);
const semver = require('semver'); const semver = require('semver');
@ -53,12 +40,14 @@ try {
checkVersion('async'); checkVersion('async');
checkVersion('commander'); checkVersion('commander');
checkVersion('chalk'); checkVersion('chalk');
checkVersion('lodash');
} catch (e) { } catch (e) {
if (['ENOENT', 'DEP_WRONG_VERSION', 'MODULE_NOT_FOUND'].includes(e.code)) { if (['ENOENT', 'DEP_WRONG_VERSION', 'MODULE_NOT_FOUND'].includes(e.code)) {
console.warn('Dependencies outdated or not yet installed.'); console.warn('Dependencies outdated or not yet installed.');
console.log('Installing them now...\n'); console.log('Installing them now...\n');
packageInstall.updatePackageFile(); packageInstall.updatePackageFile();
packageInstall.preserveExtraneousPlugins();
packageInstall.installAll(); packageInstall.installAll();
const chalk = require('chalk'); const chalk = require('chalk');

@ -1,6 +1,7 @@
'use strict'; 'use strict';
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const cproc = require('child_process'); const cproc = require('child_process');
@ -17,34 +18,22 @@ function sortDependencies(dependencies) {
}, {}); }, {});
} }
function merge(to, from) {
// Poor man's version of _.merge()
if (Object.values(from).every(val => typeof val !== 'object')) {
return Object.assign(to, from);
}
Object.keys(from).forEach((key) => {
if (Object.getPrototypeOf(from[key]) === Object.prototype) {
to[key] = merge(to[key], from[key]);
} else {
to[key] = from[key];
}
});
return to;
}
pkgInstall.updatePackageFile = () => { pkgInstall.updatePackageFile = () => {
let oldPackageContents = {}; let oldPackageContents;
try { try {
oldPackageContents = JSON.parse(fs.readFileSync(paths.currentPackage, 'utf8')); oldPackageContents = JSON.parse(fs.readFileSync(paths.currentPackage, 'utf8'));
} catch (e) { } catch (e) {
if (e.code !== 'ENOENT') { if (e.code !== 'ENOENT') {
throw e; throw e;
} else {
// No local package.json, copy from install/package.json
fs.copyFileSync(paths.installPackage, paths.currentPackage);
return;
} }
} }
const _ = require('lodash');
const defaultPackageContents = JSON.parse(fs.readFileSync(paths.installPackage, 'utf8')); const defaultPackageContents = JSON.parse(fs.readFileSync(paths.installPackage, 'utf8'));
let dependencies = {}; let dependencies = {};
@ -59,7 +48,7 @@ pkgInstall.updatePackageFile = () => {
// Sort dependencies alphabetically // Sort dependencies alphabetically
dependencies = sortDependencies({ ...dependencies, ...defaultPackageContents.dependencies }); dependencies = sortDependencies({ ...dependencies, ...defaultPackageContents.dependencies });
const packageContents = { ...merge(oldPackageContents, defaultPackageContents), dependencies, devDependencies }; const packageContents = { ..._.merge(oldPackageContents, defaultPackageContents), dependencies, devDependencies };
fs.writeFileSync(paths.currentPackage, JSON.stringify(packageContents, null, 4)); fs.writeFileSync(paths.currentPackage, JSON.stringify(packageContents, null, 4));
}; };

@ -23,12 +23,11 @@ describe('Package install lib', () => {
// Move `install/package.json` and `package.json` out of the way for now // Move `install/package.json` and `package.json` out of the way for now
await fs.copyFile(sourcePackagePath, path.resolve(__dirname, '../install/package.json.bak')); // safekeeping await fs.copyFile(sourcePackagePath, path.resolve(__dirname, '../install/package.json.bak')); // safekeeping
await fs.copyFile(packageFilePath, path.resolve(__dirname, '../package.json.bak')); // safekeeping await fs.copyFile(packageFilePath, path.resolve(__dirname, '../package.json.bak')); // safekeeping
await fs.copyFile(sourcePackagePath, packageFilePath); // match files for testing
}); });
beforeEach(async () => { beforeEach(async () => {
await fs.copyFile(path.resolve(__dirname, '../install/package.json.bak'), sourcePackagePath); await fs.copyFile(path.resolve(__dirname, '../install/package.json.bak'), sourcePackagePath);
await fs.copyFile(path.resolve(__dirname, '../package.json.bak'), packageFilePath); await fs.copyFile(sourcePackagePath, packageFilePath); // match files for testing
source = JSON.parse(await fs.readFile(sourcePackagePath)); source = JSON.parse(await fs.readFile(sourcePackagePath));
current = JSON.parse(await fs.readFile(packageFilePath)); current = JSON.parse(await fs.readFile(packageFilePath));
}); });
@ -95,6 +94,14 @@ describe('Package install lib', () => {
assert.strictEqual(updated.devDependencies.hasOwnProperty('expect'), false); assert.strictEqual(updated.devDependencies.hasOwnProperty('expect'), false);
}); });
it('should handle if there is no package.json', async () => {
await fs.unlink(packageFilePath);
pkgInstall.updatePackageFile();
const updated = JSON.parse(await fs.readFile(packageFilePath, 'utf8'));
assert.deepStrictEqual(updated, source);
});
after(async () => { after(async () => {
// Clean up // Clean up
await fs.rename(path.resolve(__dirname, '../install/package.json.bak'), sourcePackagePath); await fs.rename(path.resolve(__dirname, '../install/package.json.bak'), sourcePackagePath);

Loading…
Cancel
Save