mirror of
https://github.com/appium/appium.git
synced 2026-02-24 12:20:05 -06:00
chore: unify package root detection & package.json reading
This replaces all of the ad-hoc ways to find the closest `package.json` file (usually for reading the `version` field) with utility functions in the `fs` module of `@appium/support`. - add `fs.findRoot(<dir>)` - Finds the closest parent directory from `dir` containing a `package.json` - add `fs.readPackageJsonFrom(<dir>)` - Like above, except reads and returns the parsed contents of `package.json` - Remove `find-root` dep from `appium` and add it to `@appium/support` instead - Leverage these functions where needed - Remove unnecessary `pkgRoot` export in `@appium/doctor` - `fs-specs.js`: fix some tests which make assumptions about CWD; remove a low-value test
This commit is contained in:
@@ -4,6 +4,7 @@ import { ArgumentParser } from 'argparse';
|
||||
import { sharedArgs, serverArgs, extensionArgs } from './args';
|
||||
import { DRIVER_TYPE, PLUGIN_TYPE } from '../extension-config';
|
||||
import { rootDir } from '../utils';
|
||||
import { fs } from '@appium/support';
|
||||
|
||||
|
||||
function makeDebugParser (parser) {
|
||||
@@ -23,7 +24,7 @@ function getParser (debug = false) {
|
||||
}
|
||||
parser.add_argument('-v', '--version', {
|
||||
action: 'version',
|
||||
version: require(path.resolve(rootDir, 'package.json')).version
|
||||
version: fs.readPackageJsonFrom(rootDir).version
|
||||
});
|
||||
const subParsers = parser.add_subparsers({dest: 'subcommand'});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import _ from 'lodash';
|
||||
import { mkdirp, system } from '@appium/support';
|
||||
import { mkdirp, system, fs } from '@appium/support';
|
||||
import axios from 'axios';
|
||||
import { exec } from 'teen_process';
|
||||
import { rootDir } from './utils';
|
||||
@@ -10,12 +10,7 @@ import {
|
||||
} from './cli/argparse-actions';
|
||||
import findUp from 'find-up';
|
||||
|
||||
let npmPackage;
|
||||
try {
|
||||
npmPackage = require('../package.json');
|
||||
} catch {
|
||||
npmPackage = require('../../package.json');
|
||||
}
|
||||
const npmPackage = fs.readPackageJsonFrom(__dirname);
|
||||
|
||||
const APPIUM_VER = npmPackage.version;
|
||||
const MIN_NODE_VERSION = npmPackage.engines.node;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import _ from 'lodash';
|
||||
import logger from './logger';
|
||||
import { processCapabilities, PROTOCOLS } from '@appium/base-driver';
|
||||
import findRoot from 'find-root';
|
||||
import { parseJsonStringOrFile } from './cli/parser-helpers';
|
||||
import { fs } from '@appium/support';
|
||||
|
||||
const W3C_APPIUM_PREFIX = 'appium';
|
||||
|
||||
@@ -229,7 +229,7 @@ function pullSettings (caps) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const rootDir = findRoot(__dirname);
|
||||
const rootDir = fs.findRoot(__dirname);
|
||||
|
||||
export {
|
||||
inspectObject, parseCapsForInnerDriver, insertAppiumPrefixes, rootDir,
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
"axios": "^0.21.0",
|
||||
"bluebird": "3.x",
|
||||
"continuation-local-storage": "3.x",
|
||||
"find-root": "^1.1.0",
|
||||
"find-up": "^5.0.0",
|
||||
"lodash": "^4.17.11",
|
||||
"longjohn": "^0.2.12",
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
import 'colors';
|
||||
import _ from 'lodash';
|
||||
import log from './logger';
|
||||
import { fs } from '@appium/support';
|
||||
|
||||
// for test compat
|
||||
let version;
|
||||
try {
|
||||
version = require('../../package.json').version;
|
||||
} catch {
|
||||
version = require('../package.json').version;
|
||||
}
|
||||
const {version} = fs.readPackageJsonFrom(__dirname);
|
||||
|
||||
class FixSkippedError extends Error {
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import B from 'bluebird';
|
||||
import path from 'path';
|
||||
import _inquirer from 'inquirer';
|
||||
import log from '../lib/logger';
|
||||
import authorize from 'authorize-ios';
|
||||
@@ -10,14 +9,6 @@ import { isFunction } from 'lodash';
|
||||
// rename to make more sense
|
||||
const authorizeIos = authorize;
|
||||
|
||||
// test support
|
||||
let pkgRoot;
|
||||
try {
|
||||
pkgRoot = path.dirname(require.resolve('../package.json'));
|
||||
} catch {
|
||||
pkgRoot = path.dirname(require.resolve('../../package.json'));
|
||||
}
|
||||
|
||||
function ok (message) {
|
||||
return {ok: true, optional: false, message};
|
||||
}
|
||||
@@ -121,5 +112,5 @@ async function getNpmPackageInfo (packageName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
export { pkgRoot, ok, nok, okOptional, nokOptional, inquirer, configureBinaryLog,
|
||||
export { ok, nok, okOptional, nokOptional, inquirer, configureBinaryLog,
|
||||
authorizeIos, resolveExecutablePath, getNpmPackageInfo, resetLog };
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// transpile:mocha
|
||||
|
||||
import { pkgRoot, configureBinaryLog, resetLog } from '../lib/utils';
|
||||
import { configureBinaryLog, resetLog } from '../lib/utils';
|
||||
import { fs } from '@appium/support';
|
||||
import chai from 'chai';
|
||||
import path from 'path';
|
||||
@@ -11,14 +11,14 @@ chai.should();
|
||||
describe('utils', function () {
|
||||
|
||||
it('fs.readFile', async function () {
|
||||
(await fs.readFile(path.resolve(pkgRoot, 'test', 'fixtures',
|
||||
(await fs.readFile(path.resolve(__dirname, 'fixtures',
|
||||
'wow.txt'), 'utf8')).should.include('WOW');
|
||||
});
|
||||
|
||||
it('fs.exists', async function () {
|
||||
(await fs.exists(path.resolve(pkgRoot, 'test', 'fixtures',
|
||||
(await fs.exists(path.resolve(__dirname, 'fixtures',
|
||||
'wow.txt'))).should.be.ok;
|
||||
(await fs.exists(path.resolve(pkgRoot, 'test', 'fixtures',
|
||||
(await fs.exists(path.resolve(__dirname, 'fixtures',
|
||||
'notwow.txt'))).should.not.be.ok;
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// jshint ignore: start
|
||||
import _ from 'lodash';
|
||||
import path from 'path';
|
||||
import _fs from 'fs';
|
||||
import rimraf from 'rimraf';
|
||||
import ncp from 'ncp';
|
||||
@@ -9,12 +11,14 @@ import glob from 'glob';
|
||||
import crypto from 'crypto';
|
||||
import klaw from 'klaw';
|
||||
import sanitize from 'sanitize-filename';
|
||||
import findRoot from 'find-root';
|
||||
import { pluralize } from './util';
|
||||
import log from './logger';
|
||||
import Timer from './timing';
|
||||
|
||||
const mkdirAsync = B.promisify(_fs.mkdir);
|
||||
const ncpAsync = B.promisify(ncp);
|
||||
const findRootCached = _.memoize(findRoot);
|
||||
|
||||
const fs = {
|
||||
async hasAccess (path) {
|
||||
@@ -141,6 +145,39 @@ const fs = {
|
||||
walker.destroy();
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Reads the closest `package.json` file from absolute path `dir`.
|
||||
* @param {string} dir - Directory to search from
|
||||
* @throws {TypeError} If `dir` is not a nonempty string or relative path
|
||||
* @throws {Error} If there were problems finding or reading a `package.json` file
|
||||
* @returns {object} A parsed `package.json`
|
||||
*/
|
||||
readPackageJsonFrom (dir) {
|
||||
const root = fs.findRoot(dir);
|
||||
try {
|
||||
return JSON.parse(_fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
||||
} catch (err) {
|
||||
err.message = `Failed to read a \`package.json\` from dir \`${dir}\`:\n\n${err.message}`;
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Finds the project root directory from `dir`.
|
||||
* @param {string} dir - Directory to search from
|
||||
* @throws {TypeError} If `dir` is not a nonempty string or relative path
|
||||
* @throws {Error} If there were problems finding the project root
|
||||
* @returns {string} The closeset parent dir containing `package.json`
|
||||
*/
|
||||
findRoot (dir) {
|
||||
if (!dir || !path.isAbsolute(dir)) {
|
||||
throw new TypeError('`findRoot()` must be provided a non-empty, absolute path');
|
||||
}
|
||||
const result = findRootCached(dir);
|
||||
if (!result) {
|
||||
throw new Error(`\`findRoot()\` could not find \`package.json\` from ${dir}`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"bluebird": "^3.5.1",
|
||||
"bplist-creator": "^0",
|
||||
"bplist-parser": "^0.x",
|
||||
"find-root": "^1.1.0",
|
||||
"form-data": "^4.0.0",
|
||||
"get-stream": "^6.0.1",
|
||||
"glob": "^7.1.7",
|
||||
|
||||
@@ -4,7 +4,9 @@ import path from 'path';
|
||||
import { exec } from 'teen_process';
|
||||
import B from 'bluebird';
|
||||
import _ from 'lodash';
|
||||
import chaiAsPromised from 'chai-as-promised';
|
||||
|
||||
chai.use(chaiAsPromised);
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
@@ -14,6 +16,7 @@ describe('fs', function () {
|
||||
this.timeout(MOCHA_TIMEOUT);
|
||||
|
||||
const existingPath = path.resolve(__dirname, 'fs-specs.js');
|
||||
|
||||
it('should have expected methods', function () {
|
||||
should.exist(fs.open);
|
||||
should.exist(fs.close);
|
||||
@@ -149,8 +152,8 @@ describe('fs', function () {
|
||||
});
|
||||
});
|
||||
it('glob', async function () {
|
||||
let glob = 'test/*-specs.js';
|
||||
let tests = await fs.glob(glob);
|
||||
let glob = '*-specs.js';
|
||||
let tests = await fs.glob(glob, {cwd: __dirname});
|
||||
tests.should.be.an('array');
|
||||
tests.should.have.length.above(2);
|
||||
});
|
||||
@@ -195,4 +198,72 @@ describe('fs', function () {
|
||||
_.isNil(filePath).should.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('findRoot()', function () {
|
||||
describe('when not provided an argument', function () {
|
||||
it('should throw', function () {
|
||||
(() => fs.findRoot()).should.throw(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when provided a relative path', function () {
|
||||
it('should throw', function () {
|
||||
(() => fs.findRoot('./foo')).should.throw(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when provided an empty string', function () {
|
||||
it('should throw', function () {
|
||||
(() => fs.findRoot('')).should.throw(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when provided an absolute path', function () {
|
||||
describe('when the path has a parent `package.json`', function () {
|
||||
it('should locate the dir with the closest `package.json`', function () {
|
||||
fs.findRoot(__dirname).should.be.a('string');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the path does not have a parent `package.json`', function () {
|
||||
it('should throw', function () {
|
||||
(() => fs.findRoot('/')).should.throw(Error);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('readPackageJsonFrom()', function () {
|
||||
describe('when not provided an argument', function () {
|
||||
it('should throw', function () {
|
||||
(() => fs.readPackageJsonFrom()).should.throw(TypeError, /non-empty, absolute path/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when provided a relative path', function () {
|
||||
it('should throw', function () {
|
||||
(() => fs.readPackageJsonFrom('./foo')).should.throw(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when provided an empty string', function () {
|
||||
it('should throw', function () {
|
||||
(() => fs.readPackageJsonFrom('')).should.throw(TypeError);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when provided an absolute path', function () {
|
||||
describe('when the path does not have a parent `package.json`', function () {
|
||||
it('should throw', function () {
|
||||
(() => fs.readPackageJsonFrom('/')).should.throw(Error);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the path has a parent `package.json`', function () {
|
||||
it('should read the `package.json` found in the root dir', function () {
|
||||
fs.readPackageJsonFrom(__dirname).should.be.an('object');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user