Compare commits

..

1 Commits

Author SHA1 Message Date
609a36c128 docs: add usage info to readme 2019-04-04 17:08:24 -07:00
7 changed files with 18 additions and 78 deletions

View File

@@ -6,17 +6,6 @@ Node package compare and change runner.
[![npm](https://img.shields.io/npm/v/pkgcomp.svg)](https://www.npmjs.com/package/pkgcomp) [![npm](https://img.shields.io/npm/v/pkgcomp.svg)](https://www.npmjs.com/package/pkgcomp)
[![Project Status](https://img.shields.io/badge/status-experimental-orange.svg)](https://nodejs.org/api/documentation.html#documentation_stability_index) [![Project Status](https://img.shields.io/badge/status-experimental-orange.svg)](https://nodejs.org/api/documentation.html#documentation_stability_index)
This tool will execute a command if the dependencies or lock files of your module have changed since the last time it was run. Any of the following will be considered a change:
- If the `dependencies` or `devDependencies` in `package.json` change
- If the `dependencies` or `devDependencies` in any of your workspaces change
- Uses `workspaces` property in root `package.json`, works with Yarn workspaces
- If one of the files in your `checkFiles` config's md5 hash changes
If the command exits with a non-zero exit code, `pkgcomp` will exit with the same exit code.
**NOTE:** Out of the box the script will do nothing, you have to provide a command to run, via the `cmd` config. See [Configuration](#configuration) below.
## Usage ## Usage
Simply install the package and run it from the command line in your project. You can install it globally and run it that way, but installing locally is generally better. Simply install the package and run it from the command line in your project. You can install it globally and run it that way, but installing locally is generally better.
@@ -26,7 +15,9 @@ yarn add -D pkgcomp
npx pkgcomp npx pkgcomp
``` ```
**NOTE:** Out of the box the script will do nothing, you have to provide a command to run, via the `cmd` config. See [Configuration](#configuration) below. If the `dependencies` or `devDependencies` in `package.json` change, or if one of the files in your `checkFiles` config's md5 hash changes, your command will run. If the command exits with a non-zero exit code, `pkgcomp` will exit with the same exit code.
Out of the box the script will do nothing, you have to provide a command to run, via the `cmd` config. See [Configuration](#configuration) below.
You can also set the command, and control how the script works, via the available [command line arguments](#cli-arguments) You can also set the command, and control how the script works, via the available [command line arguments](#cli-arguments)
@@ -63,7 +54,7 @@ Configuration is provided as JSON, and can be defined in any of the following (l
### Config options ### Config options
Name | Default | Description Name | Default | Description
---- | ------- | ----------- -- | -- | --
`checkFiles` | `['package-lock.json', 'yarn.lock']` | Additional files to checksum and compare, files that are not included will be skipped `checkFiles` | `['package-lock.json', 'yarn.lock']` | Additional files to checksum and compare, files that are not included will be skipped
`rootDir` | `process.cwd()` | The root path to your project `rootDir` | `process.cwd()` | The root path to your project
`dataDir` | `<Home>/.local/share` | Directory where this module's data should be written to `dataDir` | `<Home>/.local/share` | Directory where this module's data should be written to
@@ -97,7 +88,7 @@ As a property in `package.json`:
## CLI Arguments ## CLI Arguments
Argument | Default | Description Argument | Default | Description
-------- | ------- | ----------- -- | -- | --
`--verbose` | `false` | Shows more verbose output, like if the command is being skipped or a file in `checkFiles` does not exist `--verbose` | `false` | Shows more verbose output, like if the command is being skipped or a file in `checkFiles` does not exist
`--force` | `false` | Runs your command regardless of whether or not there were changes in the package `--force` | `false` | Runs your command regardless of whether or not there were changes in the package
`--cmd` | | Specify the command to run when changes are found (ex. `--cmd="yarn install"`) `--cmd` | | Specify the command to run when changes are found (ex. `--cmd="yarn install"`)

View File

@@ -9,12 +9,11 @@
"scripts": { "scripts": {
"lint": "eslint 'src/**/*.{js,mjs}'", "lint": "eslint 'src/**/*.{js,mjs}'",
"version": "npm-auto-version", "version": "npm-auto-version",
"start": "node .", "start": "node ."
"test": "npm run lint"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://git.w33ble.com/w33ble/pkgcomp.git" "url": "git+https://github.com/w33ble/pkgcomp.git"
}, },
"keywords": [ "keywords": [
"spawn", "spawn",
@@ -64,7 +63,7 @@
"trailingComma": "es5" "trailingComma": "es5"
}, },
"dependencies": { "dependencies": {
"glob-parent": "^5.0.0", "fast-deep-equal": "^2.0.1",
"joycon": "^2.2.4", "joycon": "^2.2.4",
"md5-file": "^4.0.0", "md5-file": "^4.0.0",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",

View File

@@ -36,9 +36,7 @@ function buildConfig(args) {
// parse args from CLI // parse args from CLI
const args = parseArgs(); const args = parseArgs();
const { name } = utils.getPackageInfo(); pkgcomp(buildConfig(args), utils.getIdent(), args).catch(err => {
pkgcomp(buildConfig(args), name, args).catch(err => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.error(err); console.error(err);
process.exit(err.exitCode); process.exit(err.exitCode);

View File

@@ -18,7 +18,7 @@ exports.read = (fileRoot, ident) => {
try { try {
const data = JSON.parse(fs.readFileSync(filePath)); const data = JSON.parse(fs.readFileSync(filePath));
return JSON.stringify(data[ident] || {}); return data[ident] || {};
} catch (err) { } catch (err) {
if (err.code === 'ENOENT') { if (err.code === 'ENOENT') {
fs.writeFileSync(filePath, JSON.stringify({})); fs.writeFileSync(filePath, JSON.stringify({}));

View File

@@ -1,5 +1,6 @@
const path = require('path'); const path = require('path');
const md5File = require('md5-file'); const md5File = require('md5-file');
const deepEqual = require('fast-deep-equal');
const shellExec = require('shell-exec'); const shellExec = require('shell-exec');
const data = require('./data'); const data = require('./data');
const utils = require('./utils'); const utils = require('./utils');
@@ -42,25 +43,14 @@ module.exports = async function pkgcomp(config, ident, opts = defaultOptions) {
// read dependencies from package.json // read dependencies from package.json
const pkg = utils.getFileContents(path.join(config.rootDir, 'package.json'), { format: 'json' }); const pkg = utils.getFileContents(path.join(config.rootDir, 'package.json'), { format: 'json' });
// read dependencies from workspace packages
const workspaces = utils.getPackageWorkspaces().map(({ name, package }) => {
const wpkg = utils.getFileContents(path.join(config.rootDir, package), { format: 'json' });
return {
name,
dependencies: wpkg.dependencies,
devDependencies: wpkg.devDependencies,
};
});
const payload = { const payload = {
hashes, hashes,
dependencies: pkg.dependencies, dependencies: pkg.dependencies,
devDependencies: pkg.devDependencies, devDependencies: pkg.devDependencies,
workspaces,
}; };
// check if the command should be run // check if the command should be run
const runCmd = Boolean(opts.force || (doExec && packageHistory !== JSON.stringify(payload))); const runCmd = Boolean(opts.force || (doExec && !deepEqual(packageHistory, payload)));
if (runCmd) { if (runCmd) {
const res = await execCommand(config.cmd); const res = await execCommand(config.cmd);
@@ -70,9 +60,6 @@ module.exports = async function pkgcomp(config, ident, opts = defaultOptions) {
err.cmd = res.cmd; err.cmd = res.cmd;
throw err; throw err;
} }
} else if (opts.verbose) {
// eslint-disable-next-line no-console
console.log('No changes, command skipped');
} }
data.write(config.dataDir, ident, payload); data.write(config.dataDir, ident, payload);

View File

@@ -2,7 +2,6 @@ const path = require('path');
const fs = require('fs'); const fs = require('fs');
const os = require('os'); const os = require('os');
const JoyCon = require('joycon'); const JoyCon = require('joycon');
const globParent = require('glob-parent');
exports.getRootPath = () => process.cwd(); exports.getRootPath = () => process.cwd();
@@ -28,40 +27,13 @@ exports.getFileContents = (filePath, opts = {}) => {
return content; return content;
}; };
exports.getPackageInfo = () => { exports.getRootFileContents = (filename, opts = {}) => {
const { name, workspaces } = exports.getFileContents( return exports.getFileContents(path.join(exports.getRootPath(), filename), opts);
path.join(exports.getRootPath(), 'package.json'),
{
format: 'json',
}
);
if (!name) throw new Error('Unable to read project name from package.json');
// handle nohoist config: https://yarnpkg.com/blog/2018/02/15/nohoist/
const realWorkspaces = workspaces.packages ? workspaces.packages : workspaces;
return { name, workspaces: realWorkspaces };
}; };
exports.getPackageWorkspaces = () => { exports.getIdent = () => {
const { workspaces } = exports.getPackageInfo(); const { name } = exports.getRootFileContents('package.json', { format: 'json' });
if (!workspaces) return []; return name;
return workspaces.reduce((acc, glob) => {
const parent = globParent(glob);
const packages = fs
.readdirSync(parent)
.map(package => {
const packageJson = path.join(parent, package, 'package.json');
if (!exports.canAccessFile(packageJson)) return false;
return {
name: package,
package: packageJson,
};
})
.filter(Boolean);
return acc.concat(packages);
}, []);
}; };
exports.getConfig = (overrides = {}) => { exports.getConfig = (overrides = {}) => {

View File

@@ -1027,13 +1027,6 @@ getopts@^2.0.6:
resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.4.tgz#3137fe8a5fddf304904059a851bdc1c22f0f54fb" resolved "https://registry.yarnpkg.com/getopts/-/getopts-2.2.4.tgz#3137fe8a5fddf304904059a851bdc1c22f0f54fb"
integrity sha512-Rz7DGyomZjrenu9Jx4qmzdlvJgvrEFHXHvjK0FcZtcTC1U5FmES7OdZHUwMuSnEE6QvBvwse1JODKj7TgbSEjQ== integrity sha512-Rz7DGyomZjrenu9Jx4qmzdlvJgvrEFHXHvjK0FcZtcTC1U5FmES7OdZHUwMuSnEE6QvBvwse1JODKj7TgbSEjQ==
glob-parent@^5.0.0:
version "5.0.0"
resolved "https://npm.w33ble.com:443/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954"
integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==
dependencies:
is-glob "^4.0.1"
glob@^7.0.3, glob@^7.1.2, glob@^7.1.3: glob@^7.0.3, glob@^7.1.2, glob@^7.1.3:
version "7.1.3" version "7.1.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1"
@@ -1331,7 +1324,7 @@ is-fullwidth-code-point@^2.0.0:
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
is-glob@^4.0.0, is-glob@^4.0.1: is-glob@^4.0.0:
version "4.0.1" version "4.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==