From f8279e51b7d75033fa3c801721caa4ab1bad18d2 Mon Sep 17 00:00:00 2001 From: Viktor Varland Date: Wed, 7 Apr 2021 13:14:07 +0200 Subject: [PATCH] feat: new and improved d2-style (#378) "d2-style" no longer tries to obfuscate what tools are used under the hood, and leans into being a friendly helper to nudge developers to comply with the dhis2 code style and guidelines. New features: - "d2-style " can now run all configured linters and formatters in a single command, making it easier to use. - "d2-style " is used to add configuration files for individual tools, e.g. eslint, prettier, etc. - "d2-style add" supports templates for e.g. react using: d2-style add eslint react - "d2-style install" reads the project configuration from .d2/style.config.js and sets up the project in accordance to that. BREAKING CHANGE: The verb (check/apply) is now moved to the top-level. E.g. "d2-style js check" becomes "d2-style check js". This is to allow all checkers to run with a single command: "d2-style check" BREAKING CHANGE: "d2-style install" is no longer used to set up linters. As of husky@5 the tool is vastly simplified and much faster. Hooks can be installed manually with "d2-style install", but is also run as a "post-install" script that we control for consistency. Configuration is added to the project with the "d2-style add" command. --- .browserslistrc | 0 .d2/hooks/.gitignore | 1 + .d2/hooks/commit-msg | 4 + .d2/hooks/pre-commit | 4 + .d2/hooks/pre-push | 4 + .d2/style.config.js | 7 + .editorconfig | 0 .eslintrc.js | 0 .github/dependabot.yml | 0 .github/semantic.yml | 0 .github/stale.yml | 0 .github/workflows/codeql-analysis.yml | 0 .github/workflows/comment-and-close.yml | 0 .github/workflows/dhis2-verify-node.yml | 0 .gitignore | 0 .prettierrc.js | 0 CHANGELOG.md | 23 ++ LICENSE | 0 README.md | 0 config/commitlint.config.js | 0 config/d2-style.config.js | 18 + config/{js => }/eslint-react.config.js | 0 config/{js => }/eslint.config.js | 3 - config/git/hooks/commit-msg | 2 - config/js/browserslist.config.rc | 5 - config/{js => }/prettier.config.js | 0 docs/_sidebar.md | 0 docs/faq.md | 0 docs/getting-started.md | 0 docs/ignore-files.md | 0 docs/migrate-guide.md | 0 docs/overrides.md | 0 index.js | 4 +- netlify.toml | 0 package.json | 16 +- src/commands.js | 15 +- src/commands/actions/eslint.js | 35 ++ src/commands/actions/git-hook.js | 49 +++ src/commands/add.js | 22 ++ src/commands/apply.js | 31 ++ src/commands/check.js | 66 ++++ src/commands/commit.js | 35 -- src/commands/install.js | 114 ++++--- src/commands/javascript.js | 67 ---- src/commands/remove.js | 18 + src/commands/structured-text.js | 67 ---- src/commands/types/commit.js | 35 ++ src/commands/types/javascript.js | 79 +++++ src/commands/types/structured-text.js | 62 ++++ src/index.js | 0 src/tools/commitlint.js | 10 +- src/tools/eslint.js | 6 +- src/tools/husky.js | 55 +++ src/tools/prettier.js | 17 +- src/utils/config.js | 156 ++++++--- src/utils/files.js | 58 +++- src/utils/groups.js | 314 ------------------ src/utils/paths.js | 67 ++-- src/utils/run.js | 32 +- src/utils/std-log-messages.js | 0 .../editorconfig-base.rc | 0 .../eslint-base.js | 0 .../eslint-react.js | 0 .../github-dependabot.yml | 0 .../github-semantic.yml | 0 .../stale.yml => templates/github-stale.yml | 0 .../prettier-base.js | 0 tests/configs.js | 0 tests/group-resolution.js | 100 ------ tests/main.js | 0 yarn.lock | 88 +++-- 71 files changed, 874 insertions(+), 815 deletions(-) mode change 100644 => 100755 .browserslistrc create mode 100755 .d2/hooks/.gitignore create mode 100755 .d2/hooks/commit-msg create mode 100755 .d2/hooks/pre-commit create mode 100755 .d2/hooks/pre-push create mode 100755 .d2/style.config.js mode change 100644 => 100755 .editorconfig mode change 100644 => 100755 .eslintrc.js mode change 100644 => 100755 .github/dependabot.yml mode change 100644 => 100755 .github/semantic.yml mode change 100644 => 100755 .github/stale.yml mode change 100644 => 100755 .github/workflows/codeql-analysis.yml mode change 100644 => 100755 .github/workflows/comment-and-close.yml mode change 100644 => 100755 .github/workflows/dhis2-verify-node.yml mode change 100644 => 100755 .gitignore mode change 100644 => 100755 .prettierrc.js mode change 100644 => 100755 CHANGELOG.md mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 config/commitlint.config.js create mode 100755 config/d2-style.config.js rename config/{js => }/eslint-react.config.js (100%) mode change 100644 => 100755 rename config/{js => }/eslint.config.js (94%) mode change 100644 => 100755 delete mode 100755 config/git/hooks/commit-msg delete mode 100644 config/js/browserslist.config.rc rename config/{js => }/prettier.config.js (100%) mode change 100644 => 100755 mode change 100644 => 100755 docs/_sidebar.md mode change 100644 => 100755 docs/faq.md mode change 100644 => 100755 docs/getting-started.md mode change 100644 => 100755 docs/ignore-files.md mode change 100644 => 100755 docs/migrate-guide.md mode change 100644 => 100755 docs/overrides.md mode change 100644 => 100755 index.js mode change 100644 => 100755 netlify.toml mode change 100644 => 100755 package.json mode change 100644 => 100755 src/commands.js create mode 100755 src/commands/actions/eslint.js create mode 100755 src/commands/actions/git-hook.js create mode 100755 src/commands/add.js create mode 100755 src/commands/apply.js create mode 100755 src/commands/check.js delete mode 100644 src/commands/commit.js mode change 100644 => 100755 src/commands/install.js delete mode 100644 src/commands/javascript.js create mode 100755 src/commands/remove.js delete mode 100644 src/commands/structured-text.js create mode 100755 src/commands/types/commit.js create mode 100755 src/commands/types/javascript.js create mode 100755 src/commands/types/structured-text.js mode change 100644 => 100755 src/index.js mode change 100644 => 100755 src/tools/commitlint.js mode change 100644 => 100755 src/tools/eslint.js create mode 100755 src/tools/husky.js mode change 100644 => 100755 src/tools/prettier.js mode change 100644 => 100755 src/utils/config.js mode change 100644 => 100755 src/utils/files.js delete mode 100644 src/utils/groups.js mode change 100644 => 100755 src/utils/paths.js mode change 100644 => 100755 src/utils/run.js mode change 100644 => 100755 src/utils/std-log-messages.js rename config/editorconfig.config.rc => templates/editorconfig-base.rc (100%) mode change 100644 => 100755 rename config/js/eslint.local.js => templates/eslint-base.js (100%) mode change 100644 => 100755 rename config/js/eslint-react.local.js => templates/eslint-react.js (100%) mode change 100644 => 100755 rename config/github/dependabot.yml => templates/github-dependabot.yml (100%) mode change 100644 => 100755 rename config/github/semantic.yml => templates/github-semantic.yml (100%) mode change 100644 => 100755 rename config/github/stale.yml => templates/github-stale.yml (100%) mode change 100644 => 100755 rename config/js/prettier.local.js => templates/prettier-base.js (100%) mode change 100644 => 100755 mode change 100644 => 100755 tests/configs.js delete mode 100644 tests/group-resolution.js mode change 100644 => 100755 tests/main.js mode change 100644 => 100755 yarn.lock diff --git a/.browserslistrc b/.browserslistrc old mode 100644 new mode 100755 diff --git a/.d2/hooks/.gitignore b/.d2/hooks/.gitignore new file mode 100755 index 00000000..31354ec1 --- /dev/null +++ b/.d2/hooks/.gitignore @@ -0,0 +1 @@ +_ diff --git a/.d2/hooks/commit-msg b/.d2/hooks/commit-msg new file mode 100755 index 00000000..9dd44f4e --- /dev/null +++ b/.d2/hooks/commit-msg @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +./bin/d2-style check commit "$1" diff --git a/.d2/hooks/pre-commit b/.d2/hooks/pre-commit new file mode 100755 index 00000000..22887254 --- /dev/null +++ b/.d2/hooks/pre-commit @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +./bin/d2-style check diff --git a/.d2/hooks/pre-push b/.d2/hooks/pre-push new file mode 100755 index 00000000..f077c917 --- /dev/null +++ b/.d2/hooks/pre-push @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +yarn test diff --git a/.d2/style.config.js b/.d2/style.config.js new file mode 100755 index 00000000..c6270722 --- /dev/null +++ b/.d2/style.config.js @@ -0,0 +1,7 @@ +module.exports = { + hooks: { + 'commit-msg': ['./bin/d2-style check commit "$1"'], + 'pre-commit': ['./bin/d2-style check'], + 'pre-push': ['yarn test'], + }, +} diff --git a/.editorconfig b/.editorconfig old mode 100644 new mode 100755 diff --git a/.eslintrc.js b/.eslintrc.js old mode 100644 new mode 100755 diff --git a/.github/dependabot.yml b/.github/dependabot.yml old mode 100644 new mode 100755 diff --git a/.github/semantic.yml b/.github/semantic.yml old mode 100644 new mode 100755 diff --git a/.github/stale.yml b/.github/stale.yml old mode 100644 new mode 100755 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml old mode 100644 new mode 100755 diff --git a/.github/workflows/comment-and-close.yml b/.github/workflows/comment-and-close.yml old mode 100644 new mode 100755 diff --git a/.github/workflows/dhis2-verify-node.yml b/.github/workflows/dhis2-verify-node.yml old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.prettierrc.js b/.prettierrc.js old mode 100644 new mode 100755 diff --git a/CHANGELOG.md b/CHANGELOG.md old mode 100644 new mode 100755 index d8a52dd3..37e48086 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ # [8.0.0-alpha.2](https://github.com/dhis2/cli-style/compare/v8.0.0-alpha.1...v8.0.0-alpha.2) (2020-12-16) +# [8.0.0-alpha.3](https://github.com/dhis2/cli-style/compare/v8.0.0-alpha.2...v8.0.0-alpha.3) (2020-12-16) + +# [8.0.0-alpha.2](https://github.com/dhis2/cli-style/compare/v8.0.0-alpha.1...v8.0.0-alpha.2) (2020-12-16) + ### Features * opt-in git hooks ([#333](https://github.com/dhis2/cli-style/issues/333)) ([a3bc415](https://github.com/dhis2/cli-style/commit/a3bc415d3971756e2ef53ab59dbbc4fb48046b07)) @@ -29,6 +33,25 @@ remove hooks that reference husky.sh in .git/hooks. * **eslint:** add import order rule ([#334](https://github.com/dhis2/cli-style/issues/334)) ([c7b9991](https://github.com/dhis2/cli-style/commit/c7b99917e39b2ed16165d0a115f0e0c3ebe775e1)) +# [8.0.0-alpha.2](https://github.com/dhis2/cli-style/compare/v8.0.0-alpha.1...v8.0.0-alpha.2) (2020-12-16) + +### Features + +* opt-in git hooks ([#333](https://github.com/dhis2/cli-style/issues/333)) ([a3bc415](https://github.com/dhis2/cli-style/commit/a3bc415d3971756e2ef53ab59dbbc4fb48046b07)) + +# [8.0.0-alpha.1](https://github.com/dhis2/cli-style/compare/v7.2.3...v8.0.0-alpha.1) (2020-12-16) + + +### Code Refactoring + +* remove husky ([752b944](https://github.com/dhis2/cli-style/commit/752b94409a3a9735d324d05aefdd296f0d6bfb44)) + + +### BREAKING CHANGES + +* Husky has been removed from cli-style. You will need to +remove hooks that reference husky.sh in .git/hooks. + ## [7.2.3](https://github.com/dhis2/cli-style/compare/v7.2.2...v7.2.3) (2020-12-16) diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/config/commitlint.config.js b/config/commitlint.config.js old mode 100644 new mode 100755 diff --git a/config/d2-style.config.js b/config/d2-style.config.js new file mode 100755 index 00000000..b7721c8a --- /dev/null +++ b/config/d2-style.config.js @@ -0,0 +1,18 @@ +module.exports = { + hooks: { + 'commit-msg': ['yarn d2-style commit check "$1"'], + 'pre-commit': ['yarn d2-style check'], + 'pre-push': ['yarn test'], + }, + tools: { + eslint: ['react'], + prettier: [], + github: ['dependabot', 'semantic-pr', 'stale'], + editorconfig: [], + commitlint: [], + }, + patterns: { + js: '**/*.{js,jsx,ts,tsx}', + text: '**/*.{md,json,yml,html}', + }, +} diff --git a/config/js/eslint-react.config.js b/config/eslint-react.config.js old mode 100644 new mode 100755 similarity index 100% rename from config/js/eslint-react.config.js rename to config/eslint-react.config.js diff --git a/config/js/eslint.config.js b/config/eslint.config.js old mode 100644 new mode 100755 similarity index 94% rename from config/js/eslint.config.js rename to config/eslint.config.js index eb9de21b..0b59fd5c --- a/config/js/eslint.config.js +++ b/config/eslint.config.js @@ -9,8 +9,6 @@ module.exports = { // unignore implicit rules about what types of files can be linted ignorePatterns: ['!.*'], - plugins: ['prettier'], - env: { browser: true, node: true, @@ -42,7 +40,6 @@ module.exports = { }, ], 'no-mixed-spaces-and-tabs': ['error'], - 'prettier/prettier': ['error'], 'import/order': [ 'error', { diff --git a/config/git/hooks/commit-msg b/config/git/hooks/commit-msg deleted file mode 100755 index 3be737cd..00000000 --- a/config/git/hooks/commit-msg +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -yarn d2-style commit check "$1" diff --git a/config/js/browserslist.config.rc b/config/js/browserslist.config.rc deleted file mode 100644 index 04938758..00000000 --- a/config/js/browserslist.config.rc +++ /dev/null @@ -1,5 +0,0 @@ -> 0.5% -last 2 versions -Firefox ESR -not ie 11 -not dead diff --git a/config/js/prettier.config.js b/config/prettier.config.js old mode 100644 new mode 100755 similarity index 100% rename from config/js/prettier.config.js rename to config/prettier.config.js diff --git a/docs/_sidebar.md b/docs/_sidebar.md old mode 100644 new mode 100755 diff --git a/docs/faq.md b/docs/faq.md old mode 100644 new mode 100755 diff --git a/docs/getting-started.md b/docs/getting-started.md old mode 100644 new mode 100755 diff --git a/docs/ignore-files.md b/docs/ignore-files.md old mode 100644 new mode 100755 diff --git a/docs/migrate-guide.md b/docs/migrate-guide.md old mode 100644 new mode 100755 diff --git a/docs/overrides.md b/docs/overrides.md old mode 100644 new mode 100755 diff --git a/index.js b/index.js old mode 100644 new mode 100755 index 57ab34cf..7fb1dd60 --- a/index.js +++ b/index.js @@ -1,5 +1,5 @@ const command = require('./src/index.js') -const { bundledConfigPaths } = require('./src/utils/groups.js') +const { packageConfigs } = require('./src/utils/config.js') -exports.config = bundledConfigPaths() +exports.config = packageConfigs exports.command = command diff --git a/netlify.toml b/netlify.toml old mode 100644 new mode 100755 diff --git a/package.json b/package.json old mode 100644 new mode 100755 index e6012415..38fdd765 --- a/package.json +++ b/package.json @@ -15,14 +15,10 @@ }, "scripts": { "test": "tape tests/**/*.js", - "lint:js": "./bin/d2-style js check", - "lint:text": "./bin/d2-style text check", - "lint:staged": "yarn lint:js --staged && yarn lint:text --staged", - "lint": "yarn lint:js && yarn lint:text", - "format:js": "./bin/d2-style js apply", - "format:text": "./bin/d2-style text apply", - "format:staged": "yarn format:js --staged && yarn format:text --staged", - "format": "yarn format:js && yarn format:text", + "lint:staged": "yarn lint --staged", + "lint": "./bin/d2-style check", + "format:staged": "yarn format --staged", + "format": "./bin/d2-style apply", "build:docs": "d2-utils-docsite build ./docs -o ./dist --jsdoc src/ --jsdocOutputFile api.md", "start": "d2-utils-docsite serve ./docs -o ./dist --jsdoc src/ --jsdocOutputFile api.md" }, @@ -37,11 +33,11 @@ "eslint": "^7.18.0", "eslint-config-prettier": "^7.2.0", "eslint-plugin-import": "^2.22.1", - "eslint-plugin-prettier": "^3.3.1", "eslint-plugin-react": "^7.22.0", "fast-glob": "^3.2.5", "find-up": "^5.0.0", - "fs-extra": "^9.0.1", + "fs-extra": "^9.1.0", + "husky": "^5.2.0", "perfy": "^1.1.5", "prettier": "^2.2.1", "semver": "^7.3.4", diff --git a/src/commands.js b/src/commands.js old mode 100644 new mode 100755 index 2cc25e23..e2e4d84b --- a/src/commands.js +++ b/src/commands.js @@ -1,3 +1,12 @@ -module.exports = yargs => { - yargs.commandDir('commands') -} +const { packageConfigs, styleConfig } = require('./utils/config.js') + +module.exports = yargs => + yargs + .config({ + config: { + ...require(packageConfigs.d2Style), + ...styleConfig, + }, + files: [], + }) + .commandDir('commands') diff --git a/src/commands/actions/eslint.js b/src/commands/actions/eslint.js new file mode 100755 index 00000000..c8b81a33 --- /dev/null +++ b/src/commands/actions/eslint.js @@ -0,0 +1,35 @@ +const log = require('@dhis2/cli-helpers-engine').reporter +const cfg = require('../../utils/config.js') + +exports.command = 'eslint [type]' + +exports.desc = '' + +exports.builder = yargs => + yargs + .positional('type', { + describe: '', + type: 'string', + }) + .option('overwrite', { + describe: '', + type: 'boolean', + }) + .example('$0', 'Adds the standard ESLint configuration to .eslintrc.js') + +exports.handler = argv => { + const { add, type, overwrite } = argv + + log.info(`eslint > ${add ? 'add' : 'remove'}`) + + if (add) { + const template = type ? type : 'base' + cfg.add({ + tool: 'eslint', + template, + overwrite, + }) + } else { + cfg.remove({ tool: 'eslint', type }) + } +} diff --git a/src/commands/actions/git-hook.js b/src/commands/actions/git-hook.js new file mode 100755 index 00000000..40f4eb92 --- /dev/null +++ b/src/commands/actions/git-hook.js @@ -0,0 +1,49 @@ +const path = require('path') +const log = require('@dhis2/cli-helpers-engine').reporter +const { husky } = require('../../tools/husky.js') +const { remove } = require('../../utils/config.js') +const { CONSUMING_ROOT, PROJECT_HOOKS_DIR } = require('../../utils/paths.js') + +const defaultCommand = type => + `echo "To customize this hook, edit ${type} in ${path.relative( + CONSUMING_ROOT, + PROJECT_HOOKS_DIR + )}"\nexit 1` + +exports.command = 'git-hook [command]' + +exports.desc = '' + +exports.builder = yargs => + yargs + .positional('type', { + describe: '', + type: 'string', + }) + .positional('command', { + describe: '', + type: 'string', + }) + .option('overwrite', { + describe: '', + type: 'boolean', + }) + +exports.handler = argv => { + const { add, type, command, overwrite } = argv + + log.info(`git-hook > ${add ? 'add' : 'remove'}`) + + if (add) { + const cmd = overwrite ? 'set' : 'add' + + husky({ + command: cmd, + hookType: type, + hookCmd: command ? command : defaultCommand(type), + }) + } else { + const hookFile = path.join(PROJECT_HOOKS_DIR, type) + remove({ path: hookFile }) + } +} diff --git a/src/commands/add.js b/src/commands/add.js new file mode 100755 index 00000000..a937a475 --- /dev/null +++ b/src/commands/add.js @@ -0,0 +1,22 @@ +exports.command = 'add' + +exports.describe = 'Add a configuration file for a tool to the project.' + +exports.builder = yargs => + yargs + .commandDir('actions') + .config({ + add: true, + }) + .example( + '$0 add eslint', + 'Adds the standard ESLint configuration to the project.' + ) + .example( + '$0 add eslint react', + 'Adds React specific ESLint configuration to the project.' + ) + .example( + '$0 add git-hook pre-push "yarn test"', + 'Adds a pre-push git hook that runs the command "yarn test"' + ) diff --git a/src/commands/apply.js b/src/commands/apply.js new file mode 100755 index 00000000..07883b5e --- /dev/null +++ b/src/commands/apply.js @@ -0,0 +1,31 @@ +const { jscmd } = require('./check.js') + +exports.command = 'apply' + +exports.describe = + 'Apply code format and fix all lint issues that can be resolved automatically.' + +exports.builder = yargs => + jscmd(yargs) + .command(require('./types/javascript.js')) + .command(require('./types/structured-text.js')) + .option('staged', { + describe: 'Only check staged files in Git', + type: 'boolean', + default: false, + }) + .config({ + apply: true, + }) + .example( + '$0 apply', + 'Finds and applies code format and lint fixes to all supported, or configured, file formats.' + ) + .example( + '$0 apply js', + 'Applies code format and lint fixes to JavaScript files.' + ) + .example( + '$0 apply text --staged', + 'Only match files that are staged in Git.' + ) diff --git a/src/commands/check.js b/src/commands/check.js new file mode 100755 index 00000000..ab350ba0 --- /dev/null +++ b/src/commands/check.js @@ -0,0 +1,66 @@ +const log = require('@dhis2/cli-helpers-engine').reporter +const { callback, exit } = require('../utils/run.js') +const { handler: jsHandler } = require('./types/javascript.js') +const { handler: textHandler } = require('./types/structured-text.js') + +const statusCode = callback() + +exports.jscmd = yargs => + yargs.command( + '$0 [files..]', + 'default', + yargs => + yargs.positional('files', { + describe: '', + type: 'string', + }), + argv => { + if (!argv.config.patterns) { + log.warn( + 'No patterns defined, please check the configuration file' + ) + process.exit(1) + } + + if (argv.config.patterns.js) { + jsHandler(argv, statusCode) + log.print('') + } + + if (argv.config.patterns.text) { + textHandler(argv, statusCode) + } + + exit(statusCode()) + } + ) + +exports.command = 'check' + +exports.describe = 'Automatically run the appropriate checks on files' + +exports.builder = yargs => + this.jscmd(yargs) + .command(require('./types/javascript.js')) + .command(require('./types/structured-text.js')) + .command(require('./types/commit.js')) + .option('staged', { + describe: 'Only check staged files in Git', + type: 'boolean', + default: false, + }) + .config({ + apply: false, + }) + .example( + '$0 check', + 'Finds and checks code for formatting and lint issues, for all supported, or configured, file formats.' + ) + .example( + '$0 check js', + 'Checks code format and lint issues to JavaScript files.' + ) + .example( + '$0 check text --staged', + 'Only match files that are staged in Git.' + ) diff --git a/src/commands/commit.js b/src/commands/commit.js deleted file mode 100644 index 77ff0884..00000000 --- a/src/commands/commit.js +++ /dev/null @@ -1,35 +0,0 @@ -const log = require('@dhis2/cli-helpers-engine').reporter -const { namespace } = require('@dhis2/cli-helpers-engine') -const { commitlint } = require('../tools/commitlint.js') -const { CONSUMING_ROOT } = require('../utils/paths.js') - -const commitCmd = yargs => { - return yargs.command( - 'check [file]', - 'Checks commit messages according to standard.', - function builder(yargs) { - return yargs - .positional('file', { - describe: 'File that contains the commit message', - type: 'string', - default: `${CONSUMING_ROOT}/.git/COMMIT_EDITMSG`, - }) - .option('commitlintConfig', { - describe: 'Commitlint config file to use', - type: 'string', - }) - }, - function handler(argv) { - log.info('d2-style > commit') - commitlint({ - config: argv.commitlintConfig, - file: argv.file, - }) - } - ) -} - -module.exports = namespace('commit', { - describe: 'Check commit messages according to standards.', - builder: yargs => commitCmd(yargs), -}) diff --git a/src/commands/install.js b/src/commands/install.js old mode 100644 new mode 100755 index 97464c1e..eae51da8 --- a/src/commands/install.js +++ b/src/commands/install.js @@ -1,46 +1,68 @@ -const { reporter, prompt } = require('@dhis2/cli-helpers-engine') -const { configure } = require('../utils/config.js') -const { printGroups, projects } = require('../utils/groups.js') - -const promptForProject = async () => { - const res = await prompt([ - { - name: 'project', - message: 'Choose the project template', - type: 'list', - choices: () => projects.map(a => a[0]), - }, - ]) - return [`project/${res.project}`] -} - -exports.command = 'install [group..]' - -exports.describe = 'Install DHIS2 configurations for a/all group(s)' - -exports.builder = { - force: { - describe: 'Overwrites existing configuration', - type: 'boolean', - default: 'false', - }, - listGroups: { - describe: 'List available groups', - type: 'boolean', - default: 'false', - }, -} - -exports.handler = async argv => { - if (argv.listGroups) { - reporter.print(printGroups()) - process.exit(0) - } - - const force = argv.force - const group = argv.group || (await promptForProject()) - - const root = process.cwd() - - configure(root, group, force) -} +const path = require('path') +const log = require('@dhis2/cli-helpers-engine').reporter +const { husky, isSupportedHook } = require('../tools/husky.js') +const { fileExists, deleteFile } = require('../utils/files.js') +const { PROJECT_HOOKS_DIR } = require('../utils/paths.js') +const { callback, exit } = require('../utils/run.js') + +const statusCode = callback() + +exports.command = 'install' + +exports.describe = 'Install the project configuration into the local project.' + +exports.builder = yargs => this.installcmd(yargs) + +exports.installcmd = yargs => + yargs.command( + '$0', + 'default', + yargs => + yargs.option('clean', { + describe: '', + type: 'boolean', + }), + argv => { + const { config, clean } = argv + + if (clean && fileExists(PROJECT_HOOKS_DIR)) { + const result = deleteFile(PROJECT_HOOKS_DIR) + log.debug(`Deleted ${PROJECT_HOOKS_DIR}: ${result}`) + } + + if (config.hooks) { + log.info('git-hooks > husky') + husky({ + command: 'install', + callback: statusCode, + }) + + /* + * If there are no hooks locally, but we have hooks defined + * in the configuration, we will install those in the repo. + */ + + for (const hookType in config.hooks) { + const hookPath = path.join(PROJECT_HOOKS_DIR, hookType) + if (isSupportedHook(hookType) && !fileExists(hookPath)) { + const hookCmds = config.hooks[hookType] + + hookCmds.map(hookCmd => + husky({ + command: 'add', + hookType, + hookCmd, + callback: statusCode, + }) + ) + } + } + + if (statusCode() === 0) { + log.print('Install completed successfully') + } + } + + exit(statusCode()) + } + ) diff --git a/src/commands/javascript.js b/src/commands/javascript.js deleted file mode 100644 index e39c996f..00000000 --- a/src/commands/javascript.js +++ /dev/null @@ -1,67 +0,0 @@ -const { namespace } = require('@dhis2/cli-helpers-engine') -const log = require('@dhis2/cli-helpers-engine').reporter -const { eslint } = require('../tools/eslint.js') -const { selectFiles } = require('../utils/files.js') -const { sayFilesChecked, sayNoFiles } = require('../utils/std-log-messages.js') - -const options = yargs => - yargs - .option('pattern', { - describe: - 'Pattern to match for files, remember to enclose in double quotes!', - type: 'string', - default: '**/*.{js,jsx,ts,tsx}', - }) - .option('staged', { - describe: 'Only check staged files in Git', - type: 'boolean', - default: false, - }) - -const handler = (argv, apply) => { - const { files, pattern, staged } = argv - - log.info('d2-style > javascript') - - const opts = { - apply, - } - - opts.files = selectFiles(files, pattern, staged) - - if (opts.files.length === 0) { - log.print(sayNoFiles('javascript', pattern, staged)) - return - } - - log.debug(`Linting files: ${opts.files.join(', ')}`) - - eslint({ - ...opts, - }) - - log.print(sayFilesChecked('javascript', opts.files.length, apply)) -} - -const javascriptCmds = yargs => { - return yargs - .command( - 'apply [files..]', - 'Apply JS format.', - yargs => options(yargs), - argv => handler(argv, true) - ) - - .command( - 'check [files..]', - 'Check JS format (do not attempt to fix)', - yargs => options(yargs), - argv => handler(argv, false) - ) -} - -module.exports = namespace('javascript', { - aliases: ['js'], - describe: 'Format javascript according to standards', - builder: yargs => javascriptCmds(yargs), -}) diff --git a/src/commands/remove.js b/src/commands/remove.js new file mode 100755 index 00000000..d99d68fa --- /dev/null +++ b/src/commands/remove.js @@ -0,0 +1,18 @@ +exports.command = 'remove' + +exports.describe = 'Removes specified tool configuration files.' + +exports.builder = yargs => + yargs + .commandDir('actions') + .config({ + add: false, + }) + .example( + '$0 remove eslint', + 'Removes the project configurationf for ESLint' + ) + .example( + '$0 remove git-hook pre-commit', + 'Removes the pre-commit Git hook.' + ) diff --git a/src/commands/structured-text.js b/src/commands/structured-text.js deleted file mode 100644 index ff106306..00000000 --- a/src/commands/structured-text.js +++ /dev/null @@ -1,67 +0,0 @@ -const { namespace } = require('@dhis2/cli-helpers-engine') -const log = require('@dhis2/cli-helpers-engine').reporter -const { prettier } = require('../tools/prettier.js') -const { selectFiles } = require('../utils/files.js') -const { sayFilesChecked, sayNoFiles } = require('../utils/std-log-messages.js') - -const options = yargs => - yargs - .option('pattern', { - describe: - 'Pattern to match for files, remember to enclose in double quotes!', - type: 'string', - default: '**/*.{md,json,yml,html}', - }) - .option('staged', { - describe: 'Only check staged files in Git', - type: 'boolean', - default: false, - }) - -const handler = (argv, apply) => { - const { files, pattern, staged } = argv - - log.info('d2-style > structured-text') - - const opts = { - apply, - } - - opts.files = selectFiles(files, pattern, staged) - - if (opts.files.length === 0) { - log.print(sayNoFiles('text', pattern, staged)) - return - } - - log.debug(`Linting files: ${opts.files.join(', ')}`) - - prettier({ - ...opts, - }) - - log.print(sayFilesChecked('text', opts.files.length, apply)) -} - -const textCmds = yargs => { - return yargs - .command( - 'apply [files..]', - 'Apply structured text format.', - yargs => options(yargs), - argv => handler(argv, true) - ) - - .command( - 'check [files..]', - 'Check structured text format (do not attempt to fix)', - yargs => options(yargs), - argv => handler(argv, false) - ) -} - -module.exports = namespace('structured-text', { - aliases: ['text'], - describe: 'Format structured text according to standards', - builder: yargs => textCmds(yargs), -}) diff --git a/src/commands/types/commit.js b/src/commands/types/commit.js new file mode 100755 index 00000000..7d984427 --- /dev/null +++ b/src/commands/types/commit.js @@ -0,0 +1,35 @@ +const log = require('@dhis2/cli-helpers-engine').reporter +const { commitlint } = require('../../tools/commitlint.js') +const { CONSUMING_ROOT } = require('../../utils/paths.js') +const { callback, exit } = require('../../utils/run.js') + +const statusCode = callback() + +exports.command = 'commit [file]' + +exports.desc = '' + +exports.builder = yargs => + yargs + .positional('file', { + describe: 'File that contains the commit message', + type: 'string', + default: `${CONSUMING_ROOT}/.git/COMMIT_EDITMSG`, + }) + .option('commitlintConfig', { + describe: 'Commitlint config file to use', + type: 'string', + }) + +exports.handler = argv => { + log.info(`commit-msg > commitlint`) + commitlint({ + config: argv.commitlintConfig, + file: argv.file, + callback: statusCode, + }) + if (statusCode() === 0) { + log.print('The commit message is conventional.') + } + exit(statusCode()) +} diff --git a/src/commands/types/javascript.js b/src/commands/types/javascript.js new file mode 100755 index 00000000..3d976e7b --- /dev/null +++ b/src/commands/types/javascript.js @@ -0,0 +1,79 @@ +const log = require('@dhis2/cli-helpers-engine').reporter +const { eslint } = require('../../tools/eslint.js') +const { prettier } = require('../../tools/prettier.js') +const { selectFiles } = require('../../utils/files.js') +const { callback: runCb, exit } = require('../../utils/run.js') +const { + sayFilesChecked, + sayNoFiles, +} = require('../../utils/std-log-messages.js') + +exports.command = 'js [files..]' + +exports.aliases = ['javascript'] + +exports.desc = 'JavaScript code style' + +exports.builder = yargs => + yargs.positional('files', { + describe: '', + type: 'string', + }) + +exports.handler = (argv, callback) => { + if ( + !argv.config.patterns || + (argv.config.patterns && !argv.config.patterns.js) + ) { + log.warn( + 'No javascript patterns defined, please check the configuration file' + ) + process.exit(1) + } + + const finalStatus = callback || runCb() + + const { + config: { + patterns: { js: jsPattern }, + }, + files, + staged, + apply, + } = argv + + const jsFiles = selectFiles(files, jsPattern, staged) + + if (jsFiles.length === 0) { + log.warn(sayNoFiles('javascript', jsPattern, staged)) + return + } + + log.debug(`Linting files: ${jsFiles.join(', ')}`) + + log.info('javascript > eslint') + eslint({ + apply, + files: jsFiles, + callback: finalStatus, + }) + + if (finalStatus() === 0) { + log.print('All matched files pass the lint rules.') + log.print('') + } + + log.info('javascript > prettier') + prettier({ + apply, + files: jsFiles, + callback: finalStatus, + }) + + if (!callback) { + log.debug(sayFilesChecked('javascript', jsFiles.length, apply)) + exit(finalStatus()) + } + + return jsFiles.length +} diff --git a/src/commands/types/structured-text.js b/src/commands/types/structured-text.js new file mode 100755 index 00000000..a1d3a1f5 --- /dev/null +++ b/src/commands/types/structured-text.js @@ -0,0 +1,62 @@ +const log = require('@dhis2/cli-helpers-engine').reporter +const { prettier } = require('../../tools/prettier.js') +const { selectFiles } = require('../../utils/files.js') +const { callback: runCb, exit } = require('../../utils/run.js') +const { + sayFilesChecked, + sayNoFiles, +} = require('../../utils/std-log-messages.js') + +exports.command = 'text [files..]' +exports.aliases = ['structured-text'] +exports.desc = 'Structured text style' +exports.builder = yargs => + yargs.positional('files', { + describe: '', + type: 'string', + }) + +exports.handler = (argv, callback) => { + if ( + !argv.config.patterns || + (argv.config.patterns && !argv.config.patterns.text) + ) { + log.warn( + 'No text patterns defined, please check the configuration file' + ) + process.exit(1) + } + + const finalStatus = callback || runCb() + + const { + config: { + patterns: { text: textPattern }, + }, + files, + staged, + apply, + } = argv + + const textFiles = selectFiles(files, textPattern, staged) + if (textFiles.length === 0) { + log.warn(sayNoFiles('structured text', textPattern, staged)) + return + } + + log.debug(`Linting files: ${textFiles.join(', ')}`) + + log.info('structured-text > prettier') + prettier({ + apply, + files: textFiles, + callback: finalStatus, + }) + + if (!callback) { + log.debug(sayFilesChecked('text', textFiles.length, apply)) + exit(finalStatus()) + } + + return textFiles.length +} diff --git a/src/index.js b/src/index.js old mode 100644 new mode 100755 diff --git a/src/tools/commitlint.js b/src/tools/commitlint.js old mode 100644 new mode 100755 index 9667c75f..22e867a2 --- a/src/tools/commitlint.js +++ b/src/tools/commitlint.js @@ -1,7 +1,11 @@ -const { COMMITLINT_CONFIG } = require('../utils/paths.js') +const { packageConfigs } = require('../utils/config.js') const { bin } = require('../utils/run.js') -exports.commitlint = ({ config = COMMITLINT_CONFIG, file }) => { +exports.commitlint = ({ + config = packageConfigs.commitlint, + file, + callback, +}) => { const cmd = 'commitlint' const args = [ 'commitlint', @@ -9,5 +13,5 @@ exports.commitlint = ({ config = COMMITLINT_CONFIG, file }) => { ...(file ? ['--edit', file] : []), ] - bin(cmd, { args }) + bin(cmd, { args }, callback) } diff --git a/src/tools/eslint.js b/src/tools/eslint.js old mode 100644 new mode 100755 index fda1e6c0..c2892391 --- a/src/tools/eslint.js +++ b/src/tools/eslint.js @@ -2,14 +2,14 @@ const { resolveIgnoreFile } = require('../utils/files.js') const { PACKAGE_ROOT } = require('../utils/paths.js') const { bin } = require('../utils/run.js') -exports.eslint = ({ files = [], apply = false, config }) => { +exports.eslint = ({ files = [], apply = false, config, callback }) => { const ignoreFile = resolveIgnoreFile(['.eslintignore']) const cmd = 'eslint' const args = [ '--no-color', '--report-unused-disable-directives', '--ignore', - '--format=unix', + '--format=stylish', `--resolve-plugins-relative-to=${PACKAGE_ROOT}`, ...(ignoreFile ? ['--ignore-path', ignoreFile] : []), ...(config ? ['--config', config] : []), @@ -17,5 +17,5 @@ exports.eslint = ({ files = [], apply = false, config }) => { ...files, ] - bin(cmd, { args }) + bin(cmd, { args }, callback) } diff --git a/src/tools/husky.js b/src/tools/husky.js new file mode 100755 index 00000000..f12f7a18 --- /dev/null +++ b/src/tools/husky.js @@ -0,0 +1,55 @@ +const { join } = require('path') +const { PROJECT_HOOKS_DIR } = require('../utils/paths.js') +const { bin, exit } = require('../utils/run.js') + +// https://git-scm.com/docs/githooks +const supportedHooks = [ + 'applypatch-msg', + 'pre-applypatch', + 'post-applypatch', + 'pre-commit', + 'pre-merge-commit', + 'prepare-commit-msg', + 'commit-msg', + 'post-commit', + 'pre-rebase', + 'post-checkout', + 'post-merge', + 'pre-push', + 'pre-receive', + 'update', + 'proc-receive', + 'post-receive', + 'post-update', + 'reference-transaction', + 'push-to-checkout', + 'pre-auto-gc', + 'post-rewrite', + 'sendemail-validate', + 'fsmonitor-watchman', + 'p4-changelist', + 'p4-prepare-changelist', + 'p4-post-changelist', + 'p4-pre-submit', + 'post-index-change', +] + +exports.isSupportedHook = hook => supportedHooks.includes(hook) + +exports.husky = ({ command, hookType, hookCmd, callback }) => { + if (hookType && !this.isSupportedHook(hookType)) { + exit(1, 'Unsupported hook') + } + + const cmd = 'husky' + const args = [ + command, + ...(command === 'install' ? [PROJECT_HOOKS_DIR] : []), + ...(['set', 'add'].includes(command) + ? [join(PROJECT_HOOKS_DIR, hookType)] + : []), + ...(hookCmd ? [hookCmd] : []), + ] + + bin(cmd, { args }, callback) +} diff --git a/src/tools/prettier.js b/src/tools/prettier.js old mode 100644 new mode 100755 index b304a4db..ac982803 --- a/src/tools/prettier.js +++ b/src/tools/prettier.js @@ -1,27 +1,16 @@ -const log = require('@dhis2/cli-helpers-engine').reporter const { resolveIgnoreFile } = require('../utils/files.js') const { bin } = require('../utils/run.js') -exports.prettier = ({ files = [], apply = false, config }) => { +exports.prettier = ({ files = [], apply = false, config, callback }) => { const ignoreFile = resolveIgnoreFile(['.prettierignore']) const cmd = 'prettier' const args = [ - '--list-different', + '--check', ...(config ? ['--config', config] : []), ...(ignoreFile ? ['--ignore-path', ignoreFile] : []), ...(apply ? ['--write'] : []), ...files, ] - bin(cmd, { args }, ({ status }) => { - if (status === 1 && !apply) { - log.warn(`Code style issues found in the above file(s).`) - } - - if (status === 2) { - log.info( - 'Internal error in Prettier, run with "--verbose" for more information.' - ) - } - }) + bin(cmd, { args }, callback) } diff --git a/src/utils/config.js b/src/utils/config.js old mode 100644 new mode 100755 index 023faebb..51275d13 --- a/src/utils/config.js +++ b/src/utils/config.js @@ -1,59 +1,125 @@ const path = require('path') const log = require('@dhis2/cli-helpers-engine').reporter -const fs = require('fs-extra') - -function copy(from, to, overwrite = true) { - try { - const exists = fs.existsSync(to) - const empty = exists ? fs.statSync(to).size === 0 : false - - const replace = empty ? true : overwrite - - if (exists && !replace) { - log.print(`Skip existing: ${path.relative(process.cwd(), to)}`) - } else { - log.print(`Installing: ${path.relative(process.cwd(), to)}`) - } - fs.ensureDirSync(path.dirname(to)) - fs.copySync(from, to, { overwrite: replace }) - } catch (err) { - log.error(`Failed to install configuration file: ${to}`, err) - } -} +const findup = require('find-up') +const { copy, fileExists, deleteFile } = require('./files.js') +const { + PACKAGE_ROOT, + PROJECT_ROOT, + CONFIG_DIR, + TEMPLATE_DIR, + STYLE_CONFIG_FILES, +} = require('./paths.js') -function configure(repo, group = [''], overwrite) { - const { - isValidGroup, - isValidProject, - resolveProjectToGroups, - groupConfigs, - expandGroupAll, - } = require('./groups.js') +/** + * Configuration files that are bundled in the cli-style package. + * Can be imported from the main entry-point. + * + * Used to either resolve the base configuration file to use, or + * referenced from a template config file when installed in a project. + */ +const packageConfigs = { + eslint: path.join(CONFIG_DIR, 'eslint.config.js'), + eslintReact: path.join(CONFIG_DIR, 'eslint-react.config.js'), + commitlint: path.join(CONFIG_DIR, 'commitlint.config.js'), + d2Style: path.join(CONFIG_DIR, 'd2-style.config.js'), + prettier: path.join(CONFIG_DIR, 'prettier.config.js'), +} - const validProjects = group.filter(isValidProject) +/** + * The configuration files as they should appear when installed into a + * project. + */ +const projectConfigs = { + editorconfig: path.join(PROJECT_ROOT, '.editorconfig'), + eslint: path.join(PROJECT_ROOT, '.eslintrc.js'), + prettier: path.join(PROJECT_ROOT, '.prettierrc.js'), + github: { + dependabot: path.join(PROJECT_ROOT, '.github', 'dependabot.yml'), + semantic: path.join(PROJECT_ROOT, '.github', 'semantic.yml'), + stale: path.join(PROJECT_ROOT, '.github', 'stale.yml'), + }, +} - const projectGroups = validProjects - .map(resolveProjectToGroups) - .reduce((a, b) => a.concat(b), []) +/** + * The template configuration files are the config files that are + * installed into the project as defined by the projectConfig path. + * + * We want to be able to update the packageConfig and have those updates + * automatically propagate to the projectConfig, so we use these + * templates to refer to the packageConfigs, which can then be + * customized in the project. + */ +const templateConfigs = { + editorconfig: { + base: path.join(TEMPLATE_DIR, 'editorconfig-base.rc'), + }, + eslint: { + base: path.join(TEMPLATE_DIR, 'eslint-base.js'), + react: path.join(TEMPLATE_DIR, 'eslint-react.js'), + }, + prettier: { + base: path.join(TEMPLATE_DIR, 'prettier-base.js'), + }, + github: { + dependabot: path.join(TEMPLATE_DIR, 'github-dependabot.yml'), + semantic: path.join(TEMPLATE_DIR, 'github-semantic.yml'), + stale: path.join(TEMPLATE_DIR, 'github-stale.yml'), + }, +} - const expandedGroups = [...projectGroups, ...group] - .map(expandGroupAll) - .reduce((a, b) => a.concat(b), []) +/** + * Add a configuration file to the project based on a template. + * If there is already a config file, we install a new one next to it + * with '.new' as the suffix. + * + * This allows users to diff old vs. new and see if there are any + * customizations that need to be brought over. + */ +function add({ tool, template, overwrite = false }) { + const toolConfig = projectConfig(tool) + const toolTemplate = templateConfig(tool, template) - const groups = [...new Set(expandedGroups)] + copy(toolTemplate, toolConfig, { overwrite, backup: true }) +} - const validGroups = groups.filter(isValidGroup) +/** + * Removes a configuration file based on the tool and/or type used. + * + * If path is used, then tool and type are ignored. + */ +function remove({ tool, type, path }) { + const config = !path ? projectConfig(tool, type) : path - if (validGroups.length !== 0) { - log.info(`Running setup for group(s): ${validGroups.join('\n * ')}`) + if (fileExists(config)) { + const result = deleteFile(config) + result + ? log.print(`Removed: ${config}`) + : log.error(`Failed to remove: ${config}`) + } else { + log.warn(`Does not exist: ${config}`) } - - return validGroups - .map(groupConfigs) - .reduce((a, b) => a.concat(b), []) - .map(c => copy(c[0], c[1], overwrite)) } +const projectConfig = (tool, template) => + template ? projectConfigs[tool][template] : projectConfigs[tool] + +const templateConfig = (tool, template) => + template ? templateConfigs[tool][template] : templateConfigs[tool] + +const resolvedStyleConfig = findup.sync(STYLE_CONFIG_FILES, { + cwd: PACKAGE_ROOT, + type: 'file', + allowSymlinks: true, +}) +const styleConfig = resolvedStyleConfig ? require(resolvedStyleConfig) : {} + module.exports = { - configure, + remove, + add, + projectConfig, + templateConfig, + projectConfigs, + templateConfigs, + packageConfigs, + styleConfig, } diff --git a/src/utils/files.js b/src/utils/files.js old mode 100644 new mode 100755 index ef84804b..a1222750 --- a/src/utils/files.js +++ b/src/utils/files.js @@ -2,7 +2,7 @@ const path = require('path') const log = require('@dhis2/cli-helpers-engine').reporter const fg = require('fast-glob') const fs = require('fs-extra') -const { CONSUMING_ROOT } = require('./paths.js') +const { CONSUMING_ROOT, PACKAGE_ROOT } = require('./paths.js') const { spawn } = require('./run.js') // blacklists for files @@ -93,10 +93,48 @@ function writeFile(fp, content) { } } +function copy(from, to, { overwrite = false, backup = false }) { + try { + const exists = fs.existsSync(to) + const empty = exists ? fs.statSync(to).size === 0 : false + + const replace = empty ? true : overwrite + + fs.ensureDirSync(path.dirname(to)) + + if (exists) { + if (backup) { + const toNew = to.concat('.new') + log.print( + `Existing config, installing as: ${path.relative( + CONSUMING_ROOT, + toNew + )}` + ) + fs.copySync(from, toNew, { overwrite: true }) + return + } + + if (replace) { + log.print(`Installing: ${path.relative(CONSUMING_ROOT, to)}`) + fs.copySync(from, to, { overwrite: true }) + return + } else { + log.print(`Skip existing: ${path.relative(CONSUMING_ROOT, to)}`) + return + } + } else { + fs.copySync(from, to, { overwrite: replace }) + } + } catch (err) { + log.error(`Failed to install configuration file: ${to}`, err) + } +} + function deleteFile(fp) { try { log.debug(`Deleting file: ${fp}`) - fs.unlinkSync(fp) + fs.removeSync(fp) return true } catch (error) { log.error('File deletion failed', fp, error) @@ -112,10 +150,13 @@ function selectFiles(files, pattern, staged) { dot: true, ignore: blacklist.map(b => `**/${b}/**`), absolute: true, + cwd: PACKAGE_ROOT, }) - if (files) { - codeFiles = codeFiles.filter(f => files.includes(f)) + if (files.length > 0) { + codeFiles = files + .filter(f => codeFiles.includes(path.resolve(f))) + .map(f => path.resolve(f)) } if (staged) { @@ -159,7 +200,7 @@ const pickFirstExists = (files = [], customRoot) => { ? path.join(customRoot, file) : path.join(CONSUMING_ROOT, file) - const exists = fs.existsSync(fp) && fs.statSync(fp).size !== 0 + const exists = fileExists(fp) if (exists) { log.debug(`Using ${fp} as the common ignore file.`) @@ -170,11 +211,16 @@ const pickFirstExists = (files = [], customRoot) => { return null } +const fileExists = fp => fs.existsSync(fp) && fs.statSync(fp).size !== 0 + const resolveIgnoreFile = (ignoreFiles = []) => { return pickFirstExists([...ignoreFiles, '.d2styleignore', '.gitignore']) } +const relativePath = fp => path.relative(CONSUMING_ROOT, fp) + module.exports = { + copy, collectFiles, collectAllFiles, collectJsFiles, @@ -191,4 +237,6 @@ module.exports = { blacklist, pickFirstExists, resolveIgnoreFile, + fileExists, + relativePath, } diff --git a/src/utils/groups.js b/src/utils/groups.js deleted file mode 100644 index d872be18..00000000 --- a/src/utils/groups.js +++ /dev/null @@ -1,314 +0,0 @@ -const path = require('path') -const { - BROWSERSLIST_CONFIG, - COMMIT_MSG_HOOK, - ESLINT_CONFIG, - ESLINT_REACT_CONFIG, - PRETTIER_CONFIG, - STALE_CONFIG, - DEPENDABOT_CONFIG, - EDITORCONFIG_CONFIG, - SEMANTIC_PR_CONFIG, - LOCAL_ESLINT_REACT_CONFIG, - LOCAL_PRETTIER_CONFIG, - LOCAL_ESLINT_CONFIG, -} = require('./paths.js') - -/** - * The group definitions for what configuration files can be installed - * with `d2-style` setup. - * - * The format of a selector is: 'identifier/specifier', e.g. - * - * git/hooks - * - * This is represented by a multi-dimensional array: - * - * [ identifier, [ - * [ specifier_one, configuration_files ], - * [ specifier_two, configuration_files ], - * ] - * - * configuration_files is also expected to be an array with the format: - * - * [ bundled_config_file, target_config_file ] - * - * The first slot in the array describes the configuration file which is - * bundled, and the second slot to where the bundled configuration file - * should be installed. - * - */ -const groups = [ - [ - 'linter', - [ - ['eslint', [LOCAL_ESLINT_CONFIG, path.join('.eslintrc.js')]], - [ - 'eslint-react', - [LOCAL_ESLINT_REACT_CONFIG, path.join('.eslintrc.js')], - ], - ], - ], - [ - 'formatter', - [['prettier', [LOCAL_PRETTIER_CONFIG, path.join('.prettierrc.js')]]], - ], - [ - 'git-hooks', - [ - [ - 'commit-msg', - [COMMIT_MSG_HOOK, path.join('.git', 'hooks', 'commit-msg')], - ], - ], - ], - [ - 'github', - [ - [ - 'dependabot', - [DEPENDABOT_CONFIG, path.join('.github', 'dependabot.yml')], - ], - ['probot-stale', [STALE_CONFIG, path.join('.github', 'stale.yml')]], - [ - 'probot-semantic-pull-requests', - [SEMANTIC_PR_CONFIG, path.join('.github', 'semantic.yml')], - ], - ], - ], - [ - 'tools', - [ - ['editorconfig', [EDITORCONFIG_CONFIG, path.join('.editorconfig')]], - [ - 'browserslist', - [BROWSERSLIST_CONFIG, path.join('.browserslistrc')], - ], - ], - ], -] - -/** - * Projects follow a simpler structure, where the selector is assumed to - * always be 'projects', so the 'identifier' is moved up to the same - * level as group in the `groups` definition. - * - * Another difference is that a project just defines the selectors it - * wants to bundle, acting as a short-hand. - */ -const projects = [ - ['base', ['tools/editorconfig', 'git-hooks/commit-msg']], - [ - 'js', - [ - 'tools/all', - 'github/all', - 'linter/eslint', - 'formatter/prettier', - 'git-hooks/commit-msg', - ], - ], - [ - 'react', - [ - 'base/all', - 'github/all', - 'linter/eslint-react', - 'formatter/prettier', - 'git-hooks/commit-msg', - ], - ], -] - -const isValidGroup = selector => { - const [identifier, specifier] = selector.split('/') - - for (const group of groups) { - const groupName = group[0] - const tools = group[1] - - if (groupName === identifier) { - if (specifier === 'all') { - return true - } - - for (const tool of tools) { - const toolName = tool[0] - if (toolName === specifier) { - return true - } - } - } - } - - return false -} - -const isValidProject = selector => { - const [identifier, specifier] = selector.split('/') - - if (identifier === 'project') { - for (const project of projects) { - const projectName = project[0] - if (specifier === projectName) { - return true - } - } - - return false - } -} - -const resolveProjectToGroups = projectName => { - // eslint-disable-next-line no-unused-vars - const [specifier, identifier] = projectName.split('/') - - for (const project of projects) { - if (project[0] === identifier) { - return project[1] - } - } - return [] -} - -const printGroups = () => { - const allGroups = [] - - allGroups.push('Available project templates:') - - for (const project of projects) { - const projectName = project[0] - const projectGroups = project[1] - - allGroups.push( - `* project/${projectName} (includes: ${projectGroups.join(', ')})` - ) - } - - allGroups.push('') - allGroups.push('All available groups:') - - for (const group of groups) { - const groupName = group[0] - const tools = group[1] - - allGroups.push(`* ${groupName}/all`) - - for (const tool of tools) { - const toolName = tool[0] - allGroups.push(`* ${groupName}/${toolName}`) - } - } - - return allGroups.join('\n') -} - -const projectConfigs = identifier => { - for (const project of projects) { - const projectName = project[0] - const projectGroups = project[1] - - if (projectName === identifier) { - return projectGroups - } - } -} - -const expandGroupAll = selector => { - const [specifier, identifier] = selector.split('/') - - for (const group of groups) { - const groupName = group[0] - const tools = group[1] - - if (groupName === specifier) { - if (identifier === 'all') { - return tools.map(tool => `${groupName}/${tool[0]}`) - } - } - } - - return [selector] -} - -const groupConfigs = selector => { - const [specifier, identifier] = selector.split('/') - - const result = new Set() - - for (const group of groups) { - const groupName = group[0] - const tools = group[1] - - if (groupName === specifier) { - if (identifier === 'all') { - tools.map(tool => tool[1]).map(config => result.add(config)) - } - - tools - .filter(tool => tool[0] === identifier) - .map(tool => tool[1]) - .map(config => result.add(config)) - } - } - - return [...result] -} - -/** - * Returns an object which contains the bundled configuration file for - * each tool in cli-style - */ -const bundledConfigPaths = () => { - const config = {} - - for (const selector of groups) { - // eslint-disable-next-line no-unused-vars - const groupName = selector[0] - const tools = selector[1] - - for (const identifier of tools) { - const toolName = identifier[0] - const toolConfigs = identifier[1] - const sourceConfigPath = toolConfigs[0] - - switch (toolName) { - /* Some tools have two configs, e.g. `*.config.js` and `*.local.js`. - * Usually we want the local configuration (see the - * groups array) since that is what we install to the - * local repo, but in this case we need the internal - * configuration file path, so we need to override it - * here. - */ - case 'prettier': - config.prettier = PRETTIER_CONFIG - break - case 'eslint': - config.eslint = ESLINT_CONFIG - break - case 'eslint-react': - config.eslintReact = ESLINT_REACT_CONFIG - config['eslint-react'] = ESLINT_REACT_CONFIG - break - default: - config[toolName] = sourceConfigPath - break - } - } - } - - return config -} - -module.exports = { - groups, - projects, - expandGroupAll, - isValidGroup, - isValidProject, - resolveProjectToGroups, - printGroups, - groupConfigs, - bundledConfigPaths, - projectConfigs, -} diff --git a/src/utils/paths.js b/src/utils/paths.js old mode 100644 new mode 100755 index c499e789..129c0a75 --- a/src/utils/paths.js +++ b/src/utils/paths.js @@ -1,55 +1,42 @@ const path = require('path') +const findup = require('find-up') const CONSUMING_ROOT = path.join(process.cwd()) const PACKAGE_ROOT = path.join(__dirname, '..', '..') -const CONFIG_DIR = path.join(PACKAGE_ROOT, 'config') - -const ESLINT_CONFIG = path.join(CONFIG_DIR, 'js', 'eslint.config.js') -const ESLINT_REACT_CONFIG = path.join( - CONFIG_DIR, - 'js', - 'eslint-react.config.js' -) -const PRETTIER_CONFIG = path.join(CONFIG_DIR, 'js', 'prettier.config.js') -const BROWSERSLIST_CONFIG = path.join( - CONFIG_DIR, - 'js', - 'browserslist.config.rc' +const PROJECT_ROOT = findup.sync( + directory => { + const amiroot = ['.git', '.github', '.d2'].map(i => + findup.sync.exists(path.join(directory, i)) + ) + return amiroot.includes(true) && directory + }, + { + cwd: CONSUMING_ROOT, + type: 'directory', + } ) -const COMMITLINT_CONFIG = path.join(CONFIG_DIR, 'commitlint.config.js') -const EDITORCONFIG_CONFIG = path.join(CONFIG_DIR, 'editorconfig.config.rc') -const DEPENDABOT_CONFIG = path.join(CONFIG_DIR, 'github', 'dependabot.yml') -const STALE_CONFIG = path.join(CONFIG_DIR, 'github', 'stale.yml') -const SEMANTIC_PR_CONFIG = path.join(CONFIG_DIR, 'github', 'semantic.yml') -const COMMIT_MSG_HOOK = path.join(CONFIG_DIR, 'git', 'hooks', 'commit-msg') +const CONFIG_DIR = path.join(PACKAGE_ROOT, 'config') +const TEMPLATE_DIR = path.join(PACKAGE_ROOT, 'templates') -// local configuration files for repositories -const LOCAL_ESLINT_REACT_CONFIG = path.join( - CONFIG_DIR, - 'js', - 'eslint-react.local.js' -) -const LOCAL_ESLINT_CONFIG = path.join(CONFIG_DIR, 'js', 'eslint.local.js') +const PROJECT_CONFIG_DIR = path.join(CONSUMING_ROOT, '.d2') +const PROJECT_HOOKS_DIR = path.join(PROJECT_CONFIG_DIR, 'hooks') -const LOCAL_PRETTIER_CONFIG = path.join(CONFIG_DIR, 'js', 'prettier.local.js') +const STYLE_CONFIG_FILES = [ + path.join('.d2', 'style.config.js'), + path.join('.d2', 'style.js'), + 'd2-style.config.js', + 'd2-style.js', +] module.exports = { CONSUMING_ROOT, - COMMIT_MSG_HOOK, - BROWSERSLIST_CONFIG, - COMMITLINT_CONFIG, PACKAGE_ROOT, CONFIG_DIR, - DEPENDABOT_CONFIG, - EDITORCONFIG_CONFIG, - ESLINT_CONFIG, - ESLINT_REACT_CONFIG, - LOCAL_ESLINT_CONFIG, - LOCAL_ESLINT_REACT_CONFIG, - LOCAL_PRETTIER_CONFIG, - PRETTIER_CONFIG, - SEMANTIC_PR_CONFIG, - STALE_CONFIG, + STYLE_CONFIG_FILES, + PROJECT_CONFIG_DIR, + PROJECT_HOOKS_DIR, + PROJECT_ROOT, + TEMPLATE_DIR, } diff --git a/src/utils/run.js b/src/utils/run.js old mode 100644 new mode 100755 index c1347e03..7dd4a596 --- a/src/utils/run.js +++ b/src/utils/run.js @@ -1,17 +1,20 @@ const path = require('path') +const log = require('@dhis2/cli-helpers-engine').reporter const spawn = require('cross-spawn') const findup = require('find-up') const { PACKAGE_ROOT } = require('./paths.js') -exports.spawn = (cmd, args, opts) => - spawn.sync(cmd, args, { +exports.spawn = (cmd, args, opts) => { + log.debug(cmd, args, opts) + return spawn.sync(cmd, args, { stdio: 'inherit', ...opts, }) +} exports.run = (cmd, { args, opts }, callback) => { return handleRun( - spawn.sync(cmd, args, { + this.spawn(cmd, args, { stdio: 'inherit', ...opts, }), @@ -29,7 +32,7 @@ exports.bin = (cmd, { args, opts }, callback) => { const binCmd = path.join(nodemodules, '.bin', cmd) return handleRun( - spawn.sync(binCmd, args, { + this.spawn(binCmd, args, { stdio: 'inherit', ...opts, }), @@ -37,13 +40,32 @@ exports.bin = (cmd, { args, opts }, callback) => { ) } +exports.callback = () => { + let status = 0 + return result => { + if (!result) return status + + if (result.status > status) { + status = result.status + } + } +} + +exports.exit = (code, msg) => { + console.log('') + if (msg && code > 0) { + log.error(msg) + } + process.exit(code) +} + function handleRun(result, callback) { if (result.error) { throw result.error } if (callback) { - callback(result) + return callback(result) } if (result.status !== 0) { diff --git a/src/utils/std-log-messages.js b/src/utils/std-log-messages.js old mode 100644 new mode 100755 diff --git a/config/editorconfig.config.rc b/templates/editorconfig-base.rc old mode 100644 new mode 100755 similarity index 100% rename from config/editorconfig.config.rc rename to templates/editorconfig-base.rc diff --git a/config/js/eslint.local.js b/templates/eslint-base.js old mode 100644 new mode 100755 similarity index 100% rename from config/js/eslint.local.js rename to templates/eslint-base.js diff --git a/config/js/eslint-react.local.js b/templates/eslint-react.js old mode 100644 new mode 100755 similarity index 100% rename from config/js/eslint-react.local.js rename to templates/eslint-react.js diff --git a/config/github/dependabot.yml b/templates/github-dependabot.yml old mode 100644 new mode 100755 similarity index 100% rename from config/github/dependabot.yml rename to templates/github-dependabot.yml diff --git a/config/github/semantic.yml b/templates/github-semantic.yml old mode 100644 new mode 100755 similarity index 100% rename from config/github/semantic.yml rename to templates/github-semantic.yml diff --git a/config/github/stale.yml b/templates/github-stale.yml old mode 100644 new mode 100755 similarity index 100% rename from config/github/stale.yml rename to templates/github-stale.yml diff --git a/config/js/prettier.local.js b/templates/prettier-base.js old mode 100644 new mode 100755 similarity index 100% rename from config/js/prettier.local.js rename to templates/prettier-base.js diff --git a/tests/configs.js b/tests/configs.js old mode 100644 new mode 100755 diff --git a/tests/group-resolution.js b/tests/group-resolution.js deleted file mode 100644 index 43667abc..00000000 --- a/tests/group-resolution.js +++ /dev/null @@ -1,100 +0,0 @@ -const test = require('tape') -const { - groups, - projects, - isValidGroup, - isValidProject, - resolveProjectToGroups, - expandGroupAll, - bundledConfigPaths, -} = require('../src/utils/groups.js') -const { - BROWSERSLIST_CONFIG, - STALE_CONFIG, - DEPENDABOT_CONFIG, - EDITORCONFIG_CONFIG, - SEMANTIC_PR_CONFIG, - PRETTIER_CONFIG, - ESLINT_CONFIG, -} = require('../src/utils/paths.js') - -function findGroup(identifier) { - const res = [] - for (const group of groups) { - const groupName = group[0] - const tools = group[1] - - if (groupName === identifier) { - for (const tool of tools) { - const toolName = tool[0] - res.push(`${groupName}/${toolName}`) - } - } - } - return res -} - -test('a valid project is accepted', t => { - t.plan(1) - const project = 'project/js' - t.ok(isValidProject(project), `${project} is valid`) -}) - -test('an invalid project will be rejected', t => { - t.plan(1) - const project = 'project/foobar' - t.notOk(isValidProject(project), `${project} is invalid`) -}) - -test('a valid group is accepted', t => { - t.plan(1) - const group = 'formatter/prettier' - t.ok(isValidGroup(group), `${group} is valid`) -}) - -test('an invalid group will be rejected', t => { - t.plan(1) - const group = 'myspecialgroup/foobar' - t.notOk(isValidGroup(group), `${group} is invalid`) -}) - -test('a valid project can be resolved into groups', t => { - t.plan(1) - const project = 'project/js' - const projectGroups = projects[1][1] - const resolvedGroups = resolveProjectToGroups(project) - - t.deepEqual( - projectGroups, - resolvedGroups, - 'resolved groups should match declared project groups' - ) -}) - -test('valid groups can be expanded', t => { - t.plan(1) - - const comboGroup = 'git-hooks/all' - const targetGroups = findGroup('git-hooks') - const expandedGroups = expandGroupAll(comboGroup) - - t.deepEqual( - expandedGroups, - targetGroups, - 'a combo group should expand to the comboed groups' - ) -}) - -test('convert to tool:config object', t => { - t.plan(7) - - const obj = bundledConfigPaths() - - t.equals(obj.eslint, ESLINT_CONFIG) - t.equals(obj.prettier, PRETTIER_CONFIG) - t.equals(obj.dependabot, DEPENDABOT_CONFIG) - t.equals(obj['probot-stale'], STALE_CONFIG) - t.equals(obj['probot-semantic-pull-requests'], SEMANTIC_PR_CONFIG) - t.equals(obj.editorconfig, EDITORCONFIG_CONFIG) - t.equals(obj.browserslist, BROWSERSLIST_CONFIG) -}) diff --git a/tests/main.js b/tests/main.js old mode 100644 new mode 100755 diff --git a/yarn.lock b/yarn.lock old mode 100644 new mode 100755 index cf27217c..463a662f --- a/yarn.lock +++ b/yarn.lock @@ -796,13 +796,13 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== +call-bind@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" + integrity sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w== dependencies: function-bind "^1.1.1" - get-intrinsic "^1.0.2" + get-intrinsic "^1.0.0" callsites@^3.0.0: version "3.1.0" @@ -1499,16 +1499,16 @@ es-abstract@^1.18.0-next.0, es-abstract@^1.18.0-next.1: string.prototype.trimstart "^1.0.1" es-get-iterator@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7" - integrity sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ== + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.1.tgz#b93ddd867af16d5118e00881396533c1c6647ad9" + integrity sha512-qorBw8Y7B15DVLaJWy6WdEV/ZkieBcu6QCq/xzWzGOKJqgG1j754vXRfZ3NY7HSShneqU43mPB4OkQBTkvHhFw== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.0" + call-bind "^1.0.0" + get-intrinsic "^1.0.1" has-symbols "^1.0.1" - is-arguments "^1.1.0" - is-map "^2.0.2" - is-set "^2.0.2" + is-arguments "^1.0.4" + is-map "^2.0.1" + is-set "^2.0.1" is-string "^1.0.5" isarray "^2.0.5" @@ -1581,13 +1581,6 @@ eslint-plugin-import@^2.22.1: resolve "^1.17.0" tsconfig-paths "^3.9.0" -eslint-plugin-prettier@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz#7079cfa2497078905011e6f82e8dd8453d1371b7" - integrity sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ== - dependencies: - prettier-linter-helpers "^1.0.0" - eslint-plugin-react@^7.22.0: version "7.22.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz#3d1c542d1d3169c45421c1215d9470e341707269" @@ -1818,11 +1811,6 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - fast-glob@^3.2.5: version "3.2.5" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.5.tgz#7939af2a656de79a4f1901903ee8adcaa7cb9661" @@ -1970,9 +1958,9 @@ flat-cache@^3.0.4: rimraf "^3.0.2" flatted@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" - integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== + version "3.1.0" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.0.tgz#a5d06b4a8b01e3a63771daa5cb7a1903e2e57067" + integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA== for-each@^0.3.3: version "0.3.3" @@ -2038,7 +2026,7 @@ fs-extra@^8.0.1, fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.0.0, fs-extra@^9.0.1: +fs-extra@^9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" integrity sha512-h2iAoN838FqAFJY2/qVpzFXy+EBxfVE220PalAqQLDVsFOHLJrZvut5puAbCdNv6WJk+B8ihI+k0c7JK5erwqQ== @@ -2048,6 +2036,16 @@ fs-extra@^9.0.0, fs-extra@^9.0.1: jsonfile "^6.0.1" universalify "^1.0.0" +fs-extra@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" + integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== + dependencies: + at-least-node "^1.0.0" + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-minipass@^1.2.5: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" @@ -2093,10 +2091,10 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.1, get-intrinsic@^1.0.2, get-intrinsic@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.0.tgz#892e62931e6938c8a23ea5aaebcfb67bd97da97e" - integrity sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg== +get-intrinsic@^1.0.0, get-intrinsic@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.0.2.tgz#6820da226e50b24894e08859469dc68361545d49" + integrity sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg== dependencies: function-bind "^1.1.1" has "^1.0.3" @@ -2367,6 +2365,11 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" +husky@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/husky/-/husky-5.2.0.tgz#fc5e1c2300d34855d47de4753607d00943fc0802" + integrity sha512-AM8T/auHXRBxlrfPVLKP6jt49GCM2Zz47m8G3FOMsLmTv8Dj/fKVWE0Rh2d4Qrvmy131xEsdQnb3OXRib67PGg== + iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -2467,7 +2470,7 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" -is-arguments@^1.0.4, is-arguments@^1.1.0: +is-arguments@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.0.tgz#62353031dfbee07ceb34656a6bde59efecae8dd9" integrity sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg== @@ -2615,7 +2618,7 @@ is-installed-globally@^0.1.0: global-dirs "^0.1.0" is-path-inside "^1.0.0" -is-map@^2.0.1, is-map@^2.0.2: +is-map@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== @@ -2683,7 +2686,7 @@ is-regex@^1.1.1: dependencies: has-symbols "^1.0.1" -is-set@^2.0.1, is-set@^2.0.2: +is-set@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== @@ -3856,13 +3859,6 @@ prepend-http@^2.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - prettier@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" @@ -4280,9 +4276,9 @@ semver-diff@^2.0.0: semver "^5.0.3" "semver@2 || 3 || 4 || 5", semver@^5.0.3: - version "5.7.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" - integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== semver@7.3.2: version "7.3.2"