From 45f16b6605368c9ff71cd36259645196fcf67fb6 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sat, 14 Sep 2019 23:00:20 -0400 Subject: [PATCH 01/48] feat: kcd -> cod --- .all-contributorsrc | 142 ------------- .eslintignore | 4 + .github/ISSUE_TEMPLATE.md | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 3 +- .npmrc | 1 + .prettierignore | 4 - .prettierrc | 10 - .travis.yml | 16 -- CHANGELOG.md | 5 +- CONTRIBUTING.md | 61 +++--- README.md | 156 ++++++-------- appveyor.yml | 13 -- babel.js | 2 +- config.js | 2 +- eslint.js | 2 +- jest.config.js | 5 +- jest.js | 2 +- other/CODE_OF_CONDUCT.md | 89 -------- other/MAINTAINING.md | 77 ------- other/USERS.md | 18 -- other/manual-releases.md | 49 ----- package.json | 33 +-- prettier.js | 2 +- src/__mocks__/cross-spawn.js | 4 +- src/__tests__/__snapshots__/index.js.snap | 1 - src/__tests__/index.js | 66 +++--- src/__tests__/utils.js | 172 ++++++++-------- src/config/__tests__/lintstagedrc.js | 60 +++--- src/config/__tests__/umbrella.js | 18 +- src/config/babel-transform.js | 4 +- src/config/babelrc.js | 112 +++++------ src/config/eslintignore | 5 +- src/config/eslintrc.js | 15 +- src/config/index.js | 2 +- src/config/jest.config.js | 28 +-- src/config/lintstagedrc.js | 24 ++- src/config/prettierignore | 3 + src/config/prettierrc.js | 9 +- src/config/rollup.config.js | 190 ++++++++---------- src/index.js | 15 +- src/run-script.js | 132 ++++++------ .../__tests__/__snapshots__/format.js.snap | 16 +- .../{precommit.js.snap => pre-commit.js.snap} | 0 .../travis-after-success.js.snap | 32 --- src/scripts/__tests__/format.js | 45 +++-- src/scripts/__tests__/helpers/serializers.js | 20 +- src/scripts/__tests__/lint.js | 55 +++-- .../__tests__/{precommit.js => pre-commit.js} | 48 ++--- src/scripts/__tests__/test.js | 58 +++--- src/scripts/__tests__/travis-after-success.js | 83 -------- src/scripts/__tests__/validate.js | 126 ++++++------ src/scripts/build/babel.js | 59 +++--- src/scripts/build/index.js | 8 +- src/scripts/build/rollup.js | 137 ++++++------- src/scripts/format.js | 56 +++--- src/scripts/lint.js | 49 ++--- src/scripts/pre-commit.js | 32 ++- src/scripts/test.js | 20 +- src/scripts/travis-after-success.js | 57 ------ src/scripts/validate.js | 34 ++-- src/utils.js | 169 ++++++++-------- 61 files changed, 977 insertions(+), 1685 deletions(-) delete mode 100644 .all-contributorsrc create mode 100644 .eslintignore delete mode 100644 .prettierignore delete mode 100644 .prettierrc delete mode 100644 .travis.yml delete mode 100644 appveyor.yml delete mode 100644 other/CODE_OF_CONDUCT.md delete mode 100644 other/MAINTAINING.md delete mode 100644 other/USERS.md delete mode 100644 other/manual-releases.md rename src/scripts/__tests__/__snapshots__/{precommit.js.snap => pre-commit.js.snap} (100%) delete mode 100644 src/scripts/__tests__/__snapshots__/travis-after-success.js.snap rename src/scripts/__tests__/{precommit.js => pre-commit.js} (54%) delete mode 100644 src/scripts/__tests__/travis-after-success.js delete mode 100644 src/scripts/travis-after-success.js diff --git a/.all-contributorsrc b/.all-contributorsrc deleted file mode 100644 index 3d5656a1..00000000 --- a/.all-contributorsrc +++ /dev/null @@ -1,142 +0,0 @@ -{ - "projectName": "kcd-scripts", - "projectOwner": "kentcdodds", - "files": [ - "README.md" - ], - "imageSize": 100, - "commit": false, - "contributors": [ - { - "login": "kentcdodds", - "name": "Kent C. Dodds", - "avatar_url": "https://avatars.githubusercontent.com/u/1500684?v=3", - "profile": "https://kentcdodds.com", - "contributions": [ - "code", - "doc", - "infra", - "test" - ] - }, - { - "login": "sudo-suhas", - "name": "Suhas Karanth", - "avatar_url": "https://avatars2.githubusercontent.com/u/22251956?v=4", - "profile": "https://github.com/sudo-suhas", - "contributions": [ - "code", - "bug", - "test" - ] - }, - { - "login": "pbomb", - "name": "Matt Parrish", - "avatar_url": "https://avatars0.githubusercontent.com/u/1402095?v=4", - "profile": "https://github.com/pbomb", - "contributions": [ - "code", - "test" - ] - }, - { - "login": "mateuscb", - "name": "Mateus", - "avatar_url": "https://avatars3.githubusercontent.com/u/1319157?v=4", - "profile": "https://github.com/mateuscb", - "contributions": [ - "code", - "test" - ] - }, - { - "login": "macklinu", - "name": "Macklin Underdown", - "avatar_url": "https://avatars1.githubusercontent.com/u/2344137?v=4", - "profile": "http://macklin.underdown.me", - "contributions": [ - "code", - "test" - ] - }, - { - "login": "stereobooster", - "name": "stereobooster", - "avatar_url": "https://avatars2.githubusercontent.com/u/179534?v=4", - "profile": "https://github.com/stereobooster", - "contributions": [ - "code", - "test" - ] - }, - { - "login": "donysukardi", - "name": "Dony Sukardi", - "avatar_url": "https://avatars0.githubusercontent.com/u/410792?v=4", - "profile": "http://dsds.io", - "contributions": [ - "bug", - "code" - ] - }, - { - "login": "alexandernanberg", - "name": "Alexander Nanberg", - "avatar_url": "https://avatars3.githubusercontent.com/u/8997319?v=4", - "profile": "https://alexandernanberg.com", - "contributions": [ - "code" - ] - }, - { - "login": "fobbyal", - "name": "Alex Liang", - "avatar_url": "https://avatars2.githubusercontent.com/u/7818365?v=4", - "profile": "https://github.com/fobbyal", - "contributions": [ - "code" - ] - }, - { - "login": "shellthor", - "name": "Jeff Detmer", - "avatar_url": "https://avatars1.githubusercontent.com/u/649578?v=4", - "profile": "http://www.jeffdetmer.com", - "contributions": [ - "code" - ] - }, - { - "login": "alexzherdev", - "name": "Alex Zherdev", - "avatar_url": "https://avatars3.githubusercontent.com/u/93752?v=4", - "profile": "https://twitter.com/endymion_r", - "contributions": [ - "code" - ] - }, - { - "login": "adamdharrington", - "name": "Adam Harrington", - "avatar_url": "https://avatars0.githubusercontent.com/u/5477801?v=4", - "profile": "https://github.com/adamdharrington", - "contributions": [ - "code", - "test" - ] - }, - { - "login": "afontcu", - "name": "AdriΓ  Fontcuberta", - "avatar_url": "https://avatars0.githubusercontent.com/u/9197791?v=4", - "profile": "https://afontcu.dev", - "contributions": [ - "code" - ] - } - ], - "repoType": "github", - "contributorsPerLine": 7, - "repoHost": "https://github.com" -} diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..e848f859 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +node_modules/ +dist/ +coverage/ +package-lock.json diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 8ffaf1ef..290edf53 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -11,7 +11,7 @@ never done that before, that's great! Check this free short video tutorial to learn how: http://kcd.im/pull-request --> -- `kcd-scripts` version: +- `cod-scripts` version: - `node` version: - `npm` (or `yarn`) version: diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ddd7e738..fa9abbee 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -36,6 +36,7 @@ merge of your pull request! - [ ] Documentation - [ ] Tests -- [ ] Ready to be merged +- [ ] Ready to be merged + diff --git a/.npmrc b/.npmrc index a57cc9e5..d2722898 100644 --- a/.npmrc +++ b/.npmrc @@ -1 +1,2 @@ registry=http://registry.npmjs.org/ +package-lock=false diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 30117ea2..00000000 --- a/.prettierignore +++ /dev/null @@ -1,4 +0,0 @@ -package.json -node_modules -dist -coverage diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index fb31ee19..00000000 --- a/.prettierrc +++ /dev/null @@ -1,10 +0,0 @@ -{ - "printWidth": 80, - "tabWidth": 2, - "useTabs": false, - "semi": false, - "singleQuote": true, - "trailingComma": "all", - "bracketSpacing": false, - "jsxBracketSameLine": false -} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e8b4d792..00000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -sudo: false -language: node_js -cache: - directories: - - node_modules -notifications: - email: false -node_js: - - '8' - - '10' - - '12' -script: npm run validate -after_success: node src travis-after-success -branches: - only: - - master diff --git a/CHANGELOG.md b/CHANGELOG.md index 06d221aa..e719b93a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # CHANGELOG -The changelog is automatically updated using [semantic-release](https://github.com/semantic-release/semantic-release). -You can see it on the [releases page](../../releases). +The changelog is automatically updated using +[semantic-release](https://github.com/semantic-release/semantic-release). You can see it on the +[releases page](../../releases). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 63356964..88b0cd6c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,8 +2,8 @@ Thanks for being willing to contribute! -**Working on your first Pull Request?** You can learn how from this _free_ series -[How to Contribute to an Open Source Project on GitHub][egghead] +**Working on your first Pull Request?** You can learn how from this _free_ series [How to Contribute +to an Open Source Project on GitHub][egghead] ## Project setup @@ -12,51 +12,48 @@ Thanks for being willing to contribute! 3. `$ npm run validate` to validate you've got it working 4. Create a branch for your PR -> Tip: Keep your `master` branch pointing at the original repository and make -> pull requests from branches on your fork. To do this, run: +> Tip: Keep your `master` branch pointing at the original repository and make pull requests from +> branches on your fork. To do this, run: > > ``` -> git remote add upstream https://github.com/kentcdodds/kcd-scripts.git +> git remote add upstream https://github.com/codfish/cod-scripts.git > git fetch upstream > git branch --set-upstream-to=upstream/master master > ``` > -> This will add the original repository as a "remote" called "upstream," -> Then fetch the git information from that remote, then set your local `master` -> branch to use the upstream master branch whenever you run `git pull`. -> Then you can make all of your pull request branches based on this `master` -> branch. Whenever you want to update your version of `master`, do a regular +> This will add the original repository as a "remote" called "upstream," Then fetch the git +> information from that remote, then set your local `master` branch to use the upstream master +> branch whenever you run `git pull`. Then you can make all of your pull request branches based on +> this `master` branch. Whenever you want to update your version of `master`, do a regular > `git pull`. ## Committing and Pushing changes -This project uses [`semantic-release`][semantic-release] to do automatic -releases and generate a changelog based on the commit history. So we follow -[a convention][convention] for commit messages. You don't have to follow this -convention if you don't want to. Just know that when we merge your commit, we'll -probably use "Squash and Merge" so we can change the commit message :) +This project uses [`semantic-release`][semantic-release] to do automatic releases and generate a +changelog based on the commit history. So we follow [a convention][convention] for commit messages. +You don't have to follow this convention if you don't want to. Just know that when we merge your +commit, we'll probably use "Squash and Merge" so we can change the commit message :) -Please make sure to run the tests before you commit your changes. You can run -`npm run test:update` which will update any snapshots that need updating. -Make sure to include those changes (if they exist) in your commit. +Please make sure to run the tests before you commit your changes. You can run `npm run test:update` +which will update any snapshots that need updating. Make sure to include those changes (if they +exist) in your commit. ### opt in/out of git hooks -There are git hooks set up with this project that are automatically installed -when you install dependencies. They're really handy, but are turned off by -default (so as to not hinder new contributors). You can opt into these by -creating a file called `.opt-in` at the root of the project and putting this -inside: +There are git hooks set up with this project that are automatically installed when you install +dependencies. They're really handy, but are turned off by default (so as to not hinder new +contributors). You can opt into these by creating a file called `.opt-in` at the root of the project +and putting this inside: ``` pre-commit ``` -One of the things that the git hooks does is automatically format the files you -change. It does this by reformating the entire file and running `git add` on -the file after. This breaks workflows where you're trying to commit portions of -the file only. You can always run your commit with `--no-verify`, but if this -is a bummer to your workflow, you can add an `.opt-out` file with the contents: +One of the things that the git hooks does is automatically format the files you change. It does this +by reformating the entire file and running `git add` on the file after. This breaks workflows where +you're trying to commit portions of the file only. You can always run your commit with +`--no-verify`, but if this is a bummer to your workflow, you can add an `.opt-out` file with the +contents: ``` autoformat @@ -66,10 +63,10 @@ autoformat Please checkout the [the open issues][issues] -Also, please watch the repo and respond to questions/bug reports/feature -requests! Thanks! +Also, please watch the repo and respond to questions/bug reports/feature requests! Thanks! [egghead]: https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github [semantic-release]: https://npmjs.com/package/semantic-release -[convention]: https://github.com/conventional-changelog/conventional-changelog-angular/blob/ed32559941719a130bb0327f886d6a32a8cbc2ba/convention.md -[issues]: https://github.com/kentcdodds/kcd-scripts/issues +[convention]: + https://github.com/conventional-changelog/conventional-changelog-angular/blob/ed32559941719a130bb0327f886d6a32a8cbc2ba/convention.md +[issues]: https://github.com/codfish/cod-scripts/issues diff --git a/README.md b/README.md index a6737b1c..a957faaf 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,28 @@
-

kcd-scripts πŸ› πŸ“¦

+

cod-scripts πŸ› πŸ“¦

CLI toolbox for common scripts for my projects


-[![Build Status][build-badge]][build] -[![Code Coverage][coverage-badge]][coverage] -[![version][version-badge]][package] -[![downloads][downloads-badge]][npmcharts] +[![Build Status][build-badge]][build] [![Code Coverage][coverage-badge]][coverage] +[![version][version-badge]][package] [![downloads][downloads-badge]][npmcharts] [![MIT License][license-badge]][license] -[![All Contributors](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors) -[![PRs Welcome][prs-badge]][prs] -[![Code of Conduct][coc-badge]][coc] +[![PRs Welcome][prs-badge]][prs] [![Code of Conduct][coc-badge]][coc] [![Watch on GitHub][github-watch-badge]][github-watch] -[![Star on GitHub][github-star-badge]][github-star] -[![Tweet][twitter-badge]][twitter] +[![Star on GitHub][github-star-badge]][github-star] [![Tweet][twitter-badge]][twitter] ## The problem -I do a bunch of open source and want to make it easier to maintain so many -projects. +I do a bunch of open source and want to make it easier to maintain so many projects. ## This solution -This is a CLI that abstracts away all configuration for my open source projects -for linting, testing, building, and more. +This is a CLI that abstracts away all configuration for my open source projects for linting, +testing, building, and more. ## Table of Contents @@ -40,49 +34,44 @@ for linting, testing, building, and more. - [Overriding Config](#overriding-config) - [Flow support](#flow-support) - [Inspiration](#inspiration) -- [Other Solutions](#other-solutions) -- [Contributors](#contributors) - [LICENSE](#license) ## Installation -This module is distributed via [npm][npm] which is bundled with [node][node] and -should be installed as one of your project's `devDependencies`: +This module is distributed via [npm][npm] which is bundled with [node][node] and should be installed +as one of your project's `devDependencies`: ``` -npm install --save-dev kcd-scripts +npm install --save-dev cod-scripts ``` ## Usage -This is a CLI and exposes a bin called `kcd-scripts`. I don't really plan on -documenting or testing it super duper well because it's really specific to my -needs. You'll find all available scripts in `src/scripts`. +This is a CLI and exposes a bin called `cod-scripts`. I don't really plan on documenting or testing +it super duper well because it's really specific to my needs. You'll find all available scripts in +`src/scripts`. -This project actually dogfoods itself. If you look in the `package.json`, you'll -find scripts with `node src {scriptName}`. This serves as an example of some -of the things you can do with `kcd-scripts`. +This project actually dogfoods itself. If you look in the `package.json`, you'll find scripts with +`node src {scriptName}`. This serves as an example of some of the things you can do with +`cod-scripts`. ### Overriding Config -Unlike `react-scripts`, `kcd-scripts` allows you to specify your own -configuration for things and have that plug directly into the way things work -with `kcd-scripts`. There are various ways that it works, but basically if you -want to have your own config for something, just add the configuration and -`kcd-scripts` will use that instead of it's own internal config. In addition, -`kcd-scripts` exposes its configuration so you can use it and override only -the parts of the config you need to. +Unlike `react-scripts`, `cod-scripts` allows you to specify your own configuration for things and +have that plug directly into the way things work with `cod-scripts`. There are various ways that it +works, but basically if you want to have your own config for something, just add the configuration +and `cod-scripts` will use that instead of it's own internal config. In addition, `cod-scripts` +exposes its configuration so you can use it and override only the parts of the config you need to. -This can be a very helpful way to make editor integration work for tools like -ESLint which require project-based ESLint configuration to be present to work. +This can be a very helpful way to make editor integration work for tools like ESLint which require +project-based ESLint configuration to be present to work. -So, if we were to do this for ESLint, you could create an `.eslintrc` with the -contents of: +So, if we were to do this for ESLint, you could create an `.eslintrc` with the contents of: ``` -{"extends": "./node_modules/kcd-scripts/eslint.js"} +{"extends": "./node_modules/cod-scripts/eslint.js"} ``` > Note: for now, you'll have to include an `.eslintignore` in your project until @@ -91,13 +80,14 @@ contents of: Or, for `babel`, a `.babelrc` with: ``` -{"presets": ["kcd-scripts/babel"]} +{ "presets": ["cod-scripts/babel"] } ``` Or, for `jest`: -```javascript -const {jest: jestConfig} = require('kcd-scripts/config') +```js +const { jest: jestConfig } = require('cod-scripts/config'); + module.exports = Object.assign(jestConfig, { // your overrides here @@ -105,83 +95,49 @@ module.exports = Object.assign(jestConfig, { transform: { '\\.(ts|tsx)$': '/node_modules/ts-jest/preprocessor.js', }, -}) +}); ``` -> Note: `kcd-scripts` intentionally does not merge things for you when you start -> configuring things to make it less magical and more straightforward. Extending -> can take place on your terms. I think this is actually a great way to do this. +> Note: `cod-scripts` intentionally does not merge things for you when you start configuring things +> to make it less magical and more straightforward. Extending can take place on your terms. I think +> this is actually a great way to do this. ### Flow support -If the `flow-bin` is a dependency on the project the `@babel/preset-flow` will automatically get loaded when you use the default babel config that comes with `kcd-scripts`. If you customised your `.babelrc`-file you might need to manually add `@babel/preset-flow` to the `presets`-section. +If the `flow-bin` is a dependency on the project the `@babel/preset-flow` will automatically get +loaded when you use the default babel config that comes with `cod-scripts`. If you customised your +`.babelrc`-file you might need to manually add `@babel/preset-flow` to the `presets`-section. ## Inspiration This is inspired by `react-scripts`. -## Other Solutions - -I'm not aware of any, if you are please [make a pull request][prs] and add it -here! Again, this is a very specific-to-me solution. - -## Contributors - -Thanks goes to these people ([emoji key][emojis]): - - - - - - - - - - - - - - - - - - - - - -
Kent C. Dodds
Kent C. Dodds

πŸ’» πŸ“– πŸš‡ ⚠️
Suhas Karanth
Suhas Karanth

πŸ’» πŸ› ⚠️
Matt Parrish
Matt Parrish

πŸ’» ⚠️
Mateus
Mateus

πŸ’» ⚠️
Macklin Underdown
Macklin Underdown

πŸ’» ⚠️
stereobooster
stereobooster

πŸ’» ⚠️
Dony Sukardi
Dony Sukardi

πŸ› πŸ’»
Alexander Nanberg
Alexander Nanberg

πŸ’»
Alex Liang
Alex Liang

πŸ’»
Jeff Detmer
Jeff Detmer

πŸ’»
Alex Zherdev
Alex Zherdev

πŸ’»
Adam Harrington
Adam Harrington

πŸ’» ⚠️
AdriΓ  Fontcuberta
AdriΓ  Fontcuberta

πŸ’»
- - - -This project follows the [all-contributors][all-contributors] specification. -Contributions of any kind welcome! - ## LICENSE MIT [npm]: https://www.npmjs.com/ [node]: https://nodejs.org -[build-badge]: https://img.shields.io/travis/kentcdodds/kcd-scripts.svg?style=flat-square -[build]: https://travis-ci.org/kentcdodds/kcd-scripts -[coverage-badge]: https://img.shields.io/codecov/c/github/kentcdodds/kcd-scripts.svg?style=flat-square -[coverage]: https://codecov.io/github/kentcdodds/kcd-scripts -[version-badge]: https://img.shields.io/npm/v/kcd-scripts.svg?style=flat-square -[package]: https://www.npmjs.com/package/kcd-scripts -[downloads-badge]: https://img.shields.io/npm/dm/kcd-scripts.svg?style=flat-square -[npmcharts]: http://npmcharts.com/compare/kcd-scripts -[license-badge]: https://img.shields.io/npm/l/kcd-scripts.svg?style=flat-square -[license]: https://github.com/kentcdodds/kcd-scripts/blob/master/LICENSE +[build-badge]: https://img.shields.io/travis/codfish/cod-scripts.svg?style=flat-square +[build]: https://travis-ci.org/codfish/cod-scripts +[coverage-badge]: https://img.shields.io/codecov/c/github/codfish/cod-scripts.svg?style=flat-square +[coverage]: https://codecov.io/github/codfish/cod-scripts +[version-badge]: https://img.shields.io/npm/v/cod-scripts.svg?style=flat-square +[package]: https://www.npmjs.com/package/cod-scripts +[downloads-badge]: https://img.shields.io/npm/dm/cod-scripts.svg?style=flat-square +[npmcharts]: http://npmcharts.com/compare/cod-scripts +[license-badge]: https://img.shields.io/npm/l/cod-scripts.svg?style=flat-square +[license]: https://github.com/codfish/cod-scripts/blob/master/LICENSE [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square [prs]: http://makeapullrequest.com [donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square [coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square -[coc]: https://github.com/kentcdodds/kcd-scripts/blob/master/other/CODE_OF_CONDUCT.md -[github-watch-badge]: https://img.shields.io/github/watchers/kentcdodds/kcd-scripts.svg?style=social -[github-watch]: https://github.com/kentcdodds/kcd-scripts/watchers -[github-star-badge]: https://img.shields.io/github/stars/kentcdodds/kcd-scripts.svg?style=social -[github-star]: https://github.com/kentcdodds/kcd-scripts/stargazers -[twitter]: https://twitter.com/intent/tweet?text=Check%20out%20kcd-scripts!%20https://github.com/kentcdodds/kcd-scripts%20%F0%9F%91%8D -[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/kentcdodds/kcd-scripts.svg?style=social -[emojis]: https://github.com/kentcdodds/all-contributors#emoji-key -[all-contributors]: https://github.com/kentcdodds/all-contributors +[coc]: https://github.com/codfish/cod-scripts/blob/master/other/CODE_OF_CONDUCT.md +[github-watch-badge]: https://img.shields.io/github/watchers/codfish/cod-scripts.svg?style=social +[github-watch]: https://github.com/codfish/cod-scripts/watchers +[github-star-badge]: https://img.shields.io/github/stars/codfish/cod-scripts.svg?style=social +[github-star]: https://github.com/codfish/cod-scripts/stargazers +[twitter]: + https://twitter.com/intent/tweet?text=Check%20out%20cod-scripts!%20https://github.com/codfish/cod-scripts%20%F0%9F%91%8D +[twitter-badge]: + https://img.shields.io/twitter/url/https/github.com/codfish/cod-scripts.svg?style=social diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 6b490736..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,13 +0,0 @@ -environment: - matrix: - - node_version: "8" -branches: - only: - - master -install: - - ps: Install-Product node $env:node_version - - npm install -test_script: npm run validate -cache: - - ~/.npm -build: off diff --git a/babel.js b/babel.js index f46b0555..953754cd 100644 --- a/babel.js +++ b/babel.js @@ -1 +1 @@ -module.exports = require('./dist/config/babelrc') +module.exports = require('./dist/config/babelrc'); diff --git a/config.js b/config.js index bb07926b..6dc01060 100644 --- a/config.js +++ b/config.js @@ -1 +1 @@ -module.exports = require('./dist/config') +module.exports = require('./dist/config'); diff --git a/eslint.js b/eslint.js index 7cc6ee52..286e06ab 100644 --- a/eslint.js +++ b/eslint.js @@ -1 +1 @@ -module.exports = require('./dist/config/eslintrc') +module.exports = require('./dist/config/eslintrc'); diff --git a/jest.config.js b/jest.config.js index d28e0ab1..f0d8dab1 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,6 @@ -const {jest: jestConfig} = require('./src/config') +const { jest: jestConfig } = require('./src/config'); module.exports = Object.assign(jestConfig, { coverageThreshold: null, -}) + testPathIgnorePatterns: [...jestConfig.testPathIgnorePatterns, './src/scripts/test.js'], +}); diff --git a/jest.js b/jest.js index 3a1bd4e9..70169854 100644 --- a/jest.js +++ b/jest.js @@ -1 +1 @@ -module.exports = require('./dist/config/jest.config') +module.exports = require('./dist/config/jest.config'); diff --git a/other/CODE_OF_CONDUCT.md b/other/CODE_OF_CONDUCT.md deleted file mode 100644 index 89dcd555..00000000 --- a/other/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,89 +0,0 @@ -# Contributor Covenant Code of Conduct - - - - - -**Table of Contents** - -- [Our Pledge](#our-pledge) -- [Our Standards](#our-standards) -- [Our Responsibilities](#our-responsibilities) -- [Scope](#scope) -- [Enforcement](#enforcement) -- [Attribution](#attribution) - - - -## Our Pledge - -In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and -our community a harassment-free experience for everyone, regardless of age, body -size, disability, ethnicity, gender identity and expression, level of experience, -nationality, personal appearance, race, religion, or sexual identity and -orientation. - -## Our Standards - -Examples of behavior that contributes to creating a positive environment -include: - -- Using welcoming and inclusive language -- Being respectful of differing viewpoints and experiences -- Gracefully accepting constructive criticism -- Focusing on what is best for the community -- Showing empathy towards other community members - -Examples of unacceptable behavior by participants include: - -- The use of sexualized language or imagery and unwelcome sexual attention or - advances -- Trolling, insulting/derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or electronic - address, without explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Our Responsibilities - -Project maintainers are responsible for clarifying the standards of acceptable -behavior and are expected to take appropriate and fair corrective action in -response to any instances of unacceptable behavior. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -## Scope - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. Examples of -representing a project or community include using an official project e-mail -address, posting via an official social media account, or acting as an appointed -representative at an online or offline event. Representation of a project may be -further defined and clarified by project maintainers. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting the project team at kent+coc@doddsfamily.us. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. The project team is -obligated to maintain confidentiality with regard to the reporter of an incident. -Further details of specific enforcement policies may be posted separately. - -Project maintainers who do not follow or enforce the Code of Conduct in good -faith may face temporary or permanent repercussions as determined by other -members of the project's leadership. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, -available at [http://contributor-covenant.org/version/1/4][version] - -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/4/ diff --git a/other/MAINTAINING.md b/other/MAINTAINING.md deleted file mode 100644 index cf87aabe..00000000 --- a/other/MAINTAINING.md +++ /dev/null @@ -1,77 +0,0 @@ -# Maintaining - - - - - -**Table of Contents** - -- [Code of Conduct](#code-of-conduct) -- [Issues](#issues) -- [Pull Requests](#pull-requests) -- [Release](#release) -- [Thanks!](#thanks) - - - -This is documentation for maintainers of this project. - -## Code of Conduct - -Please review, understand, and be an example of it. Violations of the code of conduct are -taken seriously, even (especially) for maintainers. - -## Issues - -We want to support and build the community. We do that best by helping people learn to solve -their own problems. We have an issue template and hopefully most folks follow it. If it's -not clear what the issue is, invite them to create a minimal reproduction of what they're trying -to accomplish or the bug they think they've found. - -Once it's determined that a code change is necessary, point people to -[makeapullrequest.com](http://makeapullrequest.com) and invite them to make a pull request. -If they're the one who needs the feature, they're the one who can build it. If they need -some hand holding and you have time to lend a hand, please do so. It's an investment into -another human being, and an investment into a potential maintainer. - -Remember that this is open source, so the code is not yours, it's ours. If someone needs a change -in the codebase, you don't have to make it happen yourself. Commit as much time to the project -as you want/need to. Nobody can ask any more of you than that. - -## Pull Requests - -As a maintainer, you're fine to make your branches on the main repo or on your own fork. Either -way is fine. - -When we receive a pull request, a travis build is kicked off automatically (see the `.travis.yml` -for what runs in the travis build). We avoid merging anything that breaks the travis build. - -Please review PRs and focus on the code rather than the individual. You never know when this is -someone's first ever PR and we want their experience to be as positive as possible, so be -uplifting and constructive. - -When you merge the pull request, 99% of the time you should use the -[Squash and merge](https://help.github.com/articles/merging-a-pull-request/) feature. This keeps -our git history clean, but more importantly, this allows us to make any necessary changes to the -commit message so we release what we want to release. See the next section on Releases for more -about that. - -## Release - -Our releases are automatic. They happen whenever code lands into `master`. A travis build gets -kicked off and if it's successful, a tool called -[`semantic-release`](https://github.com/semantic-release/semantic-release) is used to -automatically publish a new release to npm as well as a changelog to GitHub. It is only able to -determine the version and whether a release is necessary by the git commit messages. With this -in mind, **please brush up on [the commit message convention][commit] which drives our releases.** - -> One important note about this: Please make sure that commit messages do NOT contain the words -> "BREAKING CHANGE" in them unless we want to push a major version. I've been burned by this -> more than once where someone will include "BREAKING CHANGE: None" and it will end up releasing -> a new major version. Not a huge deal honestly, but kind of annoying... - -## Thanks! - -Thank you so much for helping to maintain this project! - -[commit]: https://github.com/conventional-changelog-archived-repos/conventional-changelog-angular/blob/ed32559941719a130bb0327f886d6a32a8cbc2ba/convention.md diff --git a/other/USERS.md b/other/USERS.md deleted file mode 100644 index 85c01cf2..00000000 --- a/other/USERS.md +++ /dev/null @@ -1,18 +0,0 @@ -# Users - - - - - - - -If you or your company uses this project, add your name to this list! Eventually -we may have a website to showcase these (wanna build it!?) - -> No users have been added yet! - - diff --git a/other/manual-releases.md b/other/manual-releases.md deleted file mode 100644 index dadf7d38..00000000 --- a/other/manual-releases.md +++ /dev/null @@ -1,49 +0,0 @@ -# manual-releases - - - - - - - -This project has an automated release set up. So things are only released when there are -useful changes in the code that justify a release. But sometimes things get messed up one way or another -and we need to trigger the release ourselves. When this happens, simply bump the number below and commit -that with the following commit message based on your needs: - -**Major** - -``` -fix(release): manually release a major version - -There was an issue with a major release, so this manual-releases.md -change is to release a new major version. - -Reference: # - -BREAKING CHANGE: -``` - -**Minor** - -``` -feat(release): manually release a minor version - -There was an issue with a minor release, so this manual-releases.md -change is to release a new minor version. - -Reference: # -``` - -**Patch** - -``` -fix(release): manually release a patch version - -There was an issue with a patch release, so this manual-releases.md -change is to release a new patch version. - -Reference: # -``` - -The number of times we've had to do a manual release is: 0 diff --git a/package.json b/package.json index 6dae795b..e8530376 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "kcd-scripts", + "name": "cod-scripts", "version": "0.0.0-semantically-released", "description": "CLI for common scripts for my projects", "engines": { @@ -7,7 +7,7 @@ "npm": ">= 5" }, "bin": { - "kcd-scripts": "dist/index.js" + "cod-scripts": "dist/index.js" }, "scripts": { "test": "node src test", @@ -31,7 +31,7 @@ "jest.js" ], "keywords": [], - "author": "Kent C. Dodds (http://kentcdodds.com/)", + "author": "Chris O'Donnell (http://codfish.io/)", "license": "MIT", "dependencies": { "@babel/cli": "^7.5.5", @@ -56,9 +56,8 @@ "cross-env": "^5.1.4", "cross-spawn": "^6.0.5", "doctoc": "^1.4.0", - "eslint": "^6.1.0", - "eslint-config-kentcdodds": "^14.3.4", - "eslint-config-prettier": "^6.0.0", + "eslint": "^5.15.2", + "eslint-config-codfish": "^2.5.0", "glob": "^7.1.4", "husky": "^3.0.3", "is-ci": "^2.0.0", @@ -69,7 +68,7 @@ "lodash.has": "^4.5.2", "lodash.omit": "^4.5.0", "mkdirp": "^0.5.1", - "prettier": "^1.18.2", + "prettier": "^1.16.4", "read-pkg-up": "^6.0.0", "resolve": "^1.12.0", "rimraf": "^2.6.2", @@ -89,31 +88,21 @@ }, "eslintConfig": { "extends": [ - "kentcdodds", - "kentcdodds/jest" + "./src/config/eslintrc.js" ], "rules": { - "no-process-exit": "off", - "import/no-dynamic-require": "off", - "import/no-unassigned-import": "off", "no-console": "off", - "no-nested-ternary": "off", - "no-useless-catch": "off" + "global-require": "off" } }, - "eslintIgnore": [ - "node_modules", - "coverage", - "dist" - ], "repository": { "type": "git", - "url": "https://github.com/kentcdodds/kcd-scripts.git" + "url": "https://github.com/codfish/cod-scripts.git" }, "bugs": { - "url": "https://github.com/kentcdodds/kcd-scripts/issues" + "url": "https://github.com/codfish/cod-scripts/issues" }, - "homepage": "https://github.com/kentcdodds/kcd-scripts#readme", + "homepage": "https://github.com/codfish/cod-scripts#readme", "devDependencies": { "jest-in-case": "^1.0.2", "slash": "^3.0.0" diff --git a/prettier.js b/prettier.js index de4ba09d..898d0336 100644 --- a/prettier.js +++ b/prettier.js @@ -1 +1 @@ -module.exports = require('./dist/config/prettierrc') +module.exports = require('./dist/config/prettierrc'); diff --git a/src/__mocks__/cross-spawn.js b/src/__mocks__/cross-spawn.js index a16265e8..fcad0923 100644 --- a/src/__mocks__/cross-spawn.js +++ b/src/__mocks__/cross-spawn.js @@ -1,3 +1,3 @@ module.exports = { - sync: jest.fn(() => ({status: 0})), -} + sync: jest.fn(() => ({ status: 0 })), +}; diff --git a/src/__tests__/__snapshots__/index.js.snap b/src/__tests__/__snapshots__/index.js.snap index 5e9e2333..3256635f 100644 --- a/src/__tests__/__snapshots__/index.js.snap +++ b/src/__tests__/__snapshots__/index.js.snap @@ -32,7 +32,6 @@ Available Scripts: lint pre-commit test - travis-after-success validate Options: diff --git a/src/__tests__/index.js b/src/__tests__/index.js index c5af4334..bc28db30 100644 --- a/src/__tests__/index.js +++ b/src/__tests__/index.js @@ -1,58 +1,58 @@ -import path from 'path' -import slash from 'slash' -import cases from 'jest-in-case' -import {unquoteSerializer} from '../scripts/__tests__/helpers/serializers' +import path from 'path'; +import slash from 'slash'; +import cases from 'jest-in-case'; +import { unquoteSerializer } from '../scripts/__tests__/helpers/serializers'; -const projectRoot = path.join(__dirname, '../../') +const projectRoot = path.join(__dirname, '../../'); -expect.addSnapshotSerializer(unquoteSerializer) +expect.addSnapshotSerializer(unquoteSerializer); expect.addSnapshotSerializer({ print: val => slash(val.replace(projectRoot, '/')), test: val => typeof val === 'string' && val.includes(projectRoot), -}) +}); cases( 'format', - ({snapshotLog = false, throws = false, signal = false, args = []}) => { + ({ snapshotLog = false, throws = false, signal = false, args = [] }) => { // beforeEach - const {sync: crossSpawnSyncMock} = require('cross-spawn') - const originalExit = process.exit - const originalArgv = process.argv - const originalLog = console.log - process.exit = jest.fn() - console.log = jest.fn() + const { sync: crossSpawnSyncMock } = require('cross-spawn'); + const originalExit = process.exit; + const originalArgv = process.argv; + const originalLog = console.log; + process.exit = jest.fn(); + console.log = jest.fn(); try { // tests - process.argv = ['node', '../', ...args] - crossSpawnSyncMock.mockClear() + process.argv = ['node', '../', ...args]; + crossSpawnSyncMock.mockClear(); if (signal) { - crossSpawnSyncMock.mockReturnValueOnce({result: 1, signal}) + crossSpawnSyncMock.mockReturnValueOnce({ result: 1, signal }); } - require('../') + require('../'); if (snapshotLog) { - expect(console.log.mock.calls).toMatchSnapshot() + expect(console.log.mock.calls).toMatchSnapshot(); } else if (signal) { - expect(process.exit).toHaveBeenCalledTimes(1) - expect(process.exit).toHaveBeenCalledWith(1) - expect(console.log.mock.calls).toMatchSnapshot() + expect(process.exit).toHaveBeenCalledTimes(1); + expect(process.exit).toHaveBeenCalledWith(1); + expect(console.log.mock.calls).toMatchSnapshot(); } else { - expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1) - const [firstCall] = crossSpawnSyncMock.mock.calls - const [script, calledArgs] = firstCall - expect([script, ...calledArgs].join(' ')).toMatchSnapshot() + expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1); + const [firstCall] = crossSpawnSyncMock.mock.calls; + const [script, calledArgs] = firstCall; + expect([script, ...calledArgs].join(' ')).toMatchSnapshot(); } } catch (error) { if (throws) { - expect(error.message).toMatchSnapshot() + expect(error.message).toMatchSnapshot(); } else { - throw error + throw error; } } finally { // afterEach - process.exit = originalExit - process.argv = originalArgv - console.log = originalLog - jest.resetModules() + process.exit = originalExit; + process.argv = originalArgv; + console.log = originalLog; + jest.resetModules(); } }, { @@ -79,6 +79,6 @@ cases( signal: 'SIGBREAK', }, }, -) +); /* eslint complexity:0 */ diff --git a/src/__tests__/utils.js b/src/__tests__/utils.js index e812bffe..322ed83f 100644 --- a/src/__tests__/utils.js +++ b/src/__tests__/utils.js @@ -1,74 +1,80 @@ jest.mock('read-pkg-up', () => ({ - sync: jest.fn(() => ({package: {}, path: '/blah/package.json'})), -})) -jest.mock('which', () => ({sync: jest.fn(() => {})})) + sync: jest.fn(() => ({ package: {}, path: '/blah/package.json' })), +})); +jest.mock('which', () => ({ sync: jest.fn(() => {}) })); -let whichSyncMock, readPkgUpSyncMock +let whichSyncMock; +let readPkgUpSyncMock; + +function mockPkg({ package: pkg = {}, path = '/blah/package.json' }) { + readPkgUpSyncMock.mockImplementationOnce(() => ({ package: pkg, path })); +} beforeEach(() => { - jest.resetModules() - whichSyncMock = require('which').sync - readPkgUpSyncMock = require('read-pkg-up').sync -}) + jest.resetModules(); + whichSyncMock = require('which').sync; + readPkgUpSyncMock = require('read-pkg-up').sync; +}); test('package is the package.json', () => { - const myPkg = {name: 'blah'} - mockPkg({package: myPkg}) - expect(require('../utils').pkg).toBe(myPkg) -}) + const myPkg = { name: 'blah' }; + mockPkg({ package: myPkg }); + expect(require('../utils').pkg).toBe(myPkg); +}); test('appDirectory is the dirname to the package.json', () => { - const pkgPath = '/some/path/to' - mockPkg({path: `${pkgPath}/package.json`}) - expect(require('../utils').appDirectory).toBe(pkgPath) -}) - -test('resolveKcdScripts resolves to src/index.js when in the kcd-scripts package', () => { - mockPkg({package: {name: 'kcd-scripts'}}) - expect(require('../utils').resolveKcdScripts()).toBe( + const pkgPath = '/some/path/to'; + mockPkg({ path: `${pkgPath}/package.json` }); + expect(require('../utils').appDirectory).toBe(pkgPath); +}); + +test('resolveCodScripts resolves to src/index.js when in the cod-scripts package', () => { + mockPkg({ package: { name: 'cod-scripts' } }); + expect(require('../utils').resolveCodScripts()).toBe( require.resolve('../').replace(process.cwd(), '.'), - ) -}) + ); +}); -test('resolveKcdScripts resolves to kcd-scripts if not in the kcd-scripts package', () => { - mockPkg({package: {name: 'not-kcd-scripts'}}) - whichSyncMock.mockImplementationOnce(() => require.resolve('../')) - expect(require('../utils').resolveKcdScripts()).toBe('kcd-scripts') -}) +test('resolveCodScripts resolves to cod-scripts if not in the cod-scripts package', () => { + mockPkg({ package: { name: 'not-cod-scripts' } }); + whichSyncMock.mockImplementationOnce(() => require.resolve('../')); + expect(require('../utils').resolveCodScripts()).toBe('cod-scripts'); +}); test(`resolveBin resolves to the full path when it's not in $PATH`, () => { expect(require('../utils').resolveBin('cross-env')).toBe( require.resolve('cross-env/dist/bin/cross-env').replace(process.cwd(), '.'), - ) -}) + ); +}); test(`resolveBin resolves to the binary if it's in $PATH`, () => { whichSyncMock.mockImplementationOnce(() => require.resolve('cross-env/dist/bin/cross-env').replace(process.cwd(), '.'), - ) - expect(require('../utils').resolveBin('cross-env')).toBe('cross-env') - expect(whichSyncMock).toHaveBeenCalledTimes(1) - expect(whichSyncMock).toHaveBeenCalledWith('cross-env') -}) + ); + expect(require('../utils').resolveBin('cross-env')).toBe('cross-env'); + expect(whichSyncMock).toHaveBeenCalledTimes(1); + expect(whichSyncMock).toHaveBeenCalledWith('cross-env'); +}); describe('for windows', () => { - let realpathSync + let realpathSync; beforeEach(() => { - jest.doMock('fs', () => ({realpathSync: jest.fn()})) - realpathSync = require('fs').realpathSync - }) + jest.doMock('fs', () => ({ realpathSync: jest.fn() })); + realpathSync = require('fs').realpathSync; // eslint-disable-line + }); + afterEach(() => { - jest.unmock('fs') - }) + jest.unmock('fs'); + }); test('resolveBin resolves to .bin path when which returns a windows-style cmd', () => { - const fullBinPath = '\\project\\node_modules\\.bin\\concurrently.CMD' - realpathSync.mockImplementation(() => fullBinPath) - expect(require('../utils').resolveBin('concurrently')).toBe(fullBinPath) - expect(realpathSync).toHaveBeenCalledTimes(2) - }) -}) + const fullBinPath = '\\project\\node_modules\\.bin\\concurrently.CMD'; + realpathSync.mockImplementation(() => fullBinPath); + expect(require('../utils').resolveBin('concurrently')).toBe(fullBinPath); + expect(realpathSync).toHaveBeenCalledTimes(2); + }); +}); test('getConcurrentlyArgs gives good args to pass to concurrently', () => { expect( @@ -88,55 +94,49 @@ test('getConcurrentlyArgs gives good args to pass to concurrently', () => { i: 'echo i', j: 'echo j', }), - ).toMatchSnapshot() -}) + ).toMatchSnapshot(); +}); test('parseEnv parses the existing environment variable', () => { - const globals = {react: 'React', 'prop-types': 'PropTypes'} - process.env.BUILD_GLOBALS = JSON.stringify(globals) - expect(require('../utils').parseEnv('BUILD_GLOBALS')).toEqual(globals) - delete process.env.BUILD_GLOBALS -}) + const globals = { react: 'React', 'prop-types': 'PropTypes' }; + process.env.BUILD_GLOBALS = JSON.stringify(globals); + expect(require('../utils').parseEnv('BUILD_GLOBALS')).toEqual(globals); + delete process.env.BUILD_GLOBALS; +}); test(`parseEnv returns the default if the environment variable doesn't exist`, () => { - const defaultVal = {hello: 'world'} - expect(require('../utils').parseEnv('DOES_NOT_EXIST', defaultVal)).toBe( - defaultVal, - ) -}) + const defaultVal = { hello: 'world' }; + expect(require('../utils').parseEnv('DOES_NOT_EXIST', defaultVal)).toBe(defaultVal); +}); test('ifAnyDep returns the true argument if true and false argument if false', () => { - mockPkg({package: {peerDependencies: {react: '*'}}}) - const t = {a: 'b'} - const f = {c: 'd'} - expect(require('../utils').ifAnyDep('react', t, f)).toBe(t) - expect(require('../utils').ifAnyDep('preact', t, f)).toBe(f) -}) + mockPkg({ package: { peerDependencies: { react: '*' } } }); + const t = { a: 'b' }; + const f = { c: 'd' }; + expect(require('../utils').ifAnyDep('react', t, f)).toBe(t); + expect(require('../utils').ifAnyDep('preact', t, f)).toBe(f); +}); test('ifAnyDep works with arrays of dependencies', () => { - mockPkg({package: {peerDependencies: {react: '*'}}}) - const t = {a: 'b'} - const f = {c: 'd'} - expect(require('../utils').ifAnyDep(['preact', 'react'], t, f)).toBe(t) - expect(require('../utils').ifAnyDep(['preact', 'webpack'], t, f)).toBe(f) -}) + mockPkg({ package: { peerDependencies: { react: '*' } } }); + const t = { a: 'b' }; + const f = { c: 'd' }; + expect(require('../utils').ifAnyDep(['preact', 'react'], t, f)).toBe(t); + expect(require('../utils').ifAnyDep(['preact', 'webpack'], t, f)).toBe(f); +}); test('ifScript returns the true argument if true and the false argument if false', () => { - mockPkg({package: {scripts: {build: 'echo build'}}}) - const t = {e: 'f'} - const f = {g: 'h'} - expect(require('../utils').ifScript('build', t, f)).toBe(t) - expect(require('../utils').ifScript('lint', t, f)).toBe(f) -}) + mockPkg({ package: { scripts: { build: 'echo build' } } }); + const t = { e: 'f' }; + const f = { g: 'h' }; + expect(require('../utils').ifScript('build', t, f)).toBe(t); + expect(require('../utils').ifScript('lint', t, f)).toBe(f); +}); test('ifFile returns the true argument if true and the false argument if false', () => { - mockPkg({path: require.resolve('../../package.json')}) - const t = {e: 'f'} - const f = {g: 'h'} - expect(require('../utils').ifFile('package.json', t, f)).toBe(t) - expect(require('../utils').ifFile('does-not-exist.blah', t, f)).toBe(f) -}) - -function mockPkg({package: pkg = {}, path = '/blah/package.json'}) { - readPkgUpSyncMock.mockImplementationOnce(() => ({package: pkg, path})) -} + mockPkg({ path: require.resolve('../../package.json') }); + const t = { e: 'f' }; + const f = { g: 'h' }; + expect(require('../utils').ifFile('package.json', t, f)).toBe(t); + expect(require('../utils').ifFile('does-not-exist.blah', t, f)).toBe(f); +}); diff --git a/src/config/__tests__/lintstagedrc.js b/src/config/__tests__/lintstagedrc.js index db4b52a4..25b8ced8 100644 --- a/src/config/__tests__/lintstagedrc.js +++ b/src/config/__tests__/lintstagedrc.js @@ -1,41 +1,39 @@ -import * as utilsMock from '../../utils' +import * as utilsMock from '../../utils'; + +function hasFormat(linter) { + return linter.some(l => l.includes('format')); +} + +function hasGitAdd(linter) { + return linter.includes('git add'); +} + +function getJsLinter(linters) { + const key = Object.keys(linters).find(k => k.includes('*') && k.includes('js')); + return linters[key]; +} jest.mock('../../utils', () => ({ ...require.requireActual('../../utils'), isOptedOut: jest.fn((key, t) => t), -})) +})); afterEach(() => { - jest.resetModules() -}) + jest.resetModules(); +}); test('includes format and git add when not opted out', () => { - utilsMock.isOptedOut.mockImplementation((key, t, f) => f) - const config = require('../lintstagedrc') - const jsLinter = getJsLinter(config) - expect(hasFormat(jsLinter)).toBe(true) - expect(hasGitAdd(jsLinter)).toBe(true) -}) + utilsMock.isOptedOut.mockImplementation((key, t, f) => f); + const config = require('../lintstagedrc'); + const jsLinter = getJsLinter(config); + expect(hasFormat(jsLinter)).toBe(true); + expect(hasGitAdd(jsLinter)).toBe(true); +}); test('does not include format and git add when opted out', () => { - utilsMock.isOptedOut.mockImplementation((key, t) => t) - const config = require('../lintstagedrc') - const jsLinter = getJsLinter(config) - expect(hasFormat(jsLinter)).toBe(false) - expect(hasGitAdd(jsLinter)).toBe(false) -}) - -function hasFormat(linter) { - return linter.some(l => l.includes('format')) -} - -function hasGitAdd(linter) { - return linter.includes('git add') -} - -function getJsLinter(linters) { - const key = Object.keys(linters).find( - k => k.includes('*') && k.includes('js'), - ) - return linters[key] -} + utilsMock.isOptedOut.mockImplementation((key, t) => t); + const config = require('../lintstagedrc'); + const jsLinter = getJsLinter(config); + expect(hasFormat(jsLinter)).toBe(false); + expect(hasGitAdd(jsLinter)).toBe(false); +}); diff --git a/src/config/__tests__/umbrella.js b/src/config/__tests__/umbrella.js index c1e9c065..a104af05 100644 --- a/src/config/__tests__/umbrella.js +++ b/src/config/__tests__/umbrella.js @@ -1,10 +1,10 @@ test('requiring some files does not blow up', () => { - require('../babel-transform') - require('../babelrc') - require('../eslintrc') - require('../jest.config') - require('../lintstagedrc') - require('../prettierrc') - require('../rollup.config') - require('../').getRollupConfig() -}) + require('../babel-transform'); + require('../babelrc'); + require('../eslintrc'); + require('../jest.config'); + require('../lintstagedrc'); + require('../prettierrc'); + require('../rollup.config'); + require('../').getRollupConfig(); +}); diff --git a/src/config/babel-transform.js b/src/config/babel-transform.js index cbda1e7a..f0f1f482 100644 --- a/src/config/babel-transform.js +++ b/src/config/babel-transform.js @@ -1,5 +1,5 @@ -const babelJest = require('babel-jest') +const babelJest = require('babel-jest'); module.exports = babelJest.createTransformer({ presets: [require.resolve('./babelrc')], -}) +}); diff --git a/src/config/babelrc.js b/src/config/babelrc.js index cadbb419..bcfbb2f0 100644 --- a/src/config/babelrc.js +++ b/src/config/babelrc.js @@ -1,97 +1,79 @@ -const browserslist = require('browserslist') -const semver = require('semver') +const browserslist = require('browserslist'); +const semver = require('semver'); -const {ifAnyDep, parseEnv, appDirectory, pkg} = require('../utils') +const { ifAnyDep, parseEnv, appDirectory, pkg } = require('../utils'); -const {BABEL_ENV, NODE_ENV, BUILD_FORMAT} = process.env -const isTest = (BABEL_ENV || NODE_ENV) === 'test' -const isPreact = parseEnv('BUILD_PREACT', false) -const isRollup = parseEnv('BUILD_ROLLUP', false) -const isUMD = BUILD_FORMAT === 'umd' -const isCJS = BUILD_FORMAT === 'cjs' -const isWebpack = parseEnv('BUILD_WEBPACK', false) -const treeshake = parseEnv('BUILD_TREESHAKE', isRollup || isWebpack) -const alias = parseEnv('BUILD_ALIAS', isPreact ? {react: 'preact'} : null) +const { BABEL_ENV, NODE_ENV, BUILD_FORMAT } = process.env; +const isTest = (BABEL_ENV || NODE_ENV) === 'test'; +const isPreact = parseEnv('BUILD_PREACT', false); +const isRollup = parseEnv('BUILD_ROLLUP', false); +const isUMD = BUILD_FORMAT === 'umd'; +const isCJS = BUILD_FORMAT === 'cjs'; +const isWebpack = parseEnv('BUILD_WEBPACK', false); +const treeshake = parseEnv('BUILD_TREESHAKE', isRollup || isWebpack); +const alias = parseEnv('BUILD_ALIAS', isPreact ? { react: 'preact' } : null); -const hasBabelRuntimeDep = Boolean( - pkg.dependencies && pkg.dependencies['@babel/runtime'], -) +const hasBabelRuntimeDep = Boolean(pkg.dependencies && pkg.dependencies['@babel/runtime']); const RUNTIME_HELPERS_WARN = - 'You should add @babel/runtime as dependency to your package. It will allow reusing "babel helpers" from node_modules rather than bundling their copies into your files.' + 'You should add @babel/runtime as dependency to your package. It will allow reusing "babel helpers" from node_modules rather than bundling their copies into your files.'; if (!treeshake && !hasBabelRuntimeDep && !isTest) { - throw new Error(RUNTIME_HELPERS_WARN) + throw new Error(RUNTIME_HELPERS_WARN); } else if (treeshake && !isUMD && !hasBabelRuntimeDep) { - console.warn(RUNTIME_HELPERS_WARN) + console.warn(RUNTIME_HELPERS_WARN); +} + +function getNodeVersion({ engines: { node: nodeVersion = '8' } = {} }) { + const oldestVersion = semver + .validRange(nodeVersion) + .replace(/[>=<|]/g, ' ') + .split(' ') + .filter(Boolean) + .sort(semver.compare)[0]; + if (!oldestVersion) { + throw new Error( + `Unable to determine the oldest version in the range in your package.json at engines.node: "${nodeVersion}". Please attempt to make it less ambiguous.`, + ); + } + return oldestVersion; } /** - * use the strategy declared by browserslist to load browsers configuration. + * Use the strategy declared by browserslist to load browsers configuration. * fallback to the default if don't found custom configuration + * * @see https://github.com/browserslist/browserslist/blob/master/node.js#L139 */ -const browsersConfig = browserslist.loadConfig({path: appDirectory}) || [ - 'ie 10', - 'ios 7', -] +const browsersConfig = browserslist.loadConfig({ path: appDirectory }) || ['ie 10', 'ios 7']; +// eslint-disable-next-line const envTargets = isTest - ? {node: 'current'} + ? { node: 'current' } : isWebpack || isRollup - ? {browsers: browsersConfig} - : {node: getNodeVersion(pkg)} -const envOptions = {modules: false, loose: true, targets: envTargets} + ? { browsers: browsersConfig } + : { node: getNodeVersion(pkg) }; +const envOptions = { modules: false, loose: true, targets: envTargets }; module.exports = () => ({ presets: [ [require.resolve('@babel/preset-env'), envOptions], ifAnyDep( ['react', 'preact'], - [ - require.resolve('@babel/preset-react'), - {pragma: isPreact ? 'React.h' : undefined}, - ], + [require.resolve('@babel/preset-react'), { pragma: isPreact ? 'React.h' : undefined }], ), ifAnyDep(['flow-bin'], [require.resolve('@babel/preset-flow')]), ].filter(Boolean), plugins: [ - [ - require.resolve('@babel/plugin-transform-runtime'), - {useESModules: treeshake && !isCJS}, - ], + [require.resolve('@babel/plugin-transform-runtime'), { useESModules: treeshake && !isCJS }], require.resolve('babel-plugin-macros'), - alias - ? [ - require.resolve('babel-plugin-module-resolver'), - {root: ['./src'], alias}, - ] - : null, + alias ? [require.resolve('babel-plugin-module-resolver'), { root: ['./src'], alias }] : null, [ require.resolve('babel-plugin-transform-react-remove-prop-types'), - isPreact ? {removeImport: true} : {mode: 'unsafe-wrap'}, + isPreact ? { removeImport: true } : { mode: 'unsafe-wrap' }, ], - isUMD - ? require.resolve('babel-plugin-transform-inline-environment-variables') - : null, - [require.resolve('@babel/plugin-proposal-class-properties'), {loose: true}], + isUMD ? require.resolve('babel-plugin-transform-inline-environment-variables') : null, + [require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }], require.resolve('babel-plugin-minify-dead-code-elimination'), - treeshake - ? null - : require.resolve('@babel/plugin-transform-modules-commonjs'), + treeshake ? null : require.resolve('@babel/plugin-transform-modules-commonjs'), ].filter(Boolean), -}) - -function getNodeVersion({engines: {node: nodeVersion = '8'} = {}}) { - const oldestVersion = semver - .validRange(nodeVersion) - .replace(/[>=<|]/g, ' ') - .split(' ') - .filter(Boolean) - .sort(semver.compare)[0] - if (!oldestVersion) { - throw new Error( - `Unable to determine the oldest version in the range in your package.json at engines.node: "${nodeVersion}". Please attempt to make it less ambiguous.`, - ) - } - return oldestVersion -} +}); diff --git a/src/config/eslintignore b/src/config/eslintignore index 5ab667c9..1d8518c4 100644 --- a/src/config/eslintignore +++ b/src/config/eslintignore @@ -1,6 +1,9 @@ node_modules/ -coverage/ dist/ build/ +coverage/ out/ .next/ +docs/ +package-lock.json +serviceWorker.js diff --git a/src/config/eslintrc.js b/src/config/eslintrc.js index 741a3944..2aed3144 100644 --- a/src/config/eslintrc.js +++ b/src/config/eslintrc.js @@ -1,11 +1,8 @@ -const {ifAnyDep} = require('../utils') +const prettierConfig = require('./prettierrc'); module.exports = { - extends: [ - require.resolve('eslint-config-kentcdodds'), - require.resolve('eslint-config-kentcdodds/jest'), - ifAnyDep('react', require.resolve('eslint-config-kentcdodds/jsx-a11y')), - ifAnyDep('react', require.resolve('eslint-config-kentcdodds/react')), - ].filter(Boolean), - rules: {}, -} + extends: [require.resolve('eslint-config-codfish')].filter(Boolean), + rules: { + 'prettier/prettier': ['error', prettierConfig], + }, +}; diff --git a/src/config/index.js b/src/config/index.js index a06d99ac..86fe9ee0 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -5,4 +5,4 @@ module.exports = { lintStaged: require('./lintstagedrc'), prettier: require('./prettierrc'), getRollupConfig: () => require('./rollup.config'), -} +}; diff --git a/src/config/jest.config.js b/src/config/jest.config.js index 5c074d7e..4447eeb7 100644 --- a/src/config/jest.config.js +++ b/src/config/jest.config.js @@ -1,16 +1,12 @@ -const path = require('path') -const {ifAnyDep, hasFile, hasPkgProp, fromRoot} = require('../utils') +const path = require('path'); +const { ifAnyDep, hasFile, hasPkgProp, fromRoot } = require('../utils'); -const here = p => path.join(__dirname, p) +const here = p => path.join(__dirname, p); -const useBuiltInBabelConfig = !hasFile('.babelrc') && !hasPkgProp('babel') +const useBuiltInBabelConfig = + !hasFile('.babelrc') && !hasFile('.babelrc.js') && !hasPkgProp('babel'); -const ignores = [ - '/node_modules/', - '/fixtures/', - '/__tests__/helpers/', - '__mocks__', -] +const ignores = ['/node_modules/', '/fixtures/', '/__tests__/helpers/', '__mocks__']; const jestConfig = { roots: [fromRoot('src')], @@ -18,7 +14,7 @@ const jestConfig = { testURL: 'http://localhost', moduleFileExtensions: ['js', 'jsx', 'json', 'ts', 'tsx'], collectCoverageFrom: ['src/**/*.+(js|jsx|ts|tsx)'], - testMatch: ['**/__tests__/**/*.+(js|jsx|ts|tsx)'], + testMatch: ['**/__tests__/**/*.+(js|jsx|ts|tsx)', '**/?(*.)+(spec|test).[jt]s?(x)'], testPathIgnorePatterns: [...ignores], coveragePathIgnorePatterns: [...ignores, 'src/(umd|cjs|esm)-entry.js$'], transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'], @@ -34,14 +30,18 @@ const jestConfig = { require.resolve('jest-watch-typeahead/filename'), require.resolve('jest-watch-typeahead/testname'), ], +}; + +if (hasFile('setupTests.js')) { + jestConfig.setupFilesAfterEnv = [fromRoot('setupTests.js')]; } if (hasFile('tests/setup-env.js')) { - jestConfig.setupFilesAfterEnv = [fromRoot('tests/setup-env.js')] + jestConfig.setupFilesAfterEnv = [fromRoot('tests/setup-env.js')]; } if (useBuiltInBabelConfig) { - jestConfig.transform = {'^.+\\.js$': here('./babel-transform')} + jestConfig.transform = { '^.+\\.js$': here('./babel-transform') }; } -module.exports = jestConfig +module.exports = jestConfig; diff --git a/src/config/lintstagedrc.js b/src/config/lintstagedrc.js index bd5bdb4f..ba770af7 100644 --- a/src/config/lintstagedrc.js +++ b/src/config/lintstagedrc.js @@ -1,14 +1,22 @@ -const {resolveKcdScripts, resolveBin, isOptedOut} = require('../utils') +const { resolveCodScripts, resolveBin, isOptedOut } = require('../utils'); -const kcdScripts = resolveKcdScripts() -const doctoc = resolveBin('doctoc') +const codScripts = resolveCodScripts(); +const doctoc = resolveBin('doctoc'); module.exports = { 'README.md': [`${doctoc} --maxlevel 3 --notitle`, 'git add'], - '*.+(js|jsx|json|yml|yaml|css|less|scss|ts|tsx|md|graphql|mdx|vue)': [ - isOptedOut('autoformat', null, `${kcdScripts} format`), - `${kcdScripts} lint`, - `${kcdScripts} test --findRelatedTests`, + '*.+(json|yml|yaml|css|less|scss|graphql)': [ + isOptedOut('autoformat', null, `${codScripts} format --no-eslint`), isOptedOut('autoformat', null, 'git add'), ].filter(Boolean), -} + '*.md': [ + isOptedOut('autoformat', null, `${codScripts} format`), + // TODO: add markdownlint + isOptedOut('autoformat', null, 'git add'), + ].filter(Boolean), + '*.js': [ + isOptedOut('autoformat', null, `${codScripts} lint --fix`), + `${codScripts} test --findRelatedTests`, + isOptedOut('autoformat', null, 'git add'), + ].filter(Boolean), +}; diff --git a/src/config/prettierignore b/src/config/prettierignore index 5ab667c9..7bd6773f 100644 --- a/src/config/prettierignore +++ b/src/config/prettierignore @@ -4,3 +4,6 @@ dist/ build/ out/ .next/ +docs/ +package-lock.json +serviceWorker.js diff --git a/src/config/prettierrc.js b/src/config/prettierrc.js index 68703bc5..b61cfc01 100644 --- a/src/config/prettierrc.js +++ b/src/config/prettierrc.js @@ -1,10 +1,11 @@ module.exports = { - printWidth: 80, + printWidth: 100, tabWidth: 2, useTabs: false, - semi: false, + semi: true, singleQuote: true, trailingComma: 'all', - bracketSpacing: false, + bracketSpacing: true, jsxBracketSameLine: false, -} + proseWrap: 'always', +}; diff --git a/src/config/rollup.config.js b/src/config/rollup.config.js index 268b5efe..bdf4b69f 100644 --- a/src/config/rollup.config.js +++ b/src/config/rollup.config.js @@ -1,140 +1,119 @@ -const path = require('path') -const glob = require('glob') -const camelcase = require('lodash.camelcase') -const rollupBabel = require('rollup-plugin-babel') -const commonjs = require('rollup-plugin-commonjs') -const nodeResolve = require('rollup-plugin-node-resolve') -const json = require('rollup-plugin-json') -const replace = require('rollup-plugin-replace') -const {terser} = require('rollup-plugin-terser') -const nodeBuiltIns = require('rollup-plugin-node-builtins') -const nodeGlobals = require('rollup-plugin-node-globals') -const {sizeSnapshot} = require('rollup-plugin-size-snapshot') -const omit = require('lodash.omit') -const { - pkg, - hasFile, - hasPkgProp, - parseEnv, - fromRoot, - uniq, - writeExtraEntry, -} = require('../utils') - -const here = p => path.join(__dirname, p) -const capitalize = s => s[0].toUpperCase() + s.slice(1) - -const minify = parseEnv('BUILD_MINIFY', false) -const format = process.env.BUILD_FORMAT -const isPreact = parseEnv('BUILD_PREACT', false) -const isNode = parseEnv('BUILD_NODE', false) -const name = process.env.BUILD_NAME || capitalize(camelcase(pkg.name)) -const useSizeSnapshot = parseEnv('BUILD_SIZE_SNAPSHOT', false) - -const esm = format === 'esm' -const umd = format === 'umd' - -const defaultGlobals = Object.keys(pkg.peerDependencies || {}).reduce( - (deps, dep) => { - deps[dep] = capitalize(camelcase(dep)) - return deps - }, - {}, -) - -const deps = Object.keys(pkg.dependencies || {}) -const peerDeps = Object.keys(pkg.peerDependencies || {}) -const defaultExternal = umd ? peerDeps : deps.concat(peerDeps) - -const input = glob.sync(fromRoot(process.env.BUILD_INPUT || 'src/index.js')) -const codeSplitting = input.length > 1 - -if ( - codeSplitting && - uniq(input.map(single => path.basename(single))).length !== input.length -) { +const path = require('path'); +const glob = require('glob'); +const camelcase = require('lodash.camelcase'); +const rollupBabel = require('rollup-plugin-babel'); +const commonjs = require('rollup-plugin-commonjs'); +const nodeResolve = require('rollup-plugin-node-resolve'); +const json = require('rollup-plugin-json'); +const replace = require('rollup-plugin-replace'); +const { terser } = require('rollup-plugin-terser'); +const nodeBuiltIns = require('rollup-plugin-node-builtins'); +const nodeGlobals = require('rollup-plugin-node-globals'); +const { sizeSnapshot } = require('rollup-plugin-size-snapshot'); +const omit = require('lodash.omit'); +const { pkg, hasFile, hasPkgProp, parseEnv, fromRoot, uniq, writeExtraEntry } = require('../utils'); + +const here = p => path.join(__dirname, p); +const capitalize = s => s[0].toUpperCase() + s.slice(1); + +const minify = parseEnv('BUILD_MINIFY', false); +const format = process.env.BUILD_FORMAT; +const isPreact = parseEnv('BUILD_PREACT', false); +const isNode = parseEnv('BUILD_NODE', false); +const name = process.env.BUILD_NAME || capitalize(camelcase(pkg.name)); +const useSizeSnapshot = parseEnv('BUILD_SIZE_SNAPSHOT', false); + +const esm = format === 'esm'; +const umd = format === 'umd'; + +const defaultGlobals = Object.keys(pkg.peerDependencies || {}).reduce((deps, dep) => { + return { ...deps, [dep]: capitalize(camelcase(dep)) }; +}, {}); + +const deps = Object.keys(pkg.dependencies || {}); +const peerDeps = Object.keys(pkg.peerDependencies || {}); +const defaultExternal = umd ? peerDeps : deps.concat(peerDeps); + +const input = glob.sync(fromRoot(process.env.BUILD_INPUT || 'src/index.js')); +const codeSplitting = input.length > 1; + +if (codeSplitting && uniq(input.map(single => path.basename(single))).length !== input.length) { throw new Error( 'Filenames of code-splitted entries should be unique to get deterministic output filenames.' + `\nReceived those: ${input}.`, - ) + ); } -const filenameSuffix = process.env.BUILD_FILENAME_SUFFIX || '' -const filenamePrefix = - process.env.BUILD_FILENAME_PREFIX || (isPreact ? 'preact/' : '') +const filenameSuffix = process.env.BUILD_FILENAME_SUFFIX || ''; +const filenamePrefix = process.env.BUILD_FILENAME_PREFIX || (isPreact ? 'preact/' : ''); const globals = parseEnv( 'BUILD_GLOBALS', - isPreact ? Object.assign(defaultGlobals, {preact: 'preact'}) : defaultGlobals, -) + isPreact ? Object.assign(defaultGlobals, { preact: 'preact' }) : defaultGlobals, +); const external = parseEnv( 'BUILD_EXTERNAL', isPreact ? defaultExternal.concat(['preact', 'prop-types']) : defaultExternal, -).filter((e, i, arry) => arry.indexOf(e) === i) +).filter((e, i, arry) => arry.indexOf(e) === i); if (isPreact) { - delete globals.react - delete globals['prop-types'] // TODO: is this necessary? - external.splice(external.indexOf('react'), 1) + delete globals.react; + delete globals['prop-types']; // TODO: is this necessary? + external.splice(external.indexOf('react'), 1); } -const externalPattern = new RegExp(`^(${external.join('|')})($|/)`) +const externalPattern = new RegExp(`^(${external.join('|')})($|/)`); function externalPredicate(id) { - const isDep = external.length > 0 && externalPattern.test(id) + const isDep = external.length > 0 && externalPattern.test(id); if (umd) { // for UMD, we want to bundle all non-peer deps - return isDep + return isDep; } // for esm/cjs we want to make all node_modules external // TODO: support bundledDependencies if someone needs it ever... - const isNodeModule = id.includes('node_modules') - const isRelative = id.startsWith('.') - return isDep || (!isRelative && !path.isAbsolute(id)) || isNodeModule + const isNodeModule = id.includes('node_modules'); + const isRelative = id.startsWith('.'); + return isDep || (!isRelative && !path.isAbsolute(id)) || isNodeModule; } -const filename = [ - pkg.name, - filenameSuffix, - `.${format}`, - minify ? '.min' : null, - '.js', -] +const filename = [pkg.name, filenameSuffix, `.${format}`, minify ? '.min' : null, '.js'] .filter(Boolean) - .join('') + .join(''); -const dirpath = path.join(...[filenamePrefix, 'dist'].filter(Boolean)) +const dirpath = path.join(...[filenamePrefix, 'dist'].filter(Boolean)); const output = [ { name, ...(codeSplitting - ? {dir: path.join(dirpath, format)} - : {file: path.join(dirpath, filename)}), + ? { dir: path.join(dirpath, format) } + : { file: path.join(dirpath, filename) }), format: esm ? 'es' : format, exports: esm ? 'named' : 'auto', globals, }, -] +]; const useBuiltinConfig = !hasFile('.babelrc') && !hasFile('.babelrc.js') && !hasFile('babel.config.js') && - !hasPkgProp('babel') -const babelPresets = useBuiltinConfig ? [here('../config/babelrc.js')] : [] - -const replacements = Object.entries( - umd ? process.env : omit(process.env, ['NODE_ENV']), -).reduce((acc, [key, value]) => { - let val - if (value === 'true' || value === 'false' || Number.isInteger(+value)) { - val = value - } else { - val = JSON.stringify(value) - } - acc[`process.env.${key}`] = val - return acc -}, {}) + !hasPkgProp('babel'); +const babelPresets = useBuiltinConfig ? [here('../config/babelrc.js')] : []; + +const replacements = Object.entries(umd ? process.env : omit(process.env, ['NODE_ENV'])).reduce( + (acc, [key, value]) => { + let val; + if (value === 'true' || value === 'false' || Number.isInteger(+value)) { + val = value; + } else { + val = JSON.stringify(value); + } + acc[`process.env.${key}`] = val; + return acc; + }, + {}, +); module.exports = { input: codeSplitting ? input : input[0], @@ -147,7 +126,7 @@ module.exports = { preferBuiltins: isNode, mainFields: ['module', 'main', 'jsnext', 'browser'], }), - commonjs({include: 'node_modules/**'}), + commonjs({ include: 'node_modules/**' }), json(), rollupBabel({ presets: babelPresets, @@ -155,26 +134,27 @@ module.exports = { runtimeHelpers: useBuiltinConfig, }), replace(replacements), - useSizeSnapshot ? sizeSnapshot({printInfo: false}) : null, + useSizeSnapshot ? sizeSnapshot({ printInfo: false }) : null, minify ? terser() : null, codeSplitting && ((writes = 0) => ({ onwrite() { + // eslint-disable-next-line if (++writes !== input.length) { - return + return; } input .filter(single => single.indexOf('index.js') === -1) .forEach(single => { - const chunk = path.basename(single) + const chunk = path.basename(single); writeExtraEntry(chunk.replace(/\..+$/, ''), { cjs: `${dirpath}/cjs/${chunk}`, esm: `${dirpath}/esm/${chunk}`, - }) - }) + }); + }); }, }))(), ].filter(Boolean), -} +}; diff --git a/src/index.js b/src/index.js index f0880373..dc17c418 100755 --- a/src/index.js +++ b/src/index.js @@ -1,18 +1,21 @@ #!/usr/bin/env node -let shouldThrow + +let shouldThrow; + try { shouldThrow = - require(`${process.cwd()}/package.json`).name === 'kcd-scripts' && - Number(process.version.slice(1).split('.')[0]) < 8 + // eslint-disable-next-line global-require,import/no-dynamic-require + require(`${process.cwd()}/package.json`).name === 'cod-scripts' && + Number(process.version.slice(1).split('.')[0]) < 8; } catch (error) { // ignore } if (shouldThrow) { throw new Error( - 'You must use Node version 8 or greater to run the scripts within kcd-scripts ' + + 'You must use Node version 8 or greater to run the scripts within cod-scripts ' + 'because we dogfood the untranspiled version of the scripts.', - ) + ); } -require('./run-script') +require('./run-script'); diff --git a/src/run-script.js b/src/run-script.js index d23fd17a..de8d5921 100755 --- a/src/run-script.js +++ b/src/run-script.js @@ -1,74 +1,17 @@ -const path = require('path') -const spawn = require('cross-spawn') -const glob = require('glob') +const path = require('path'); +const spawn = require('cross-spawn'); +const glob = require('glob'); -const [executor, ignoredBin, script, ...args] = process.argv - -if (script) { - spawnScript() -} else { - const scriptsPath = path.join(__dirname, 'scripts/') - const scriptsAvailable = glob.sync(path.join(__dirname, 'scripts', '*')) - // `glob.sync` returns paths with unix style path separators even on Windows. - // So we normalize it before attempting to strip out the scripts path. - const scriptsAvailableMessage = scriptsAvailable - .map(path.normalize) - .map(s => - s - .replace(scriptsPath, '') - .replace(/__tests__/, '') - .replace(/\.js$/, ''), - ) - .filter(Boolean) - .join('\n ') - .trim() - const fullMessage = ` -Usage: ${ignoredBin} [script] [--flags] - -Available Scripts: - ${scriptsAvailableMessage} - -Options: - All options depend on the script. Docs will be improved eventually, but for most scripts you can assume that the args you pass will be forwarded to the respective tool that's being run under the hood. - -May the force be with you. - `.trim() - console.log(`\n${fullMessage}\n`) -} +const [executor, ignoredBin, script, ...args] = process.argv; function getEnv() { // this is required to address an issue in cross-spawn // https://github.com/kentcdodds/kcd-scripts/issues/4 return Object.keys(process.env) .filter(key => process.env[key] !== undefined) - .reduce( - (envCopy, key) => { - envCopy[key] = process.env[key] - return envCopy - }, - { - [`SCRIPTS_${script.toUpperCase()}`]: true, - }, - ) -} - -function spawnScript() { - const relativeScriptPath = path.join(__dirname, './scripts', script) - const scriptPath = attemptResolve(relativeScriptPath) - - if (!scriptPath) { - throw new Error(`Unknown script "${script}".`) - } - const result = spawn.sync(executor, [scriptPath, ...args], { - stdio: 'inherit', - env: getEnv(), - }) - - if (result.signal) { - handleSignal(result) - } else { - process.exit(result.status) - } + .reduce((envCopy, key) => ({ ...envCopy, [key]: process.env[key] }), { + [`SCRIPTS_${script.toUpperCase()}`]: true, + }); } function handleSignal(result) { @@ -77,21 +20,72 @@ function handleSignal(result) { `The script "${script}" failed because the process exited too early. ` + 'This probably means the system ran out of memory or someone called ' + '`kill -9` on the process.', - ) + ); } else if (result.signal === 'SIGTERM') { console.log( `The script "${script}" failed because the process exited too early. ` + 'Someone might have called `kill` or `killall`, or the system could ' + 'be shutting down.', - ) + ); } - process.exit(1) + process.exit(1); } function attemptResolve(...resolveArgs) { try { - return require.resolve(...resolveArgs) + return require.resolve(...resolveArgs); } catch (error) { - return null + return null; + } +} + +function spawnScript() { + const relativeScriptPath = path.join(__dirname, './scripts', script); + const scriptPath = attemptResolve(relativeScriptPath); + + if (!scriptPath) { + throw new Error(`Unknown script "${script}".`); + } + const result = spawn.sync(executor, [scriptPath, ...args], { + stdio: 'inherit', + env: getEnv(), + }); + + if (result.signal) { + handleSignal(result); + } else { + process.exit(result.status); } } + +if (script) { + spawnScript(); +} else { + const scriptsPath = path.join(__dirname, 'scripts/'); + const scriptsAvailable = glob.sync(path.join(__dirname, 'scripts', '*')); + // `glob.sync` returns paths with unix style path separators even on Windows. + // So we normalize it before attempting to strip out the scripts path. + const scriptsAvailableMessage = scriptsAvailable + .map(path.normalize) + .map(s => + s + .replace(scriptsPath, '') + .replace(/__tests__/, '') + .replace(/\.js$/, ''), + ) + .filter(Boolean) + .join('\n ') + .trim(); + const fullMessage = ` +Usage: ${ignoredBin} [script] [--flags] + +Available Scripts: + ${scriptsAvailableMessage} + +Options: + All options depend on the script. Docs will be improved eventually, but for most scripts you can assume that the args you pass will be forwarded to the respective tool that's being run under the hood. + +May the force be with you. + `.trim(); + console.log(`\n${fullMessage}\n`); +} diff --git a/src/scripts/__tests__/__snapshots__/format.js.snap b/src/scripts/__tests__/__snapshots__/format.js.snap index e24746ef..4a54fbd0 100644 --- a/src/scripts/__tests__/__snapshots__/format.js.snap +++ b/src/scripts/__tests__/__snapshots__/format.js.snap @@ -1,9 +1,17 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`format --config arg can be used for a custom config 1`] = `prettier --write **/*.+(js|json|less|css|ts|tsx|md) --config ./my-config.js`; +exports[`format --config arg can be used for a custom config 1`] = `prettier --ignore-path ./src/config/prettierignore --write **/*.+(json|less|css|ts|tsx|md) --config ./my-config.js`; -exports[`format --ignore-path arg can be used for a custom ignore file 1`] = `prettier --write **/*.+(js|json|less|css|ts|tsx|md) --ignore-path ./.myignore`; +exports[`format --config arg can be used for a custom config 2`] = `prettier --ignore-path ./src/config/prettierignore --write **/*.+(json|less|css|ts|tsx|md) --config ./my-config.js`; -exports[`format --no-write prevents --write argument from being added 1`] = `prettier **/*.+(js|json|less|css|ts|tsx|md) --no-write`; +exports[`format --ignore-path arg can be used for a custom ignore file 1`] = `prettier --config ./src/config/prettierrc.js --write **/*.+(json|less|css|ts|tsx|md) --ignore-path ./.myignore`; -exports[`format calls prettier CLI with args 1`] = `prettier --write my-src/**/*.js`; +exports[`format --ignore-path arg can be used for a custom ignore file 2`] = `prettier --config ./src/config/prettierrc.js --write **/*.+(json|less|css|ts|tsx|md) --ignore-path ./.myignore`; + +exports[`format --no-write prevents --write argument from being added 1`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore **/*.+(json|less|css|ts|tsx|md) --no-write`; + +exports[`format --no-write prevents --write argument from being added 2`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore **/*.+(json|less|css|ts|tsx|md) --no-write`; + +exports[`format calls prettier CLI with args 1`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore --write my-src/**/*.js`; + +exports[`format calls prettier CLI with args 2`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore --write my-src/**/*.js`; diff --git a/src/scripts/__tests__/__snapshots__/precommit.js.snap b/src/scripts/__tests__/__snapshots__/pre-commit.js.snap similarity index 100% rename from src/scripts/__tests__/__snapshots__/precommit.js.snap rename to src/scripts/__tests__/__snapshots__/pre-commit.js.snap diff --git a/src/scripts/__tests__/__snapshots__/travis-after-success.js.snap b/src/scripts/__tests__/__snapshots__/travis-after-success.js.snap deleted file mode 100644 index 45c0eb21..00000000 --- a/src/scripts/__tests__/__snapshots__/travis-after-success.js.snap +++ /dev/null @@ -1,32 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`travis-after-success calls concurrently with both scripts when on travis 1`] = `npx travis-deploy-once@5`; - -exports[`travis-after-success calls concurrently with both scripts when on travis 2`] = `concurrently --prefix [{name}] --names codecov,release --prefix-colors bgBlue.bold.reset,bgGreen.bold.reset "echo installing codecov && npx -p codecov@3 -c 'echo running codecov && codecov'" "echo installing semantic-release && npx -p semantic-release@15 -c 'echo running semantic-release && semantic-release'"`; - -exports[`travis-after-success does not do autorelease script when running on travis but in a pull request 1`] = `npx travis-deploy-once@5`; - -exports[`travis-after-success does not do autorelease script when running on travis but in a pull request 2`] = `concurrently --prefix [{name}] --names codecov --prefix-colors bgBlue.bold.reset "echo installing codecov && npx -p codecov@3 -c 'echo running codecov && codecov'"`; - -exports[`travis-after-success does not do the autorelease script when the version is different 1`] = `npx travis-deploy-once@5`; - -exports[`travis-after-success does not do the autorelease script when the version is different 2`] = `concurrently --prefix [{name}] --names codecov --prefix-colors bgBlue.bold.reset "echo installing codecov && npx -p codecov@3 -c 'echo running codecov && codecov'"`; - -exports[`travis-after-success does not do the codecov script when opted out 1`] = `npx travis-deploy-once@5`; - -exports[`travis-after-success does not do the codecov script when opted out 2`] = `concurrently --prefix [{name}] --names release --prefix-colors bgBlue.bold.reset "echo installing semantic-release && npx -p semantic-release@15 -c 'echo running semantic-release && semantic-release'"`; - -exports[`travis-after-success does not do the codecov script when there is no coverage directory 1`] = `npx travis-deploy-once@5`; - -exports[`travis-after-success does not do the codecov script when there is no coverage directory 2`] = `concurrently --prefix [{name}] --names release --prefix-colors bgBlue.bold.reset "echo installing semantic-release && npx -p semantic-release@15 -c 'echo running semantic-release && semantic-release'"`; - -exports[`travis-after-success does not run either script when no coverage dir and not the right version 1`] = ` -Array [ - Array [ - installing and running travis-deploy-once, - ], - Array [ - No need to autorelease or report coverage. Skipping travis-after-success script..., - ], -] -`; diff --git a/src/scripts/__tests__/format.js b/src/scripts/__tests__/format.js index ec798516..d796bcae 100644 --- a/src/scripts/__tests__/format.js +++ b/src/scripts/__tests__/format.js @@ -1,32 +1,35 @@ -import cases from 'jest-in-case' -import {unquoteSerializer, winPathSerializer} from './helpers/serializers' +import cases from 'jest-in-case'; +import { unquoteSerializer, winPathSerializer } from './helpers/serializers'; -expect.addSnapshotSerializer(unquoteSerializer) -expect.addSnapshotSerializer(winPathSerializer) +expect.addSnapshotSerializer(unquoteSerializer); +expect.addSnapshotSerializer(winPathSerializer); cases( 'format', - ({args}) => { + ({ args }) => { // beforeEach - const {sync: crossSpawnSyncMock} = require('cross-spawn') - const originalExit = process.exit - const originalArgv = process.argv - const utils = require('../../utils') - utils.resolveBin = (modName, {executable = modName} = {}) => executable - process.exit = jest.fn() + const { sync: crossSpawnSyncMock } = require('cross-spawn'); + const originalExit = process.exit; + const originalArgv = process.argv; + const utils = require('../../utils'); + utils.resolveBin = (modName, { executable = modName } = {}) => executable; + process.exit = jest.fn(); // tests - process.argv = ['node', '../format', ...args] - require('../format') - expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1) - const [firstCall] = crossSpawnSyncMock.mock.calls - const [script, calledArgs] = firstCall - expect([script, ...calledArgs].join(' ')).toMatchSnapshot() + process.argv = ['node', '../format', ...args]; + require('../format'); + expect(crossSpawnSyncMock).toHaveBeenCalledTimes(2); + const [firstCall] = crossSpawnSyncMock.mock.calls; + const [script, calledArgs] = firstCall; + expect([script, ...calledArgs].join(' ')).toMatchSnapshot(); + const [secondCall] = crossSpawnSyncMock.mock.calls; + const [secondScript, secondCalledArgs] = secondCall; + expect([secondScript, ...secondCalledArgs].join(' ')).toMatchSnapshot(); // afterEach - process.exit = originalExit - process.argv = originalArgv - jest.resetModules() + process.exit = originalExit; + process.argv = originalArgv; + jest.resetModules(); }, { 'calls prettier CLI with args': { @@ -42,4 +45,4 @@ cases( args: ['--ignore-path', './.myignore'], }, }, -) +); diff --git a/src/scripts/__tests__/helpers/serializers.js b/src/scripts/__tests__/helpers/serializers.js index 683d9dee..baede0a5 100644 --- a/src/scripts/__tests__/helpers/serializers.js +++ b/src/scripts/__tests__/helpers/serializers.js @@ -1,25 +1,25 @@ -import slash from 'slash' +import slash from 'slash'; // this removes the quotes around strings... export const unquoteSerializer = { print: val => val, test: val => typeof val === 'string', -} +}; // this converts windows style file paths to unix... export const winPathSerializer = { print: val => slash(val), test: val => typeof val === 'string' && val.includes('\\'), -} - -export const relativePathSerializer = { - print: val => normalizePaths(val), - test: val => normalizePaths(val) !== val, -} +}; function normalizePaths(value) { if (typeof value !== 'string') { - return value + return value; } - return slash(value.split(process.cwd()).join('')) + return slash(value.split(process.cwd()).join('')); } + +export const relativePathSerializer = { + print: val => normalizePaths(val), + test: val => normalizePaths(val) !== val, +}; diff --git a/src/scripts/__tests__/lint.js b/src/scripts/__tests__/lint.js index 6f6022e2..c347a605 100644 --- a/src/scripts/__tests__/lint.js +++ b/src/scripts/__tests__/lint.js @@ -1,13 +1,13 @@ -import cases from 'jest-in-case' +import cases from 'jest-in-case'; import { unquoteSerializer, winPathSerializer, relativePathSerializer, -} from './helpers/serializers' +} from './helpers/serializers'; -expect.addSnapshotSerializer(unquoteSerializer) -expect.addSnapshotSerializer(winPathSerializer) -expect.addSnapshotSerializer(relativePathSerializer) +expect.addSnapshotSerializer(unquoteSerializer); +expect.addSnapshotSerializer(winPathSerializer); +expect.addSnapshotSerializer(relativePathSerializer); cases( 'lint', @@ -19,34 +19,34 @@ cases( setup = () => () => {}, }) => { // beforeEach - const {sync: crossSpawnSyncMock} = require('cross-spawn') - const originalArgv = process.argv - const originalExit = process.exit + const { sync: crossSpawnSyncMock } = require('cross-spawn'); + const originalArgv = process.argv; + const originalExit = process.exit; Object.assign(utils, { hasPkgProp, hasFile, - resolveBin: (modName, {executable = modName} = {}) => executable, - }) - process.exit = jest.fn() - const teardown = setup() + resolveBin: (modName, { executable = modName } = {}) => executable, + }); + process.exit = jest.fn(); + const teardown = setup(); - process.argv = ['node', '../lint', ...args] + process.argv = ['node', '../lint', ...args]; try { // tests - require('../lint') - expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1) - const [firstCall] = crossSpawnSyncMock.mock.calls - const [script, calledArgs] = firstCall - expect([script, ...calledArgs].join(' ')).toMatchSnapshot() + require('../lint'); + expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1); + const [firstCall] = crossSpawnSyncMock.mock.calls; + const [script, calledArgs] = firstCall; + expect([script, ...calledArgs].join(' ')).toMatchSnapshot(); } catch (error) { - throw error + throw error; } finally { - teardown() + teardown(); // afterEach - process.exit = originalExit - process.argv = originalArgv - jest.resetModules() + process.exit = originalExit; + process.argv = originalArgv; + jest.resetModules(); } }, { @@ -76,12 +76,7 @@ cases( args: ['--no-cache'], }, 'runs on given files, but only js files': { - args: [ - './src/index.js', - './package.json', - './src/index.css', - './src/component.js', - ], + args: ['./src/index.js', './package.json', './src/index.css', './src/component.js'], }, }, -) +); diff --git a/src/scripts/__tests__/precommit.js b/src/scripts/__tests__/pre-commit.js similarity index 54% rename from src/scripts/__tests__/precommit.js rename to src/scripts/__tests__/pre-commit.js index d6107362..328f48d9 100644 --- a/src/scripts/__tests__/precommit.js +++ b/src/scripts/__tests__/pre-commit.js @@ -1,8 +1,8 @@ -import cases from 'jest-in-case' -import {unquoteSerializer, winPathSerializer} from './helpers/serializers' +import cases from 'jest-in-case'; +import { unquoteSerializer, winPathSerializer } from './helpers/serializers'; -expect.addSnapshotSerializer(unquoteSerializer) -expect.addSnapshotSerializer(winPathSerializer) +expect.addSnapshotSerializer(unquoteSerializer); +expect.addSnapshotSerializer(winPathSerializer); cases( 'pre-commit', @@ -13,35 +13,35 @@ cases( hasFile = () => false, }) => { // beforeEach - const {sync: crossSpawnSyncMock} = require('cross-spawn') - const originalArgv = process.argv - const originalExit = process.exit + const { sync: crossSpawnSyncMock } = require('cross-spawn'); + const originalArgv = process.argv; + const originalExit = process.exit; Object.assign(utils, { hasPkgProp, hasFile, - resolveBin: (modName, {executable = modName} = {}) => executable, - }) - process.exit = jest.fn() + resolveBin: (modName, { executable = modName } = {}) => executable, + }); + process.exit = jest.fn(); - process.argv = ['node', '../pre-commit', ...args] - utils.isOptedIn = optIn => optIn === 'pre-commit' + process.argv = ['node', '../pre-commit', ...args]; + utils.isOptedIn = optIn => optIn === 'pre-commit'; // eslint-disable-line try { // tests - require('../pre-commit') - expect(crossSpawnSyncMock).toHaveBeenCalledTimes(2) - const [firstCall, secondCall] = crossSpawnSyncMock.mock.calls - const [scriptOne, calledArgsOne] = firstCall - expect([scriptOne, ...calledArgsOne].join(' ')).toMatchSnapshot() - const [scriptTwo, calledArgsTwo] = secondCall - expect([scriptTwo, ...calledArgsTwo].join(' ')).toMatchSnapshot() + require('../pre-commit'); + expect(crossSpawnSyncMock).toHaveBeenCalledTimes(2); + const [firstCall, secondCall] = crossSpawnSyncMock.mock.calls; + const [scriptOne, calledArgsOne] = firstCall; + expect([scriptOne, ...calledArgsOne].join(' ')).toMatchSnapshot(); + const [scriptTwo, calledArgsTwo] = secondCall; + expect([scriptTwo, ...calledArgsTwo].join(' ')).toMatchSnapshot(); } catch (error) { - throw error + throw error; } finally { // afterEach - process.exit = originalExit - process.argv = originalArgv - jest.resetModules() + process.exit = originalExit; + process.argv = originalArgv; + jest.resetModules(); } }, { @@ -62,4 +62,4 @@ cases( args: ['--verbose'], }, }, -) +); diff --git a/src/scripts/__tests__/test.js b/src/scripts/__tests__/test.js index 3069a317..c8add504 100644 --- a/src/scripts/__tests__/test.js +++ b/src/scripts/__tests__/test.js @@ -1,12 +1,12 @@ -import cases from 'jest-in-case' -import {unquoteSerializer} from './helpers/serializers' +import cases from 'jest-in-case'; +import { unquoteSerializer } from './helpers/serializers'; -jest.mock('jest', () => ({run: jest.fn()})) -jest.mock('../../config/jest.config', () => ({builtInConfig: true})) -let mockIsCI = false -jest.mock('is-ci', () => mockIsCI) +jest.mock('jest', () => ({ run: jest.fn() })); +jest.mock('../../config/jest.config', () => ({ builtInConfig: true })); +let mockIsCI = false; +jest.mock('is-ci', () => mockIsCI); -expect.addSnapshotSerializer(unquoteSerializer) +expect.addSnapshotSerializer(unquoteSerializer); cases( 'test', @@ -21,37 +21,37 @@ cases( }) => { // beforeEach // eslint-disable-next-line jest/no-jest-import - const {run: jestRunMock} = require('jest') - const originalArgv = process.argv - const prevCI = mockIsCI - const prevPreCommit = process.env['SCRIPTS_PRE-COMMIT'] - mockIsCI = ci - process.env['SCRIPTS_PRE-COMMIT'] = preCommit + const { run: jestRunMock } = require('jest'); + const originalArgv = process.argv; + const prevCI = mockIsCI; + const prevPreCommit = process.env['SCRIPTS_PRE-COMMIT']; + mockIsCI = ci; + process.env['SCRIPTS_PRE-COMMIT'] = preCommit; Object.assign(utils, { hasPkgProp: () => pkgHasJestProp, hasFile: () => hasJestConfigFile, - }) - process.exit = jest.fn() - const teardown = setup() + }); + process.exit = jest.fn(); + const teardown = setup(); - process.argv = ['node', '../test', ...args] + process.argv = ['node', '../test', ...args]; try { // tests - require('../test') - expect(jestRunMock).toHaveBeenCalledTimes(1) - const [firstCall] = jestRunMock.mock.calls - const [jestArgs] = firstCall - expect(jestArgs.join(' ')).toMatchSnapshot() + require('../test'); + expect(jestRunMock).toHaveBeenCalledTimes(1); + const [firstCall] = jestRunMock.mock.calls; + const [jestArgs] = firstCall; + expect(jestArgs.join(' ')).toMatchSnapshot(); } catch (error) { - throw error + throw error; } finally { - teardown() + teardown(); // afterEach - process.argv = originalArgv - mockIsCI = prevCI - process.env['SCRIPTS_PRE-COMMIT'] = prevPreCommit - jest.resetModules() + process.argv = originalArgv; + mockIsCI = prevCI; + process.env['SCRIPTS_PRE-COMMIT'] = prevPreCommit; + jest.resetModules(); } }, { @@ -84,4 +84,4 @@ cases( args: ['--coverage', '--watch'], }, }, -) +); diff --git a/src/scripts/__tests__/travis-after-success.js b/src/scripts/__tests__/travis-after-success.js deleted file mode 100644 index fecd5569..00000000 --- a/src/scripts/__tests__/travis-after-success.js +++ /dev/null @@ -1,83 +0,0 @@ -import cases from 'jest-in-case' -import {unquoteSerializer} from './helpers/serializers' - -expect.addSnapshotSerializer(unquoteSerializer) - -cases( - 'travis-after-success', - ({ - version = '0.0.0-semantically-released', - hasCoverageDir = true, - isOptedOutOfCoverage = false, - env = { - TRAVIS: 'true', - TRAVIS_BRANCH: 'master', - TRAVIS_PULL_REQUEST: 'false', - }, - runsNothing = false, - }) => { - // beforeEach - const {sync: crossSpawnSyncMock} = require('cross-spawn') - const utils = require('../../utils') - utils.resolveBin = (modName, {executable = modName} = {}) => executable - const originalEnvs = Object.keys(env).map(envKey => { - const orig = process.env[envKey] - process.env[envKey] = env[envKey] - return orig - }) - const originalLog = console.log - const originalExit = process.exit - process.exit = jest.fn() - console.log = jest.fn() - - // tests - if (version) { - utils.pkg.version = version - } - utils.hasFile = () => hasCoverageDir - process.env.SKIP_CODECOV = isOptedOutOfCoverage - require('../travis-after-success') - if (runsNothing) { - expect(console.log.mock.calls).toMatchSnapshot() - } else { - expect(crossSpawnSyncMock).toHaveBeenCalledTimes(2) - const [firstCall, secondCall] = crossSpawnSyncMock.mock.calls - const [scriptOne, calledArgsOne] = firstCall - expect([scriptOne, ...calledArgsOne].join(' ')).toMatchSnapshot() - const [scriptTwo, calledArgsTwo] = secondCall - expect([scriptTwo, ...calledArgsTwo].join(' ')).toMatchSnapshot() - } - - // afterEach - process.exit = originalExit - console.log = originalLog - Object.keys(originalEnvs).forEach(envKey => { - process.env[envKey] = env[envKey] - }) - jest.resetModules() - }, - { - 'calls concurrently with both scripts when on travis': {}, - 'does not do the autorelease script when the version is different': { - version: '1.2.3', - }, - 'does not do the codecov script when there is no coverage directory': { - hasCoverageDir: false, - }, - 'does not do the codecov script when opted out': { - isOptedOutOfCoverage: true, - }, - 'does not do autorelease script when running on travis but in a pull request': { - env: { - TRAVIS: 'true', - TRAVIS_BRANCH: 'master', - TRAVIS_PULL_REQUEST: 'true', - }, - }, - 'does not run either script when no coverage dir and not the right version': { - runsNothing: true, - hasCoverageDir: false, - version: '1.2.3', - }, - }, -) diff --git a/src/scripts/__tests__/validate.js b/src/scripts/__tests__/validate.js index f5435fe5..52727382 100644 --- a/src/scripts/__tests__/validate.js +++ b/src/scripts/__tests__/validate.js @@ -1,34 +1,74 @@ -import cases from 'jest-in-case' -import {unquoteSerializer} from './helpers/serializers' +import cases from 'jest-in-case'; +import { unquoteSerializer } from './helpers/serializers'; -expect.addSnapshotSerializer(unquoteSerializer) +expect.addSnapshotSerializer(unquoteSerializer); + +function setupWithScripts(scripts = ['test', 'lint', 'build', 'flow']) { + return function setup() { + const utils = require('../../utils'); + const originalIfScript = utils.ifScript; + utils.ifScript = (script, t, f) => (scripts.includes(script) ? t : f); + return function teardown() { + utils.ifScript = originalIfScript; + }; + }; +} + +function setupWithArgs(args = []) { + return function setup() { + const utils = require('../../utils'); + const originalResolveBin = utils.resolveBin; + utils.resolveBin = (modName, { executable = modName } = {}) => executable; + const originalArgv = process.argv; + process.argv = ['node', '../format', ...args]; + return function teardown() { + process.argv = originalArgv; + utils.resolveBin = originalResolveBin; + }; + }; +} + +function withDefaultSetup(setupFn) { + return function defaultSetup() { + const utils = require('../../utils'); + utils.resolveBin = (modName, { executable = modName } = {}) => executable; + const argsTeardown = setupWithArgs()(); + const teardownScripts = setupWithScripts()(); + const teardownFn = setupFn(); + return function defaultTeardown() { + argsTeardown(); + teardownFn(); + teardownScripts(); + }; + }; +} cases( 'validate', - ({setup = () => () => {}}) => { + ({ setup = () => () => {} }) => { // beforeEach - const {sync: crossSpawnSyncMock} = require('cross-spawn') - const originalExit = process.exit - process.exit = jest.fn() - process.env['SCRIPTS_PRE-COMMIT'] = 'false' - const teardown = setup() + const { sync: crossSpawnSyncMock } = require('cross-spawn'); + const originalExit = process.exit; + process.exit = jest.fn(); + process.env['SCRIPTS_PRE-COMMIT'] = 'false'; + const teardown = setup(); try { // tests - require('../validate') - expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1) - const [firstCall] = crossSpawnSyncMock.mock.calls - const [script, calledArgs] = firstCall - expect([script, ...calledArgs].join(' ')).toMatchSnapshot() + require('../validate'); + expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1); + const [firstCall] = crossSpawnSyncMock.mock.calls; + const [script, calledArgs] = firstCall; + expect([script, ...calledArgs].join(' ')).toMatchSnapshot(); } catch (error) { - throw error + throw error; } finally { - teardown() + teardown(); } // afterEach - process.exit = originalExit - jest.resetModules() + process.exit = originalExit; + jest.resetModules(); }, { 'calls concurrently with all scripts': { @@ -51,52 +91,12 @@ cases( }, [`doesn't use test or lint if it's in pre-commit`]: { setup: withDefaultSetup(() => { - const previousVal = process.env['SCRIPTS_PRE-COMMIT'] - process.env['SCRIPTS_PRE-COMMIT'] = 'true' + const previousVal = process.env['SCRIPTS_PRE-COMMIT']; + process.env['SCRIPTS_PRE-COMMIT'] = 'true'; return function teardown() { - process.env['SCRIPTS_PRE-COMMIT'] = previousVal - } + process.env['SCRIPTS_PRE-COMMIT'] = previousVal; + }; }), }, }, -) - -function setupWithScripts(scripts = ['test', 'lint', 'build', 'flow']) { - return function setup() { - const utils = require('../../utils') - const originalIfScript = utils.ifScript - utils.ifScript = (script, t, f) => (scripts.includes(script) ? t : f) - return function teardown() { - utils.ifScript = originalIfScript - } - } -} - -function setupWithArgs(args = []) { - return function setup() { - const utils = require('../../utils') - const originalResolveBin = utils.resolveBin - utils.resolveBin = (modName, {executable = modName} = {}) => executable - const originalArgv = process.argv - process.argv = ['node', '../format', ...args] - return function teardown() { - process.argv = originalArgv - utils.resolveBin = originalResolveBin - } - } -} - -function withDefaultSetup(setupFn) { - return function defaultSetup() { - const utils = require('../../utils') - utils.resolveBin = (modName, {executable = modName} = {}) => executable - const argsTeardown = setupWithArgs()() - const teardownScripts = setupWithScripts()() - const teardownFn = setupFn() - return function defaultTeardown() { - argsTeardown() - teardownFn() - teardownScripts() - } - } -} +); diff --git a/src/scripts/build/babel.js b/src/scripts/build/babel.js index 40249d9d..179da1a3 100644 --- a/src/scripts/build/babel.js +++ b/src/scripts/build/babel.js @@ -1,56 +1,51 @@ -const path = require('path') -const spawn = require('cross-spawn') -const yargsParser = require('yargs-parser') -const rimraf = require('rimraf') -const glob = require('glob') -const {hasPkgProp, fromRoot, resolveBin, hasFile} = require('../../utils') +const path = require('path'); +const spawn = require('cross-spawn'); +const yargsParser = require('yargs-parser'); +const rimraf = require('rimraf'); +const glob = require('glob'); +const { hasPkgProp, fromRoot, resolveBin, hasFile } = require('../../utils'); -const args = process.argv.slice(2) -const here = p => path.join(__dirname, p) +const args = process.argv.slice(2); +const here = p => path.join(__dirname, p); -const parsedArgs = yargsParser(args) +const parsedArgs = yargsParser(args); const useBuiltinConfig = !args.includes('--presets') && !hasFile('.babelrc') && !hasFile('.babelrc.js') && !hasFile('babel.config.js') && - !hasPkgProp('babel') -const config = useBuiltinConfig - ? ['--presets', here('../../config/babelrc.js')] - : [] + !hasPkgProp('babel'); +const config = useBuiltinConfig ? ['--presets', here('../../config/babelrc.js')] : []; -const builtInIgnore = '**/__tests__/**,**/__mocks__/**' +const builtInIgnore = '**/__tests__/**,**/__mocks__/**'; -const ignore = args.includes('--ignore') ? [] : ['--ignore', builtInIgnore] +const ignore = args.includes('--ignore') ? [] : ['--ignore', builtInIgnore]; -const copyFiles = args.includes('--no-copy-files') ? [] : ['--copy-files'] +const copyFiles = args.includes('--no-copy-files') ? [] : ['--copy-files']; -const useSpecifiedOutDir = args.includes('--out-dir') -const builtInOutDir = 'dist' -const outDir = useSpecifiedOutDir ? [] : ['--out-dir', builtInOutDir] +const useSpecifiedOutDir = args.includes('--out-dir') || args.includes('-d'); +const builtInOutDir = 'dist'; +const outDir = useSpecifiedOutDir ? [] : ['--out-dir', builtInOutDir]; if (!useSpecifiedOutDir && !args.includes('--no-clean')) { - rimraf.sync(fromRoot('dist')) + rimraf.sync(fromRoot('dist')); } const result = spawn.sync( - resolveBin('@babel/cli', {executable: 'babel'}), + resolveBin('@babel/cli', { executable: 'babel' }), [...outDir, ...copyFiles, ...ignore, ...config, 'src'].concat(args), - {stdio: 'inherit'}, -) + { stdio: 'inherit' }, +); // because babel will copy even ignored files, we need to remove the ignored files -const pathToOutDir = fromRoot(parsedArgs.outDir || builtInOutDir) +const pathToOutDir = fromRoot(parsedArgs.outDir || builtInOutDir); const ignoredPatterns = (parsedArgs.ignore || builtInIgnore) .split(',') - .map(pattern => path.join(pathToOutDir, pattern)) -const ignoredFiles = ignoredPatterns.reduce( - (all, pattern) => [...all, ...glob.sync(pattern)], - [], -) + .map(pattern => path.join(pathToOutDir, pattern)); +const ignoredFiles = ignoredPatterns.reduce((all, pattern) => [...all, ...glob.sync(pattern)], []); ignoredFiles.forEach(ignoredFile => { - rimraf.sync(ignoredFile) -}) + rimraf.sync(ignoredFile); +}); -process.exit(result.status) +process.exit(result.status); diff --git a/src/scripts/build/index.js b/src/scripts/build/index.js index 9b96498f..f3f380db 100644 --- a/src/scripts/build/index.js +++ b/src/scripts/build/index.js @@ -1,9 +1,9 @@ if (process.argv.includes('--browser')) { - console.error('--browser has been deprecated, use --bundle instead') + console.error('--browser has been deprecated, use --bundle instead'); } -if (process.argv.includes('--bundle') || process.argv.includes('--browser')) { - require('./rollup') +if (process.argv.includes('--bundle')) { + require('./rollup'); } else { - require('./babel') + require('./babel'); } diff --git a/src/scripts/build/rollup.js b/src/scripts/build/rollup.js index 62269b34..29617dcb 100644 --- a/src/scripts/build/rollup.js +++ b/src/scripts/build/rollup.js @@ -1,68 +1,101 @@ -const path = require('path') -const spawn = require('cross-spawn') -const glob = require('glob') -const rimraf = require('rimraf') -const yargsParser = require('yargs-parser') +const path = require('path'); +const spawn = require('cross-spawn'); +const glob = require('glob'); +const rimraf = require('rimraf'); +const yargsParser = require('yargs-parser'); const { hasFile, resolveBin, fromRoot, getConcurrentlyArgs, writeExtraEntry, -} = require('../../utils') +} = require('../../utils'); -const crossEnv = resolveBin('cross-env') -const rollup = resolveBin('rollup') -const args = process.argv.slice(2) -const here = p => path.join(__dirname, p) -const hereRelative = p => here(p).replace(process.cwd(), '.') -const parsedArgs = yargsParser(args) +const crossEnv = resolveBin('cross-env'); +const rollup = resolveBin('rollup'); +const args = process.argv.slice(2); +const here = p => path.join(__dirname, p); +const hereRelative = p => here(p).replace(process.cwd(), '.'); +const parsedArgs = yargsParser(args); -const useBuiltinConfig = - !args.includes('--config') && !hasFile('rollup.config.js') +const useBuiltinConfig = !args.includes('--config') && !hasFile('rollup.config.js'); +// eslint-disable-next-line const config = useBuiltinConfig ? `--config ${hereRelative('../../config/rollup.config.js')}` : args.includes('--config') ? '' - : '--config' // --config will pick up the rollup.config.js file + : '--config'; // --config will pick up the rollup.config.js file -const environment = parsedArgs.environment - ? `--environment ${parsedArgs.environment}` - : '' -const watch = parsedArgs.watch ? '--watch' : '' -const sizeSnapshot = parsedArgs['size-snapshot'] +const environment = parsedArgs.environment ? `--environment ${parsedArgs.environment}` : ''; +const watch = parsedArgs.watch ? '--watch' : ''; +const sizeSnapshot = parsedArgs['size-snapshot']; -let formats = ['esm', 'cjs', 'umd', 'umd.min'] +let formats = ['esm', 'cjs', 'umd', 'umd.min']; if (typeof parsedArgs.bundle === 'string') { - formats = parsedArgs.bundle.split(',') + formats = parsedArgs.bundle.split(','); } -const defaultEnv = 'BUILD_ROLLUP=true' +const defaultEnv = 'BUILD_ROLLUP=true'; + +function prefixKeys(prefix, object) { + return Object.entries(object).reduce((cmds, [key, value]) => { + return { ...cmds, [`${prefix}${key}`]: value }; + }, {}); +} const getCommand = (env, ...flags) => [crossEnv, defaultEnv, env, rollup, config, environment, watch, ...flags] .filter(Boolean) - .join(' ') + .join(' '); + +function getCommands({ preact = false } = {}) { + return formats.reduce((cmds, format) => { + const [formatName, minify = false] = format.split('.'); + const nodeEnv = minify ? 'production' : 'development'; + const sourceMap = formatName === 'umd' ? '--sourcemap' : ''; + const buildMinify = Boolean(minify); + + return { + ...cmds, + [format]: getCommand( + [ + `BUILD_FORMAT=${formatName}`, + `BUILD_MINIFY=${buildMinify}`, + `NODE_ENV=${nodeEnv}`, + `BUILD_PREACT=${preact}`, + `BUILD_SIZE_SNAPSHOT=${sizeSnapshot}`, + `BUILD_NODE=${process.env.BUILD_NODE || false}`, + `BUILD_REACT_NATIVE=${process.env.BUILD_REACT_NATIVE || false}`, + ].join(' '), + sourceMap, + ), + }; + }, {}); +} + +function getPReactScripts() { + const reactCommands = prefixKeys('react.', getCommands()); + const preactCommands = prefixKeys('preact.', getCommands({ preact: true })); + return getConcurrentlyArgs(Object.assign(reactCommands, preactCommands)); +} -const buildPreact = args.includes('--p-react') -const scripts = buildPreact - ? getPReactScripts() - : getConcurrentlyArgs(getCommands()) +const buildPreact = args.includes('--p-react'); +const scripts = buildPreact ? getPReactScripts() : getConcurrentlyArgs(getCommands()); -const cleanBuildDirs = !args.includes('--no-clean') +const cleanBuildDirs = !args.includes('--no-clean'); if (cleanBuildDirs) { - rimraf.sync(fromRoot('dist')) + rimraf.sync(fromRoot('dist')); if (buildPreact) { - rimraf.sync(fromRoot('preact')) + rimraf.sync(fromRoot('preact')); } } const result = spawn.sync(resolveBin('concurrently'), scripts, { stdio: 'inherit', -}) +}); if (result.status === 0 && buildPreact && !args.includes('--no-package-json')) { writeExtraEntry( @@ -72,43 +105,7 @@ if (result.status === 0 && buildPreact && !args.includes('--no-package-json')) { esm: glob.sync(fromRoot('preact/**/*.esm.js'))[0], }, false, - ) -} - -function getPReactScripts() { - const reactCommands = prefixKeys('react.', getCommands()) - const preactCommands = prefixKeys('preact.', getCommands({preact: true})) - return getConcurrentlyArgs(Object.assign(reactCommands, preactCommands)) -} - -function prefixKeys(prefix, object) { - return Object.entries(object).reduce((cmds, [key, value]) => { - cmds[`${prefix}${key}`] = value - return cmds - }, {}) -} - -function getCommands({preact = false} = {}) { - return formats.reduce((cmds, format) => { - const [formatName, minify = false] = format.split('.') - const nodeEnv = minify ? 'production' : 'development' - const sourceMap = formatName === 'umd' ? '--sourcemap' : '' - const buildMinify = Boolean(minify) - - cmds[format] = getCommand( - [ - `BUILD_FORMAT=${formatName}`, - `BUILD_MINIFY=${buildMinify}`, - `NODE_ENV=${nodeEnv}`, - `BUILD_PREACT=${preact}`, - `BUILD_SIZE_SNAPSHOT=${sizeSnapshot}`, - `BUILD_NODE=${process.env.BUILD_NODE || false}`, - `BUILD_REACT_NATIVE=${process.env.BUILD_REACT_NATIVE || false}`, - ].join(' '), - sourceMap, - ) - return cmds - }, {}) + ); } -process.exit(result.status) +process.exit(result.status); diff --git a/src/scripts/format.js b/src/scripts/format.js index 94b804ad..2bd04cf1 100644 --- a/src/scripts/format.js +++ b/src/scripts/format.js @@ -1,44 +1,46 @@ -const path = require('path') -const spawn = require('cross-spawn') -const yargsParser = require('yargs-parser') -const {hasPkgProp, resolveBin, hasFile} = require('../utils') +const path = require('path'); +const spawn = require('cross-spawn'); +const yargsParser = require('yargs-parser'); +const { hasPkgProp, resolveBin, hasFile, resolveCodScripts } = require('../utils'); -const args = process.argv.slice(2) -const parsedArgs = yargsParser(args) +const args = process.argv.slice(2); +const parsedArgs = yargsParser(args); -const here = p => path.join(__dirname, p) -const hereRelative = p => here(p).replace(process.cwd(), '.') +const here = p => path.join(__dirname, p); +const hereRelative = p => here(p).replace(process.cwd(), '.'); const useBuiltinConfig = !args.includes('--config') && !hasFile('.prettierrc') && !hasFile('prettier.config.js') && - !hasPkgProp('prettierrc') -const config = useBuiltinConfig - ? ['--config', hereRelative('../config/prettierrc.js')] - : [] + !hasPkgProp('prettierrc'); -const useBuiltinIgnore = - !args.includes('--ignore-path') && !hasFile('.prettierignore') -const ignore = useBuiltinIgnore - ? ['--ignore-path', hereRelative('../config/prettierignore')] - : [] +const config = useBuiltinConfig ? ['--config', hereRelative('../config/prettierrc.js')] : []; +const useBuiltinIgnore = !args.includes('--ignore-path') && !hasFile('.prettierignore'); +const ignore = useBuiltinIgnore ? ['--ignore-path', hereRelative('../config/prettierignore')] : []; -const write = args.includes('--no-write') ? [] : ['--write'] +const write = args.includes('--no-write') ? [] : ['--write']; // this ensures that when running format as a pre-commit hook and we get // the full file path, we make that non-absolute so it is treated as a glob, // This way the prettierignore will be applied -const relativeArgs = args.map(a => a.replace(`${process.cwd()}/`, '')) +const relativeArgs = args.map(a => a.replace(`${process.cwd()}/`, '')); +const filesToApply = parsedArgs._.length ? [] : ['**/*.+(json|less|css|ts|tsx|md)']; -const filesToApply = parsedArgs._.length - ? [] - : ['**/*.+(js|json|less|css|ts|tsx|md)'] - -const result = spawn.sync( +// run prettier on all non-js files +const prettierResult = spawn.sync( resolveBin('prettier'), [...config, ...ignore, ...write, ...filesToApply].concat(relativeArgs), - {stdio: 'inherit'}, -) + { stdio: 'inherit' }, +); + +if (prettierResult.status !== 0 || args.includes('--no-eslint')) { + process.exit(prettierResult.status); +} + +// run eslint for js files (`eslint-plugin-prettier` will run prettier for us) +const eslintResult = spawn.sync(resolveCodScripts(), ['lint', '--fix'].concat(args), { + stdio: 'inherit', +}); -process.exit(result.status) +process.exit(eslintResult.status); diff --git a/src/scripts/lint.js b/src/scripts/lint.js index 2a3be2b0..18cb817f 100644 --- a/src/scripts/lint.js +++ b/src/scripts/lint.js @@ -1,55 +1,44 @@ -const path = require('path') -const spawn = require('cross-spawn') -const yargsParser = require('yargs-parser') -const {hasPkgProp, resolveBin, hasFile, fromRoot} = require('../utils') +const path = require('path'); +const spawn = require('cross-spawn'); +const yargsParser = require('yargs-parser'); +const { hasPkgProp, resolveBin, hasFile, fromRoot } = require('../utils'); -let args = process.argv.slice(2) -const here = p => path.join(__dirname, p) -const hereRelative = p => here(p).replace(process.cwd(), '.') -const parsedArgs = yargsParser(args) +let args = process.argv.slice(2); +const here = p => path.join(__dirname, p); +const hereRelative = p => here(p).replace(process.cwd(), '.'); +const parsedArgs = yargsParser(args); const useBuiltinConfig = !args.includes('--config') && !hasFile('.eslintrc') && !hasFile('.eslintrc.js') && - !hasPkgProp('eslintConfig') + !hasPkgProp('eslintConfig'); -const config = useBuiltinConfig - ? ['--config', hereRelative('../config/eslintrc.js')] - : [] +const config = useBuiltinConfig ? ['--config', hereRelative('../config/eslintrc.js')] : []; const useBuiltinIgnore = - !args.includes('--ignore-path') && - !hasFile('.eslintignore') && - !hasPkgProp('eslintIgnore') + !args.includes('--ignore-path') && !hasFile('.eslintignore') && !hasPkgProp('eslintIgnore'); -const ignore = useBuiltinIgnore - ? ['--ignore-path', hereRelative('../config/eslintignore')] - : [] +const ignore = useBuiltinIgnore ? ['--ignore-path', hereRelative('../config/eslintignore')] : []; const cache = args.includes('--no-cache') ? [] - : [ - '--cache', - '--cache-location', - fromRoot('node_modules/.cache/.eslintcache'), - ] + : ['--cache', '--cache-location', fromRoot('node_modules/.cache/.eslintcache')]; -const filesGiven = parsedArgs._.length > 0 - -const filesToApply = filesGiven ? [] : ['.'] +const filesGiven = parsedArgs._.length > 0; +const filesToApply = filesGiven ? [] : ['.']; if (filesGiven) { // we need to take all the flag-less arguments (the files that should be linted) // and filter out the ones that aren't js files. Otherwise json or css files // may be passed through - args = args.filter(a => !parsedArgs._.includes(a) || /\.jsx?$/.test(a)) + args = args.filter(a => !parsedArgs._.includes(a) || /\.(jsx|js)?$/.test(a)); } const result = spawn.sync( resolveBin('eslint'), [...config, ...ignore, ...cache, ...args, ...filesToApply], - {stdio: 'inherit'}, -) + { stdio: 'inherit' }, +); -process.exit(result.status) +process.exit(result.status); diff --git a/src/scripts/pre-commit.js b/src/scripts/pre-commit.js index 03be42f5..e9188718 100644 --- a/src/scripts/pre-commit.js +++ b/src/scripts/pre-commit.js @@ -1,34 +1,30 @@ -const path = require('path') -const spawn = require('cross-spawn') -const {isOptedIn, hasPkgProp, hasFile, resolveBin} = require('../utils') +const path = require('path'); +const spawn = require('cross-spawn'); +const { isOptedIn, hasPkgProp, hasFile, resolveBin } = require('../utils'); -const here = p => path.join(__dirname, p) -const hereRelative = p => here(p).replace(process.cwd(), '.') +const here = p => path.join(__dirname, p); +const hereRelative = p => here(p).replace(process.cwd(), '.'); -const args = process.argv.slice(2) +const args = process.argv.slice(2); const useBuiltInConfig = !args.includes('--config') && !hasFile('.lintstagedrc') && !hasFile('lint-staged.config.js') && - !hasPkgProp('lint-staged') + !hasPkgProp('lint-staged'); -const config = useBuiltInConfig - ? ['--config', hereRelative('../config/lintstagedrc.js')] - : [] +const config = useBuiltInConfig ? ['--config', hereRelative('../config/lintstagedrc.js')] : []; -const lintStagedResult = spawn.sync( - resolveBin('lint-staged'), - [...config, ...args], - {stdio: 'inherit'}, -) +const lintStagedResult = spawn.sync(resolveBin('lint-staged'), [...config, ...args], { + stdio: 'inherit', +}); if (lintStagedResult.status !== 0 || !isOptedIn('pre-commit')) { - process.exit(lintStagedResult.status) + process.exit(lintStagedResult.status); } else { const validateResult = spawn.sync('npm', ['run', 'validate'], { stdio: 'inherit', - }) + }); - process.exit(validateResult.status) + process.exit(validateResult.status); } diff --git a/src/scripts/test.js b/src/scripts/test.js index 106a2d09..f00d3adb 100644 --- a/src/scripts/test.js +++ b/src/scripts/test.js @@ -1,10 +1,10 @@ -process.env.BABEL_ENV = 'test' -process.env.NODE_ENV = 'test' +process.env.BABEL_ENV = 'test'; +process.env.NODE_ENV = 'test'; -const isCI = require('is-ci') -const {hasPkgProp, parseEnv, hasFile} = require('../utils') +const isCI = require('is-ci'); +const { hasPkgProp, parseEnv, hasFile } = require('../utils'); -const args = process.argv.slice(2) +const args = process.argv.slice(2); const watch = !isCI && @@ -13,14 +13,12 @@ const watch = !args.includes('--coverage') && !args.includes('--updateSnapshot') ? ['--watch'] - : [] + : []; const config = - !args.includes('--config') && - !hasFile('jest.config.js') && - !hasPkgProp('jest') + !args.includes('--config') && !hasFile('jest.config.js') && !hasPkgProp('jest') ? ['--config', JSON.stringify(require('../config/jest.config'))] - : [] + : []; // eslint-disable-next-line jest/no-jest-import -require('jest').run([...config, ...watch, ...args]) +require('jest').run([...config, ...watch, ...args]); diff --git a/src/scripts/travis-after-success.js b/src/scripts/travis-after-success.js deleted file mode 100644 index 5e76eaba..00000000 --- a/src/scripts/travis-after-success.js +++ /dev/null @@ -1,57 +0,0 @@ -const spawn = require('cross-spawn') -const { - resolveBin, - getConcurrentlyArgs, - hasFile, - pkg, - parseEnv, -} = require('../utils') - -console.log('installing and running travis-deploy-once') -const deployOnceResults = spawn.sync('npx', ['travis-deploy-once@5'], { - stdio: 'inherit', -}) -if (deployOnceResults.status === 0) { - runAfterSuccessScripts() -} else { - console.log( - 'travis-deploy-once exited with a non-zero exit code', - deployOnceResults.status, - ) - process.exit(deployOnceResults.status) -} - -// eslint-disable-next-line complexity -function runAfterSuccessScripts() { - const autorelease = - pkg.version === '0.0.0-semantically-released' && - parseEnv('TRAVIS', false) && - process.env.TRAVIS_BRANCH === 'master' && - !parseEnv('TRAVIS_PULL_REQUEST', false) - - const reportCoverage = hasFile('coverage') && !parseEnv('SKIP_CODECOV', false) - - if (!autorelease && !reportCoverage) { - console.log( - 'No need to autorelease or report coverage. Skipping travis-after-success script...', - ) - } else { - const result = spawn.sync( - resolveBin('concurrently'), - getConcurrentlyArgs( - { - codecov: reportCoverage - ? `echo installing codecov && npx -p codecov@3 -c 'echo running codecov && codecov'` - : null, - release: autorelease - ? `echo installing semantic-release && npx -p semantic-release@15 -c 'echo running semantic-release && semantic-release'` - : null, - }, - {killOthers: false}, - ), - {stdio: 'inherit'}, - ) - - process.exit(result.status) - } -} diff --git a/src/scripts/validate.js b/src/scripts/validate.js index 2706536e..5f15ecba 100644 --- a/src/scripts/validate.js +++ b/src/scripts/validate.js @@ -1,38 +1,28 @@ -const spawn = require('cross-spawn') -const { - parseEnv, - resolveBin, - ifScript, - getConcurrentlyArgs, -} = require('../utils') +const spawn = require('cross-spawn'); +const { parseEnv, resolveBin, ifScript, getConcurrentlyArgs } = require('../utils'); // pre-commit runs linting and tests on the relevant files // so those scripts don't need to be run if we're running // this in the context of a pre-commit hook. -const preCommit = parseEnv('SCRIPTS_PRE-COMMIT', false) +const preCommit = parseEnv('SCRIPTS_PRE-COMMIT', false); -const validateScripts = process.argv[2] +const validateScripts = process.argv[2]; -const useDefaultScripts = typeof validateScripts !== 'string' +const useDefaultScripts = typeof validateScripts !== 'string'; const scripts = useDefaultScripts ? { build: ifScript('build', 'npm run build --silent'), lint: preCommit ? null : ifScript('lint', 'npm run lint --silent'), - test: preCommit - ? null - : ifScript('test', 'npm run test --silent -- --coverage'), + test: preCommit ? null : ifScript('test', 'npm run test --silent -- --coverage'), flow: ifScript('flow', 'npm run flow --silent'), } : validateScripts.split(',').reduce((scriptsToRun, name) => { - scriptsToRun[name] = `npm run ${name} --silent` - return scriptsToRun - }, {}) + return { ...scriptsToRun, [name]: `npm run ${name} --silent` }; + }, {}); -const result = spawn.sync( - resolveBin('concurrently'), - getConcurrentlyArgs(scripts), - {stdio: 'inherit'}, -) +const result = spawn.sync(resolveBin('concurrently'), getConcurrentlyArgs(scripts), { + stdio: 'inherit', +}); -process.exit(result.status) +process.exit(result.status); diff --git a/src/utils.js b/src/utils.js index 7847f776..d9822c33 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,96 +1,89 @@ -const fs = require('fs') -const path = require('path') -const rimraf = require('rimraf') -const mkdirp = require('mkdirp') -const arrify = require('arrify') -const has = require('lodash.has') -const readPkgUp = require('read-pkg-up') -const which = require('which') - -const {package: pkg, path: pkgPath} = readPkgUp.sync({ +const fs = require('fs'); +const path = require('path'); +const rimraf = require('rimraf'); +const mkdirp = require('mkdirp'); +const arrify = require('arrify'); +const has = require('lodash.has'); +const readPkgUp = require('read-pkg-up'); +const which = require('which'); + +const { package: pkg, path: pkgPath } = readPkgUp.sync({ cwd: fs.realpathSync(process.cwd()), -}) -const appDirectory = path.dirname(pkgPath) +}); +const appDirectory = path.dirname(pkgPath); -function resolveKcdScripts() { - if (pkg.name === 'kcd-scripts') { - return require.resolve('./').replace(process.cwd(), '.') - } - return resolveBin('kcd-scripts') -} - -// eslint-disable-next-line complexity -function resolveBin(modName, {executable = modName, cwd = process.cwd()} = {}) { - let pathFromWhich +function resolveBin(modName, { executable = modName, cwd = process.cwd() } = {}) { + let pathFromWhich; try { - pathFromWhich = fs.realpathSync(which.sync(executable)) - if (pathFromWhich && pathFromWhich.includes('.CMD')) return pathFromWhich + pathFromWhich = fs.realpathSync(which.sync(executable)); + if (pathFromWhich && pathFromWhich.includes('.CMD')) return pathFromWhich; } catch (_error) { // ignore _error } try { - const modPkgPath = require.resolve(`${modName}/package.json`) - const modPkgDir = path.dirname(modPkgPath) - const {bin} = require(modPkgPath) - const binPath = typeof bin === 'string' ? bin : bin[executable] - const fullPathToBin = path.join(modPkgDir, binPath) + const modPkgPath = require.resolve(`${modName}/package.json`); + const modPkgDir = path.dirname(modPkgPath); + const { bin } = require(modPkgPath); // eslint-disable-line + const binPath = typeof bin === 'string' ? bin : bin[executable]; + const fullPathToBin = path.join(modPkgDir, binPath); if (fullPathToBin === pathFromWhich) { - return executable + return executable; } - return fullPathToBin.replace(cwd, '.') + return fullPathToBin.replace(cwd, '.'); } catch (error) { if (pathFromWhich) { - return executable + return executable; } - throw error + throw error; } } -const fromRoot = (...p) => path.join(appDirectory, ...p) -const hasFile = (...p) => fs.existsSync(fromRoot(...p)) -const ifFile = (files, t, f) => - arrify(files).some(file => hasFile(file)) ? t : f +function resolveCodScripts() { + if (pkg.name === 'cod-scripts') { + return require.resolve('./').replace(process.cwd(), '.'); + } + return resolveBin('cod-scripts'); +} + +const fromRoot = (...p) => path.join(appDirectory, ...p); +const hasFile = (...p) => fs.existsSync(fromRoot(...p)); +const ifFile = (files, t, f) => (arrify(files).some(file => hasFile(file)) ? t : f); -const hasPkgProp = props => arrify(props).some(prop => has(pkg, prop)) +const hasPkgProp = props => arrify(props).some(prop => has(pkg, prop)); -const hasPkgSubProp = pkgProp => props => - hasPkgProp(arrify(props).map(p => `${pkgProp}.${p}`)) +const hasPkgSubProp = pkgProp => props => hasPkgProp(arrify(props).map(p => `${pkgProp}.${p}`)); -const ifPkgSubProp = pkgProp => (props, t, f) => - hasPkgSubProp(pkgProp)(props) ? t : f +const ifPkgSubProp = pkgProp => (props, t, f) => (hasPkgSubProp(pkgProp)(props) ? t : f); -const hasScript = hasPkgSubProp('scripts') -const hasPeerDep = hasPkgSubProp('peerDependencies') -const hasDep = hasPkgSubProp('dependencies') -const hasDevDep = hasPkgSubProp('devDependencies') -const hasAnyDep = args => [hasDep, hasDevDep, hasPeerDep].some(fn => fn(args)) +const hasScript = hasPkgSubProp('scripts'); +const hasPeerDep = hasPkgSubProp('peerDependencies'); +const hasDep = hasPkgSubProp('dependencies'); +const hasDevDep = hasPkgSubProp('devDependencies'); +const hasAnyDep = args => [hasDep, hasDevDep, hasPeerDep].some(fn => fn(args)); -const ifPeerDep = ifPkgSubProp('peerDependencies') -const ifDep = ifPkgSubProp('dependencies') -const ifDevDep = ifPkgSubProp('devDependencies') -const ifAnyDep = (deps, t, f) => (hasAnyDep(arrify(deps)) ? t : f) -const ifScript = ifPkgSubProp('scripts') +const ifPeerDep = ifPkgSubProp('peerDependencies'); +const ifDep = ifPkgSubProp('dependencies'); +const ifDevDep = ifPkgSubProp('devDependencies'); +const ifAnyDep = (deps, t, f) => (hasAnyDep(arrify(deps)) ? t : f); +const ifScript = ifPkgSubProp('scripts'); + +function envIsSet(name) { + // eslint-disable-next-line no-prototype-builtins + return process.env.hasOwnProperty(name) && process.env[name] && process.env[name] !== 'undefined'; +} function parseEnv(name, def) { if (envIsSet(name)) { try { - return JSON.parse(process.env[name]) + return JSON.parse(process.env[name]); } catch (err) { - return process.env[name] + return process.env[name]; } } - return def -} - -function envIsSet(name) { - return ( - process.env.hasOwnProperty(name) && - process.env[name] && - process.env[name] !== 'undefined' - ) + return def; } -function getConcurrentlyArgs(scripts, {killOthers = true} = {}) { +function getConcurrentlyArgs(scripts, { killOthers = true } = {}) { const colors = [ 'bgBlue', 'bgGreen', @@ -100,20 +93,18 @@ function getConcurrentlyArgs(scripts, {killOthers = true} = {}) { 'bgRed', 'bgBlack', 'bgYellow', - ] + ]; + // eslint-disable-next-line no-param-reassign scripts = Object.entries(scripts).reduce((all, [name, script]) => { if (script) { - all[name] = script + // eslint-disable-next-line no-param-reassign + all[name] = script; } - return all - }, {}) + return all; + }, {}); const prefixColors = Object.keys(scripts) - .reduce( - (pColors, _s, i) => - pColors.concat([`${colors[i % colors.length]}.bold.reset`]), - [], - ) - .join(',') + .reduce((pColors, _s, i) => pColors.concat([`${colors[i % colors.length]}.bold.reset`]), []) + .join(','); // prettier-ignore return [ @@ -127,32 +118,32 @@ function getConcurrentlyArgs(scripts, {killOthers = true} = {}) { function isOptedOut(key, t = true, f = false) { if (!fs.existsSync(fromRoot('.opt-out'))) { - return f + return f; } - const contents = fs.readFileSync(fromRoot('.opt-out'), 'utf-8') - return contents.includes(key) ? t : f + const contents = fs.readFileSync(fromRoot('.opt-out'), 'utf-8'); + return contents.includes(key) ? t : f; } function isOptedIn(key, t = true, f = false) { if (!fs.existsSync(fromRoot('.opt-in'))) { - return f + return f; } - const contents = fs.readFileSync(fromRoot('.opt-in'), 'utf-8') - return contents.includes(key) ? t : f + const contents = fs.readFileSync(fromRoot('.opt-in'), 'utf-8'); + return contents.includes(key) ? t : f; } function uniq(arr) { - return Array.from(new Set(arr)) + return Array.from(new Set(arr)); } -function writeExtraEntry(name, {cjs, esm}, clean = true) { +function writeExtraEntry(name, { cjs, esm }, clean = true) { if (clean) { - rimraf.sync(fromRoot(name)) + rimraf.sync(fromRoot(name)); } - mkdirp.sync(fromRoot(name)) + mkdirp.sync(fromRoot(name)); - const pkgJson = fromRoot(`${name}/package.json`) - const entryDir = fromRoot(name) + const pkgJson = fromRoot(`${name}/package.json`); + const entryDir = fromRoot(name); fs.writeFileSync( pkgJson, @@ -165,7 +156,7 @@ function writeExtraEntry(name, {cjs, esm}, clean = true) { null, 2, ), - ) + ); } module.exports = { @@ -187,7 +178,7 @@ module.exports = { parseEnv, pkg, resolveBin, - resolveKcdScripts, + resolveCodScripts, uniq, writeExtraEntry, -} +}; From ab174b40dfe63c65011fc215bd92819a8ee87ad3 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sun, 15 Sep 2019 19:15:58 -0400 Subject: [PATCH 02/48] chore: add github actions --- .github/workflows/commitlint.yml | 19 ++++++++++++++++ .github/workflows/release.yml | 34 ++++++++++++++++++++++++++++ .github/workflows/validate.yml | 39 ++++++++++++++++++++++++++++++++ package.json | 2 ++ 4 files changed, 94 insertions(+) create mode 100644 .github/workflows/commitlint.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/validate.yml diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml new file mode 100644 index 00000000..32ed3313 --- /dev/null +++ b/.github/workflows/commitlint.yml @@ -0,0 +1,19 @@ +name: Lint Commit Messages + +on: pull_request + +jobs: + commitlint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@master + + - run: npm install --no-save + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - run: + npx commitlint --from="origin/${{ github.base_ref }}" --to="origin/${{ github.head_ref }}" + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..34abf300 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,34 @@ +name: Release + +on: + push: + branches: + - master + +jobs: + release: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@master + + - uses: actions/setup-node@v1 + with: + node-version: 12.x + registry-url: https://registry.ey.npme.io + + - name: validate before release + run: | + npm install --no-save + npm run build + npm run lint + npm run test + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + CI: true + + - name: semantic release + uses: codfish/semantic-release-action@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 00000000..e0245d9e --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,39 @@ +name: Validate Code + +on: push + +jobs: + validate: + runs-on: ubuntu-latest + + strategy: + matrix: + node: [10.x, 11.x, 12.x] + + steps: + - uses: actions/checkout@master + + - uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node }} + registry-url: https://registry.ey.npme.io + + - name: install dependencies + run: npm install --no-save + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - run: npm run build + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: lint js + run: npm run lint + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: run tests + run: npm run test + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + CI: true diff --git a/package.json b/package.json index e8530376..deac74e0 100644 --- a/package.json +++ b/package.json @@ -104,6 +104,8 @@ }, "homepage": "https://github.com/codfish/cod-scripts#readme", "devDependencies": { + "@commitlint/cli": "^8.1.0", + "@commitlint/config-conventional": "^8.1.0", "jest-in-case": "^1.0.2", "slash": "^3.0.0" } From a6c345592dfe8d68bf00ad93b3c20fe05398c15d Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sun, 15 Sep 2019 19:35:24 -0400 Subject: [PATCH 03/48] feat: add commitlint config files --- .github/workflows/commitlint.yml | 3 ++- commitlint.js | 1 + src/config/commitlint.config.js | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 commitlint.js create mode 100644 src/config/commitlint.config.js diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 32ed3313..8c0d9011 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -14,6 +14,7 @@ jobs: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: - npx commitlint --from="origin/${{ github.base_ref }}" --to="origin/${{ github.head_ref }}" + npx commitlint --config="./src/config/commitlint.config.js" --from="origin/${{ + github.base_ref }}" --to="origin/${{ github.head_ref }}" env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/commitlint.js b/commitlint.js new file mode 100644 index 00000000..23a4bda0 --- /dev/null +++ b/commitlint.js @@ -0,0 +1 @@ +module.exports = require('./dist/config/commitlint.config'); diff --git a/src/config/commitlint.config.js b/src/config/commitlint.config.js new file mode 100644 index 00000000..84dcb122 --- /dev/null +++ b/src/config/commitlint.config.js @@ -0,0 +1,3 @@ +module.exports = { + extends: ['@commitlint/config-conventional'], +}; From c1460020721e5552bccae5230fb34eb170b5b362 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sun, 15 Sep 2019 20:16:13 -0400 Subject: [PATCH 04/48] chore: fix npm registry --- .github/workflows/release.yml | 1 - .github/workflows/validate.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 34abf300..81a26106 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,6 @@ jobs: - uses: actions/setup-node@v1 with: node-version: 12.x - registry-url: https://registry.ey.npme.io - name: validate before release run: | diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index e0245d9e..6d4d047f 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -16,7 +16,6 @@ jobs: - uses: actions/setup-node@v1 with: node-version: ${{ matrix.node }} - registry-url: https://registry.ey.npme.io - name: install dependencies run: npm install --no-save From a2243f9d93a083316e8b553a626731bf51639c55 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Mon, 16 Sep 2019 13:39:27 -0400 Subject: [PATCH 05/48] docs: update LICENSE --- LICENSE | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/LICENSE b/LICENSE index 4c43675b..5e8d3bbb 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,6 @@ The MIT License (MIT) -Copyright (c) 2017 Kent C. Dodds + +Copyright (c) 2019 Chris O'Donnell (https://codfish.io/) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -8,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. From b30ff206a7f78814f1a19d397516879d706d9f3d Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Tue, 17 Sep 2019 12:08:44 -0400 Subject: [PATCH 06/48] feat: add more filetypes to prettier formatting --- src/scripts/__tests__/__snapshots__/format.js.snap | 12 ++++++------ src/scripts/format.js | 4 +++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/scripts/__tests__/__snapshots__/format.js.snap b/src/scripts/__tests__/__snapshots__/format.js.snap index 4a54fbd0..9c9ad7c9 100644 --- a/src/scripts/__tests__/__snapshots__/format.js.snap +++ b/src/scripts/__tests__/__snapshots__/format.js.snap @@ -1,16 +1,16 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`format --config arg can be used for a custom config 1`] = `prettier --ignore-path ./src/config/prettierignore --write **/*.+(json|less|css|ts|tsx|md) --config ./my-config.js`; +exports[`format --config arg can be used for a custom config 1`] = `prettier --ignore-path ./src/config/prettierignore --write **/*.+(md|json|yml|yaml|css|less|scss|sass|graphql|ts|tsx) --config ./my-config.js`; -exports[`format --config arg can be used for a custom config 2`] = `prettier --ignore-path ./src/config/prettierignore --write **/*.+(json|less|css|ts|tsx|md) --config ./my-config.js`; +exports[`format --config arg can be used for a custom config 2`] = `prettier --ignore-path ./src/config/prettierignore --write **/*.+(md|json|yml|yaml|css|less|scss|sass|graphql|ts|tsx) --config ./my-config.js`; -exports[`format --ignore-path arg can be used for a custom ignore file 1`] = `prettier --config ./src/config/prettierrc.js --write **/*.+(json|less|css|ts|tsx|md) --ignore-path ./.myignore`; +exports[`format --ignore-path arg can be used for a custom ignore file 1`] = `prettier --config ./src/config/prettierrc.js --write **/*.+(md|json|yml|yaml|css|less|scss|sass|graphql|ts|tsx) --ignore-path ./.myignore`; -exports[`format --ignore-path arg can be used for a custom ignore file 2`] = `prettier --config ./src/config/prettierrc.js --write **/*.+(json|less|css|ts|tsx|md) --ignore-path ./.myignore`; +exports[`format --ignore-path arg can be used for a custom ignore file 2`] = `prettier --config ./src/config/prettierrc.js --write **/*.+(md|json|yml|yaml|css|less|scss|sass|graphql|ts|tsx) --ignore-path ./.myignore`; -exports[`format --no-write prevents --write argument from being added 1`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore **/*.+(json|less|css|ts|tsx|md) --no-write`; +exports[`format --no-write prevents --write argument from being added 1`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore **/*.+(md|json|yml|yaml|css|less|scss|sass|graphql|ts|tsx) --no-write`; -exports[`format --no-write prevents --write argument from being added 2`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore **/*.+(json|less|css|ts|tsx|md) --no-write`; +exports[`format --no-write prevents --write argument from being added 2`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore **/*.+(md|json|yml|yaml|css|less|scss|sass|graphql|ts|tsx) --no-write`; exports[`format calls prettier CLI with args 1`] = `prettier --config ./src/config/prettierrc.js --ignore-path ./src/config/prettierignore --write my-src/**/*.js`; diff --git a/src/scripts/format.js b/src/scripts/format.js index 2bd04cf1..ca42da97 100644 --- a/src/scripts/format.js +++ b/src/scripts/format.js @@ -25,7 +25,9 @@ const write = args.includes('--no-write') ? [] : ['--write']; // the full file path, we make that non-absolute so it is treated as a glob, // This way the prettierignore will be applied const relativeArgs = args.map(a => a.replace(`${process.cwd()}/`, '')); -const filesToApply = parsedArgs._.length ? [] : ['**/*.+(json|less|css|ts|tsx|md)']; +const filesToApply = parsedArgs._.length + ? [] + : ['**/*.+(md|json|yml|yaml|css|less|scss|sass|graphql|ts|tsx)']; // run prettier on all non-js files const prettierResult = spawn.sync( From 6f41bd8020de3cec09a1a3176a148fea97be9264 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Tue, 17 Sep 2019 12:09:30 -0400 Subject: [PATCH 07/48] fix: add missing --no-eslint flag for lint-staged *.md command --- src/config/lintstagedrc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/lintstagedrc.js b/src/config/lintstagedrc.js index ba770af7..5c2a9d4c 100644 --- a/src/config/lintstagedrc.js +++ b/src/config/lintstagedrc.js @@ -10,7 +10,7 @@ module.exports = { isOptedOut('autoformat', null, 'git add'), ].filter(Boolean), '*.md': [ - isOptedOut('autoformat', null, `${codScripts} format`), + isOptedOut('autoformat', null, `${codScripts} format --no-eslint`), // TODO: add markdownlint isOptedOut('autoformat', null, 'git add'), ].filter(Boolean), From 6a2c02446e116380d46ae995e8f1f58e6cb5db4d Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Wed, 18 Sep 2019 07:56:11 -0400 Subject: [PATCH 08/48] feat: bump dependencies BREAKING CHANGE: Bumped eslint-config-codfish major version which may have caused breaking rule changes. You might see errors where you didn't before and things may pass where they wouldn't have before. --- package.json | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index deac74e0..6e297447 100644 --- a/package.json +++ b/package.json @@ -53,11 +53,11 @@ "babel-plugin-transform-react-remove-prop-types": "^0.4.21", "browserslist": "^4.6.6", "concurrently": "^4.1.1", - "cross-env": "^5.1.4", - "cross-spawn": "^6.0.5", + "cross-env": "^6.0.0", + "cross-spawn": "^7.0.0", "doctoc": "^1.4.0", - "eslint": "^5.15.2", - "eslint-config-codfish": "^2.5.0", + "eslint": "^6.4.0", + "eslint-config-codfish": "^4.0.0", "glob": "^7.1.4", "husky": "^3.0.3", "is-ci": "^2.0.0", @@ -71,7 +71,7 @@ "prettier": "^1.16.4", "read-pkg-up": "^6.0.0", "resolve": "^1.12.0", - "rimraf": "^2.6.2", + "rimraf": "^3.0.0", "rollup": "^1.19.4", "rollup-plugin-babel": "^4.3.3", "rollup-plugin-commonjs": "^10.0.2", @@ -84,7 +84,7 @@ "rollup-plugin-terser": "^5.1.1", "semver": "^6.3.0", "which": "^1.3.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^14.0.0" }, "eslintConfig": { "extends": [ @@ -92,7 +92,8 @@ ], "rules": { "no-console": "off", - "global-require": "off" + "global-require": "off", + "no-useless-catch": "off" } }, "repository": { From ca41fc641cb4f9b33f85297fe15c0c2331366281 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 19 Sep 2019 16:34:22 -0400 Subject: [PATCH 09/48] feat: add commitlint script --- README.md | 27 ++++++++++++++++ package.json | 39 +++++++++++++++++++---- src/__tests__/__snapshots__/index.js.snap | 1 + src/config/__tests__/umbrella.js | 1 + src/config/commitlint.config.js | 2 ++ src/config/index.js | 1 + src/scripts/commitlint.js | 24 ++++++++++++++ 7 files changed, 88 insertions(+), 7 deletions(-) create mode 100644 src/scripts/commitlint.js diff --git a/README.md b/README.md index a957faaf..33a3a983 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,33 @@ module.exports = Object.assign(jestConfig, { }); ``` +Or, for `commitlint`, a `commitlint.config.js` file or `commitlint` prop in package.json: + +```js +// commitlint.config.js or .commitlintrc.js +const { commitlint: commitlintConfig } = require('cod-scripts/commitlint'); + +module.exports = { + ...commitlintConfig, + rules: { + // overrides here + }, +}; +``` + +```json +// package.json +{ + "commitlint": { + "extends": ["./node_modules/cod-scripts/commitlint"], + "rules": { + // your overrides here + // https://commitlint.js.org/#/reference-rules + } + } +} +``` + > Note: `cod-scripts` intentionally does not merge things for you when you start configuring things > to make it less magical and more straightforward. Extending can take place on your terms. I think > this is actually a great way to do this. diff --git a/package.json b/package.json index 6e297447..b795606f 100644 --- a/package.json +++ b/package.json @@ -14,17 +14,14 @@ "test:update": "node src test --updateSnapshot", "build": "node src build", "lint": "node src lint", + "commitlint": "node src commitlint", "format": "node src format", "validate": "node src validate" }, - "husky": { - "hooks": { - "pre-commit": "node src pre-commit" - } - }, "files": [ "dist", "babel.js", + "commitlint.js", "eslint.js", "config.js", "prettier.js", @@ -43,6 +40,8 @@ "@babel/preset-flow": "^7.0.0", "@babel/preset-react": "^7.0.0", "@babel/runtime": "^7.5.5", + "@commitlint/cli": "^8.1.0", + "@commitlint/config-conventional": "^8.1.0", "arrify": "^2.0.1", "babel-core": "^7.0.0-0", "babel-jest": "^24.8.0", @@ -96,6 +95,34 @@ "no-useless-catch": "off" } }, + "husky": { + "hooks": { + "pre-commit": "node src pre-commit", + "commit-msg": "node src commitlint -E HUSKY_GIT_PARAMS" + } + }, + "commitlint": { + "extends": [ + "./src/config/commitlint.config" + ], + "rules": { + "scope-enum": [ + 2, + "always", + [ + "eslint", + "babel", + "rollup", + "commitlint", + "jest", + "lintstaged", + "lint-staged", + "husky", + "prettier" + ] + ] + } + }, "repository": { "type": "git", "url": "https://github.com/codfish/cod-scripts.git" @@ -105,8 +132,6 @@ }, "homepage": "https://github.com/codfish/cod-scripts#readme", "devDependencies": { - "@commitlint/cli": "^8.1.0", - "@commitlint/config-conventional": "^8.1.0", "jest-in-case": "^1.0.2", "slash": "^3.0.0" } diff --git a/src/__tests__/__snapshots__/index.js.snap b/src/__tests__/__snapshots__/index.js.snap index 3256635f..60b7d5c1 100644 --- a/src/__tests__/__snapshots__/index.js.snap +++ b/src/__tests__/__snapshots__/index.js.snap @@ -28,6 +28,7 @@ Usage: ../ [script] [--flags] Available Scripts: build + commitlint format lint pre-commit diff --git a/src/config/__tests__/umbrella.js b/src/config/__tests__/umbrella.js index a104af05..45e09478 100644 --- a/src/config/__tests__/umbrella.js +++ b/src/config/__tests__/umbrella.js @@ -1,6 +1,7 @@ test('requiring some files does not blow up', () => { require('../babel-transform'); require('../babelrc'); + require('../commitlint.config'); require('../eslintrc'); require('../jest.config'); require('../lintstagedrc'); diff --git a/src/config/commitlint.config.js b/src/config/commitlint.config.js index 84dcb122..418698da 100644 --- a/src/config/commitlint.config.js +++ b/src/config/commitlint.config.js @@ -1,3 +1,5 @@ +// https://commitlint.js.org/#/reference-rules module.exports = { + // https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum extends: ['@commitlint/config-conventional'], }; diff --git a/src/config/index.js b/src/config/index.js index 86fe9ee0..d9b7d4a3 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -1,5 +1,6 @@ module.exports = { babel: require('./babelrc'), + commitlint: require('./commitlint.config'), eslint: require('./eslintrc'), jest: require('./jest.config'), lintStaged: require('./lintstagedrc'), diff --git a/src/scripts/commitlint.js b/src/scripts/commitlint.js new file mode 100644 index 00000000..36ec5bb7 --- /dev/null +++ b/src/scripts/commitlint.js @@ -0,0 +1,24 @@ +const path = require('path'); +const spawn = require('cross-spawn'); +const { hasPkgProp, resolveBin, hasFile } = require('../utils'); + +const args = process.argv.slice(2); +const here = p => path.join(__dirname, p); +const hereRelative = p => here(p).replace(process.cwd(), '.'); + +const useBuiltinConfig = + !args.includes('--config') && + !args.includes('-g') && + !hasFile('commitlint.config.js') && + !hasFile('.commitlintrc.js') && + !hasFile('.commitlintrc.json') && + !hasFile('.commitlintrc.yml') && + !hasPkgProp('commitlint'); + +const config = useBuiltinConfig ? ['--config', hereRelative('../config/commitlint.config.js')] : []; + +const result = spawn.sync(resolveBin('commitlint'), [...config, ...args], { + stdio: 'inherit', +}); + +process.exit(result.status); From 22db519b7fc3b477059224a2b26e3f6f19c42bc8 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sat, 21 Sep 2019 21:54:58 -0400 Subject: [PATCH 10/48] feat(eslint): bump eslint-config-codfish version BREAKING CHANGE: New eslint-config-codfish version introduces rule changes for react/jsx-props-no-spreading --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b795606f..2bd5f89e 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "cross-spawn": "^7.0.0", "doctoc": "^1.4.0", "eslint": "^6.4.0", - "eslint-config-codfish": "^4.0.0", + "eslint-config-codfish": "^5.1.0", "glob": "^7.1.4", "husky": "^3.0.3", "is-ci": "^2.0.0", From 98081bb37f72f83c53a7785a1bc2ff8b242d2c11 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Tue, 24 Sep 2019 16:14:35 -0400 Subject: [PATCH 11/48] fix: downgrade eslint dep to v5 cant figure out why but v6 introduces some dependencies that conflict with other projects like styleguidist. Most likely styleguidists fault but i dont need v6 yet, so reverting this --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2bd5f89e..5344a756 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "cross-env": "^6.0.0", "cross-spawn": "^7.0.0", "doctoc": "^1.4.0", - "eslint": "^6.4.0", + "eslint": "^5.15.2", "eslint-config-codfish": "^5.1.0", "glob": "^7.1.4", "husky": "^3.0.3", From 12bd2e4d8fafcb0c20cbe577706ac58eba37403d Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Wed, 2 Oct 2019 16:22:00 -0400 Subject: [PATCH 12/48] feat(jest): add support for jest.setup.js file Check for existence of jest.setup.js in root and use it as `setupFilesAfterEnv` file. --- src/config/jest.config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/config/jest.config.js b/src/config/jest.config.js index 4447eeb7..e7bccb54 100644 --- a/src/config/jest.config.js +++ b/src/config/jest.config.js @@ -32,6 +32,10 @@ const jestConfig = { ], }; +if (hasFile('jest.setup.js')) { + jestConfig.setupFilesAfterEnv = [fromRoot('jest.setup.js')]; +} + if (hasFile('setupTests.js')) { jestConfig.setupFilesAfterEnv = [fromRoot('setupTests.js')]; } From 729671713b9b27753478c6c2d1caed57e29e8a24 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Wed, 2 Oct 2019 17:19:11 -0400 Subject: [PATCH 13/48] style: add missing semi-colon --- src/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.js b/src/utils.js index d9822c33..1329cdcc 100644 --- a/src/utils.js +++ b/src/utils.js @@ -113,7 +113,7 @@ function getConcurrentlyArgs(scripts, { killOthers = true } = {}) { '--names', Object.keys(scripts).join(','), '--prefix-colors', prefixColors, ...Object.values(scripts).map(s => JSON.stringify(s)), // stringify escapes quotes ✨ - ].filter(Boolean) + ].filter(Boolean); } function isOptedOut(key, t = true, f = false) { From 35d28e246ac3a67d7a9c779f4c8a1679dfa24287 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 3 Oct 2019 10:38:45 -0400 Subject: [PATCH 14/48] test: fix broken dependency paths --- src/__tests__/utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/utils.js b/src/__tests__/utils.js index 322ed83f..b9bd7c7c 100644 --- a/src/__tests__/utils.js +++ b/src/__tests__/utils.js @@ -43,13 +43,13 @@ test('resolveCodScripts resolves to cod-scripts if not in the cod-scripts packag test(`resolveBin resolves to the full path when it's not in $PATH`, () => { expect(require('../utils').resolveBin('cross-env')).toBe( - require.resolve('cross-env/dist/bin/cross-env').replace(process.cwd(), '.'), + require.resolve('cross-env/src/bin/cross-env').replace(process.cwd(), '.'), ); }); test(`resolveBin resolves to the binary if it's in $PATH`, () => { whichSyncMock.mockImplementationOnce(() => - require.resolve('cross-env/dist/bin/cross-env').replace(process.cwd(), '.'), + require.resolve('cross-env/src/bin/cross-env').replace(process.cwd(), '.'), ); expect(require('../utils').resolveBin('cross-env')).toBe('cross-env'); expect(whichSyncMock).toHaveBeenCalledTimes(1); From 76e8a466c200ea5937b5f061e8a0f705daaac065 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Tue, 24 Sep 2019 23:20:59 -0400 Subject: [PATCH 15/48] feat(jest): add testing-library setup files automatically --- src/config/jest.config.js | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/config/jest.config.js b/src/config/jest.config.js index e7bccb54..85e862b4 100644 --- a/src/config/jest.config.js +++ b/src/config/jest.config.js @@ -1,5 +1,5 @@ const path = require('path'); -const { ifAnyDep, hasFile, hasPkgProp, fromRoot } = require('../utils'); +const { ifAnyDep, hasFile, ifFile, hasPkgProp, fromRoot } = require('../utils'); const here = p => path.join(__dirname, p); @@ -30,20 +30,14 @@ const jestConfig = { require.resolve('jest-watch-typeahead/filename'), require.resolve('jest-watch-typeahead/testname'), ], + setupFilesAfterEnv: [ + ifAnyDep('@testing-library/jest-dom', '@testing-library/jest-dom/extend-expect'), + ifFile('jest.setup.js', fromRoot('jest.setup.js')), + ifFile('setupTests.js', fromRoot('setupTests.js')), + ifFile('tests/setup-env.js', fromRoot('tests/setup-env.js')), + ].filter(Boolean), }; -if (hasFile('jest.setup.js')) { - jestConfig.setupFilesAfterEnv = [fromRoot('jest.setup.js')]; -} - -if (hasFile('setupTests.js')) { - jestConfig.setupFilesAfterEnv = [fromRoot('setupTests.js')]; -} - -if (hasFile('tests/setup-env.js')) { - jestConfig.setupFilesAfterEnv = [fromRoot('tests/setup-env.js')]; -} - if (useBuiltInBabelConfig) { jestConfig.transform = { '^.+\\.js$': here('./babel-transform') }; } From 38f31774cc0440fe7facd42049e341973596ae20 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 3 Oct 2019 10:18:22 -0400 Subject: [PATCH 16/48] feat(jest): add fetch polyfill using react-app-polyfill --- package.json | 1 + src/config/jest.config.js | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/package.json b/package.json index 5344a756..feeb82d5 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "lodash.omit": "^4.5.0", "mkdirp": "^0.5.1", "prettier": "^1.16.4", + "react-app-polyfill": "^1.0.3", "read-pkg-up": "^6.0.0", "resolve": "^1.12.0", "rimraf": "^3.0.0", diff --git a/src/config/jest.config.js b/src/config/jest.config.js index 85e862b4..c3840c13 100644 --- a/src/config/jest.config.js +++ b/src/config/jest.config.js @@ -42,4 +42,8 @@ if (useBuiltInBabelConfig) { jestConfig.transform = { '^.+\\.js$': here('./babel-transform') }; } +if (jestConfig.testEnvironment === 'jsdom') { + jestConfig.setupFiles = [require.resolve('react-app-polyfill/jsdom')]; +} + module.exports = jestConfig; From 8d7179927577a77cb3832ad579c71dd57eb92a24 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 24 Oct 2019 16:35:13 -0400 Subject: [PATCH 17/48] feat: bump deps with patch version changes --- package.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index feeb82d5..7394aef7 100644 --- a/package.json +++ b/package.json @@ -31,15 +31,15 @@ "author": "Chris O'Donnell (http://codfish.io/)", "license": "MIT", "dependencies": { - "@babel/cli": "^7.5.5", - "@babel/core": "^7.5.5", + "@babel/cli": "^7.6.4", + "@babel/core": "^7.6.4", "@babel/plugin-proposal-class-properties": "^7.5.5", "@babel/plugin-transform-modules-commonjs": "^7.5.0", "@babel/plugin-transform-runtime": "^7.5.5", - "@babel/preset-env": "^7.5.5", + "@babel/preset-env": "^7.6.3", "@babel/preset-flow": "^7.0.0", - "@babel/preset-react": "^7.0.0", - "@babel/runtime": "^7.5.5", + "@babel/preset-react": "^7.6.3", + "@babel/runtime": "^7.6.3", "@commitlint/cli": "^8.1.0", "@commitlint/config-conventional": "^8.1.0", "arrify": "^2.0.1", @@ -50,19 +50,19 @@ "babel-plugin-module-resolver": "^3.1.1", "babel-plugin-transform-inline-environment-variables": "^0.4.0", "babel-plugin-transform-react-remove-prop-types": "^0.4.21", - "browserslist": "^4.6.6", + "browserslist": "^4.7.2", "concurrently": "^4.1.1", "cross-env": "^6.0.0", - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.1", "doctoc": "^1.4.0", "eslint": "^5.15.2", - "eslint-config-codfish": "^5.1.0", - "glob": "^7.1.4", - "husky": "^3.0.3", + "eslint-config-codfish": "^5.3.0", + "glob": "^7.1.5", + "husky": "^3.0.9", "is-ci": "^2.0.0", "jest": "^24.8.0", "jest-watch-typeahead": "^0.3.1", - "lint-staged": "^9.2.1", + "lint-staged": "^9.4.2", "lodash.camelcase": "^4.3.0", "lodash.has": "^4.5.2", "lodash.omit": "^4.5.0", From 4cb3105c2fe2d7a124d9297b5b75bdc24592fad4 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sat, 8 Feb 2020 16:44:36 -0500 Subject: [PATCH 18/48] ci: update github actions events --- .github/workflows/commitlint.yml | 20 -------------------- .github/workflows/validate.yml | 9 ++++++++- 2 files changed, 8 insertions(+), 21 deletions(-) delete mode 100644 .github/workflows/commitlint.yml diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml deleted file mode 100644 index 8c0d9011..00000000 --- a/.github/workflows/commitlint.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Lint Commit Messages - -on: pull_request - -jobs: - commitlint: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@master - - - run: npm install --no-save - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - - run: - npx commitlint --config="./src/config/commitlint.config.js" --from="origin/${{ - github.base_ref }}" --to="origin/${{ github.head_ref }}" - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 6d4d047f..2b8737e5 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -1,6 +1,6 @@ name: Validate Code -on: push +on: pull_request jobs: validate: @@ -22,6 +22,13 @@ jobs: env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: lint commits + run: + npx commitlint --config="./src/config/commitlint.config.js" --from="origin/${{ + github.base_ref }}" --to="origin/${{ github.head_ref }}" + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + - run: npm run build env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} From 6e9c45f88ee3fc0fdc09c509b857e85ad26d095b Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Mon, 17 Feb 2020 11:20:57 -0500 Subject: [PATCH 19/48] fix: only run validate pre-commit if script exists --- src/scripts/pre-commit.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scripts/pre-commit.js b/src/scripts/pre-commit.js index 12895020..f6ae85fe 100644 --- a/src/scripts/pre-commit.js +++ b/src/scripts/pre-commit.js @@ -1,6 +1,6 @@ const path = require('path'); const spawn = require('cross-spawn'); -const { hasPkgProp, hasFile, resolveBin } = require('../utils'); +const { hasPkgProp, hasFile, ifScript, resolveBin } = require('../utils'); const here = p => path.join(__dirname, p); const hereRelative = p => here(p).replace(process.cwd(), '.'); @@ -19,7 +19,7 @@ const lintStagedResult = spawn.sync(resolveBin('lint-staged'), [...config, ...ar stdio: 'inherit', }); -if (lintStagedResult.status === 0) { +if (lintStagedResult.status === 0 && ifScript('validate', true)) { const validateResult = spawn.sync('npm', ['run', 'validate'], { stdio: 'inherit', }); From 398138c816daa4f5cc64f66a35296c8824f3291a Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Mon, 17 Feb 2020 11:38:29 -0500 Subject: [PATCH 20/48] ci: lockdown checkout action to v1 --- .github/workflows/release.yml | 2 +- .github/workflows/validate.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 81a26106..073d4c8c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v1 - uses: actions/setup-node@v1 with: diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 2b8737e5..84a2ebde 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -11,7 +11,7 @@ jobs: node: [10.x, 11.x, 12.x] steps: - - uses: actions/checkout@master + - uses: actions/checkout@v1 - uses: actions/setup-node@v1 with: From 5912efde982d24dd89f4b8e9b6896753dac08796 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Mon, 30 Mar 2020 23:58:34 -0400 Subject: [PATCH 21/48] fix(jest): ensure src directory exists before using it as root --- src/config/jest.config.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/config/jest.config.js b/src/config/jest.config.js index 1b211ebb..aac38a79 100644 --- a/src/config/jest.config.js +++ b/src/config/jest.config.js @@ -15,8 +15,10 @@ const ignores = [ '__mocks__', ]; +const hasSrcDir = hasFile('src'); + const jestConfig = { - roots: [fromRoot('src')], + roots: [fromRoot(hasSrcDir ? 'src' : '')], testEnvironment: ifAnyDep(['webpack', 'rollup', 'react'], 'jsdom', 'node'), testURL: 'http://localhost', moduleFileExtensions: ['js', 'jsx', 'json', 'ts', 'tsx'], From 4d83442e7f52ee7636f3ddb9fcba327dc20185eb Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Tue, 31 Mar 2020 12:12:07 -0400 Subject: [PATCH 22/48] style: fix linting errors --- src/__tests__/index.js | 2 +- src/config/__tests__/umbrella.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/__tests__/index.js b/src/__tests__/index.js index c7249e0e..43c837ba 100644 --- a/src/__tests__/index.js +++ b/src/__tests__/index.js @@ -28,7 +28,7 @@ cases( if (signal) { crossSpawnSyncMock.mockReturnValueOnce({ result: 1, signal }); } - require('../'); + require('..'); if (snapshotLog) { expect(console.log.mock.calls).toMatchSnapshot(); } else if (signal) { diff --git a/src/config/__tests__/umbrella.js b/src/config/__tests__/umbrella.js index 45e09478..1edb1d54 100644 --- a/src/config/__tests__/umbrella.js +++ b/src/config/__tests__/umbrella.js @@ -7,5 +7,5 @@ test('requiring some files does not blow up', () => { require('../lintstagedrc'); require('../prettierrc'); require('../rollup.config'); - require('../').getRollupConfig(); + require('..').getRollupConfig(); }); From bcc7a440cff93cca51aaebf2b452d9f9402fed35 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Wed, 22 Apr 2020 09:05:32 -0400 Subject: [PATCH 23/48] docs: update readme badges --- README.md | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 15079609..e0b3cce3 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,8 @@
-[![Build Status][build-badge]][build] [![Code Coverage][coverage-badge]][coverage] [![version][version-badge]][package] [![downloads][downloads-badge]][npmcharts] [![MIT License][license-badge]][license] [![PRs Welcome][prs-badge]][prs] -[![Code of Conduct][coc-badge]][coc] [![Watch on GitHub][github-watch-badge]][github-watch] -[![Star on GitHub][github-star-badge]][github-star] [![Tweet][twitter-badge]][twitter] ## The problem @@ -135,7 +132,8 @@ loaded when you use the default babel config that comes with `cod-scripts`. If y ## Inspiration -This was forked from `kentcdodds/kcd-scripts`. This is inspired by `react-scripts`. +This was forked from `kentcdodds/kcd-scripts`. This is +[inspired by `react-scripts`](https://github.com/kentcdodds/kcd-scripts#inspiration). ## LICENSE @@ -143,26 +141,11 @@ MIT [npm]: https://www.npmjs.com/ [node]: https://nodejs.org -[build-badge]: https://img.shields.io/travis/codfish/cod-scripts.svg?style=flat-square -[build]: https://travis-ci.org/codfish/cod-scripts -[coverage-badge]: https://img.shields.io/codecov/c/github/codfish/cod-scripts.svg?style=flat-square -[coverage]: https://codecov.io/github/codfish/cod-scripts +[npmcharts]: http://npmcharts.com/compare/cod-scripts [version-badge]: https://img.shields.io/npm/v/cod-scripts.svg?style=flat-square [package]: https://www.npmjs.com/package/cod-scripts [downloads-badge]: https://img.shields.io/npm/dm/cod-scripts.svg?style=flat-square -[npmcharts]: http://npmcharts.com/compare/cod-scripts [license-badge]: https://img.shields.io/npm/l/cod-scripts.svg?style=flat-square [license]: https://github.com/codfish/cod-scripts/blob/master/LICENSE [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square [prs]: http://makeapullrequest.com -[donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square -[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square -[coc]: https://github.com/codfish/cod-scripts/blob/master/other/CODE_OF_CONDUCT.md -[github-watch-badge]: https://img.shields.io/github/watchers/codfish/cod-scripts.svg?style=social -[github-watch]: https://github.com/codfish/cod-scripts/watchers -[github-star-badge]: https://img.shields.io/github/stars/codfish/cod-scripts.svg?style=social -[github-star]: https://github.com/codfish/cod-scripts/stargazers -[twitter]: - https://twitter.com/intent/tweet?text=Check%20out%20cod-scripts!%20https://github.com/codfish/cod-scripts%20%F0%9F%91%8D -[twitter-badge]: - https://img.shields.io/twitter/url/https/github.com/codfish/cod-scripts.svg?style=social From 6fc06edd693df814c5ba457116b7d2d89cc3be83 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Wed, 22 Apr 2020 09:27:14 -0400 Subject: [PATCH 24/48] docs: update readme motivation --- README.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e0b3cce3..55c80032 100644 --- a/README.md +++ b/README.md @@ -9,14 +9,10 @@ [![version][version-badge]][package] [![downloads][downloads-badge]][npmcharts] [![MIT License][license-badge]][license] [![PRs Welcome][prs-badge]][prs] -## The problem +## Motivation -I do a bunch of open source and want to make it easier to maintain so many projects. - -## This solution - -This is a CLI that abstracts away all configuration for my open source projects for linting, -testing, building, and more. +This helps me maintain personal & work projects without duplication. This is a CLI that abstracts +away all configuration for my open source projects for linting, testing, building, and more. ## Table of Contents From 104cbb9dc133da121aded507fdea3f1872577bcd Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 23 Apr 2020 08:29:43 -0400 Subject: [PATCH 25/48] docs: add build badge --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 55c80032..ea373b6b 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@
[![version][version-badge]][package] [![downloads][downloads-badge]][npmcharts] -[![MIT License][license-badge]][license] [![PRs Welcome][prs-badge]][prs] +[![GitHub Workflow Status][actions-badge]][actions-badge] [![MIT License][license-badge]][license] +[![PRs Welcome][prs-badge]][prs] ## Motivation @@ -145,3 +146,4 @@ MIT [license]: https://github.com/codfish/cod-scripts/blob/master/LICENSE [prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square [prs]: http://makeapullrequest.com +[actions-badge]: https://img.shields.io/github/workflow/status/codfish/cod-scripts/Release/master From 0d59533a1def53a5cbad582e68625ef92f528b27 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 23 Apr 2020 08:54:32 -0400 Subject: [PATCH 26/48] docs: update readme badges --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ea373b6b..4a56a8fd 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ [![version][version-badge]][package] [![downloads][downloads-badge]][npmcharts] [![GitHub Workflow Status][actions-badge]][actions-badge] [![MIT License][license-badge]][license] -[![PRs Welcome][prs-badge]][prs] +[![PRs Welcome][prs-badge]][prs] [![Semantic Release][semantic-release-badge]][semantic-release] +[![Commitizen friendly][commitizen-badge]][commitizen] ## Motivation @@ -138,12 +139,18 @@ MIT [npm]: https://www.npmjs.com/ [node]: https://nodejs.org +[semantic-release]: https://github.com/semantic-release/semantic-release +[semantic-release-badge]: + https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg +[prs]: http://makeapullrequest.com +[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square +[commitizen]: http://commitizen.github.io/cz-cli/ +[commitizen-badge]: https://img.shields.io/badge/commitizen-friendly-brightgreen.svg [npmcharts]: http://npmcharts.com/compare/cod-scripts [version-badge]: https://img.shields.io/npm/v/cod-scripts.svg?style=flat-square [package]: https://www.npmjs.com/package/cod-scripts [downloads-badge]: https://img.shields.io/npm/dm/cod-scripts.svg?style=flat-square [license-badge]: https://img.shields.io/npm/l/cod-scripts.svg?style=flat-square [license]: https://github.com/codfish/cod-scripts/blob/master/LICENSE -[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square -[prs]: http://makeapullrequest.com +[actions]: https://github.com/codfish/cod-scripts/actions [actions-badge]: https://img.shields.io/github/workflow/status/codfish/cod-scripts/Release/master From c05f47c148d6fa13a1747bccbeb1ef25e36ff187 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sat, 25 Apr 2020 12:21:19 -0400 Subject: [PATCH 27/48] fix: add missing script in spawnScript --- src/run-script.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/run-script.js b/src/run-script.js index eca4fbc8..e0801405 100755 --- a/src/run-script.js +++ b/src/run-script.js @@ -46,6 +46,7 @@ function spawnScript() { x => x === 'format' || x === 'lint' || + x === 'commitlint' || x === 'pre-commit' || x === 'test' || x === 'validate' || From 43abbfc17c362434ea4e2a6710318d0b63228cb8 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 10 Sep 2020 15:16:17 -0400 Subject: [PATCH 28/48] feat: bump deps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE: Bumping a number of different dependencies to a new major version, possibly causing some breaking changes downstream. Because of the nature of this package, I consider eslint rule changes to be breaking cause a consumer may see failures after upgrading, so IMO it is worth the major version bump here. Major Version Changes: @commitlint/cli ^8.1.0 ❯ 9.1.2 https://github.com/conventional-changelog/commitlint#readme @commitlint/config-conventional ^8.1.0 ❯ 11.0.0 https://github.com/conventional-changelog/commitlint#readme @rollup/plugin-commonjs ^11.0.2 ❯ 15.0.0 https://github.com/rollup/plugins/tree/master/packages/commonjs/#readme @rollup/plugin-node-resolve ^7.1.1 ❯ 9.0.0 https://github.com/rollup/plugins/tree/master/packages/node-resolve/#readme @types/jest ^25.1.2 ❯ 26.0.1 https://github.com/DefinitelyTyped/DefinitelyTyped babel-jest ^25.1.0 ❯ 26.3.0 https://github.com/facebook/jest#readme cosmiconfig ^6.0.0 ❯ 7.0.0 https://github.com/davidtheclark/cosmiconfig#readme eslint ^6.8.0 ❯ 7.8.1 https://eslint.org eslint-config-codfish ^5.3.0 ❯ 6.0.1 https://github.com/codfish/eslint-config-codfish#readme jest ^25.1.0 ❯ 26.4.2 https://jestjs.io/ jest-watch-typeahead ^0.4.2 ❯ 0.6.1 https://github.com/jest-community/jest-watch-typeahead prettier ^1.16.4 ❯ 2.1.1 https://prettier.io rollup ^1.19.4 ❯ 2.26.1 https://rollupjs.org/ rollup-plugin-size-snapshot ^0.11.0 ❯ 0.12.0 https://github.com/TrySound/rollup-plugin-size-snapshot rollup-plugin-terser ^5.1.1 ❯ 7.0.2 https://github.com/TrySound/rollup-plugin-terser yargs-parser ^16.1.0 ❯ 20.0.0 https://github.com/yargs/yargs-parser#readme --- .github/ISSUE_TEMPLATE.md | 1 + package.json | 71 ++++++++++++++++++------------------- src/config/rollup.config.js | 29 ++++++++++++--- src/utils.js | 1 + 4 files changed, 61 insertions(+), 41 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 290edf53..87d61059 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -18,6 +18,7 @@ learn how: http://kcd.im/pull-request Relevant code or config ```javascript + ``` What you did: diff --git a/package.json b/package.json index a807b294..9d958761 100644 --- a/package.json +++ b/package.json @@ -32,61 +32,60 @@ "author": "Chris O'Donnell (http://codfish.io/)", "license": "MIT", "dependencies": { - "@babel/cli": "^7.6.4", - "@babel/core": "^7.6.4", - "@babel/plugin-proposal-class-properties": "^7.5.5", - "@babel/plugin-transform-modules-commonjs": "^7.5.0", - "@babel/plugin-transform-runtime": "^7.5.5", - "@babel/preset-env": "^7.6.3", - "@babel/preset-flow": "^7.0.0", - "@babel/preset-react": "^7.6.3", - "@babel/runtime": "^7.6.3", - "@commitlint/cli": "^8.1.0", - "@commitlint/config-conventional": "^8.1.0", - "@rollup/plugin-commonjs": "^11.0.2", - "@rollup/plugin-json": "^4.0.2", - "@rollup/plugin-node-resolve": "^7.1.1", - "@rollup/plugin-replace": "^2.3.1", - "@types/jest": "^25.1.2", + "@babel/cli": "^7.11.6", + "@babel/core": "^7.11.6", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-runtime": "^7.11.5", + "@babel/preset-env": "^7.11.5", + "@babel/preset-flow": "^7.10.4", + "@babel/preset-react": "^7.10.4", + "@babel/runtime": "^7.11.2", + "@commitlint/cli": "^9.1.2", + "@commitlint/config-conventional": "^11.0.0", + "@rollup/plugin-babel": "^5.2.1", + "@rollup/plugin-commonjs": "^15.0.0", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^9.0.0", + "@rollup/plugin-replace": "^2.3.3", "arrify": "^2.0.1", - "babel-jest": "^25.1.0", + "babel-jest": "^26.3.0", "babel-plugin-macros": "^2.6.1", "babel-plugin-minify-dead-code-elimination": "^0.5.0", "babel-plugin-module-resolver": "^4.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.0", "babel-plugin-transform-react-remove-prop-types": "^0.4.21", - "browserslist": "^4.7.2", - "concurrently": "^5.1.0", - "cosmiconfig": "^6.0.0", + "browserslist": "^4.14.2", + "concurrently": "^5.3.0", + "cosmiconfig": "^7.0.0", "cross-env": "^7.0.0", - "cross-spawn": "^7.0.1", + "cross-spawn": "^7.0.3", "doctoc": "^1.4.0", - "eslint": "^6.8.0", - "eslint-config-codfish": "^5.3.0", + "eslint": "^7.8.1", + "eslint-config-codfish": "^6.0.1", "glob": "^7.1.5", - "husky": "^4.2.1", + "husky": "^4.3.0", "is-ci": "^2.0.0", - "jest": "^25.1.0", - "jest-watch-typeahead": "^0.4.2", - "lint-staged": "^10.0.7", + "jest": "^26.4.2", + "jest-watch-typeahead": "^0.6.1", + "lint-staged": "^10.3.0", "lodash.camelcase": "^4.3.0", "lodash.has": "^4.5.2", "lodash.omit": "^4.5.0", - "mkdirp": "^1.0.3", - "prettier": "^1.16.4", + "mkdirp": "^1.0.4", + "prettier": "^2.1.1", "react-app-polyfill": "^1.0.3", "read-pkg-up": "^7.0.1", - "resolve": "^1.12.0", + "resolve": "^1.17.0", "rimraf": "^3.0.0", - "rollup": "^1.19.4", - "rollup-plugin-babel": "^4.3.3", + "rollup": "^2.26.11", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", - "rollup-plugin-size-snapshot": "^0.11.0", - "rollup-plugin-terser": "^5.1.1", - "semver": "^7.1.2", + "rollup-plugin-size-snapshot": "^0.12.0", + "rollup-plugin-terser": "^7.0.2", + "semver": "^7.3.2", "which": "^2.0.2", - "yargs-parser": "^16.1.0" + "yargs-parser": "^20.0.0" }, "eslintConfig": { "extends": [ diff --git a/src/config/rollup.config.js b/src/config/rollup.config.js index f2469ec1..9b49ff1c 100644 --- a/src/config/rollup.config.js +++ b/src/config/rollup.config.js @@ -1,17 +1,28 @@ const path = require('path'); +const { babel: rollupBabel } = require('@rollup/plugin-babel'); const commonjs = require('@rollup/plugin-commonjs'); const json = require('@rollup/plugin-json'); -const nodeResolve = require('@rollup/plugin-node-resolve'); +const { DEFAULTS: nodeResolveDefaults, nodeResolve } = require('@rollup/plugin-node-resolve'); + const replace = require('@rollup/plugin-replace'); const glob = require('glob'); const camelcase = require('lodash.camelcase'); -const rollupBabel = require('rollup-plugin-babel'); const { terser } = require('rollup-plugin-terser'); const nodeBuiltIns = require('rollup-plugin-node-builtins'); const nodeGlobals = require('rollup-plugin-node-globals'); const { sizeSnapshot } = require('rollup-plugin-size-snapshot'); const omit = require('lodash.omit'); -const { pkg, hasFile, hasPkgProp, parseEnv, fromRoot, uniq, writeExtraEntry } = require('../utils'); +const { + pkg, + hasFile, + hasPkgProp, + hasDep, + hasTypescript, + parseEnv, + fromRoot, + uniq, + writeExtraEntry, +} = require('../utils'); const here = p => path.join(__dirname, p); const capitalize = s => s[0].toUpperCase() + s.slice(1); @@ -36,7 +47,9 @@ const deps = Object.keys(pkg.dependencies || {}); const peerDeps = Object.keys(pkg.peerDependencies || {}); const defaultExternal = umd ? peerDeps : deps.concat(peerDeps); -const input = glob.sync(fromRoot(process.env.BUILD_INPUT || 'src/index.js')); +const input = glob.sync( + fromRoot(process.env.BUILD_INPUT || (hasTypescript ? 'src/index.{js,ts,tsx}' : 'src/index.js')), +); const codeSplitting = input.length > 1; if (codeSplitting && uniq(input.map(single => path.basename(single))).length !== input.length) { @@ -117,6 +130,10 @@ const replacements = Object.entries(umd ? process.env : omit(process.env, ['NODE {}, ); +const extensions = hasTypescript + ? [...nodeResolveDefaults.extensions, '.ts', '.tsx'] + : nodeResolveDefaults.extensions; + module.exports = { input: codeSplitting ? input : input[0], output, @@ -127,13 +144,15 @@ module.exports = { nodeResolve({ preferBuiltins: isNode, mainFields: ['module', 'main', 'jsnext', 'browser'], + extensions, }), commonjs({ include: 'node_modules/**' }), json(), rollupBabel({ presets: babelPresets, babelrc: !useBuiltinConfig, - runtimeHelpers: useBuiltinConfig, + babelHelpers: hasDep('@babel/runtime') ? 'runtime' : 'bundled', + extensions, }), replace(replacements), useSizeSnapshot ? sizeSnapshot({ printInfo: false }) : null, diff --git a/src/utils.js b/src/utils.js index ed396b12..0fba0857 100644 --- a/src/utils.js +++ b/src/utils.js @@ -159,6 +159,7 @@ module.exports = { hasLocalConfig, hasPkgProp, hasScript, + hasDep, ifAnyDep, ifDep, ifDevDep, From 7bd4877dfcb81e33cf94d3b02c57d29175ebb5c2 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sun, 1 Nov 2020 11:04:27 -0500 Subject: [PATCH 29/48] feat: bump deps --- package.json | 58 ++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/package.json b/package.json index 9d958761..26a23bfa 100644 --- a/package.json +++ b/package.json @@ -32,60 +32,64 @@ "author": "Chris O'Donnell (http://codfish.io/)", "license": "MIT", "dependencies": { - "@babel/cli": "^7.11.6", - "@babel/core": "^7.11.6", - "@babel/plugin-proposal-class-properties": "^7.10.4", - "@babel/plugin-transform-modules-commonjs": "^7.10.4", - "@babel/plugin-transform-runtime": "^7.11.5", - "@babel/preset-env": "^7.11.5", - "@babel/preset-flow": "^7.10.4", - "@babel/preset-react": "^7.10.4", - "@babel/runtime": "^7.11.2", - "@commitlint/cli": "^9.1.2", + "@babel/cli": "^7.12.1", + "@babel/core": "^7.12.3", + "@babel/plugin-proposal-class-properties": "^7.12.1", + "@babel/plugin-transform-modules-commonjs": "^7.12.1", + "@babel/plugin-transform-runtime": "^7.12.1", + "@babel/preset-env": "^7.12.1", + "@babel/preset-flow": "^7.12.1", + "@babel/preset-react": "^7.12.1", + "@babel/runtime": "^7.12.1", + "@commitlint/cli": "^11.0.0", "@commitlint/config-conventional": "^11.0.0", "@rollup/plugin-babel": "^5.2.1", - "@rollup/plugin-commonjs": "^15.0.0", + "@rollup/plugin-commonjs": "^16.0.0", "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^9.0.0", - "@rollup/plugin-replace": "^2.3.3", + "@rollup/plugin-node-resolve": "^10.0.0", + "@rollup/plugin-replace": "^2.3.4", "arrify": "^2.0.1", - "babel-jest": "^26.3.0", + "babel-jest": "^26.6.1", "babel-plugin-macros": "^2.6.1", "babel-plugin-minify-dead-code-elimination": "^0.5.0", "babel-plugin-module-resolver": "^4.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.0", "babel-plugin-transform-react-remove-prop-types": "^0.4.21", - "browserslist": "^4.14.2", + "browserslist": "^4.14.6", "concurrently": "^5.3.0", "cosmiconfig": "^7.0.0", "cross-env": "^7.0.0", "cross-spawn": "^7.0.3", "doctoc": "^1.4.0", - "eslint": "^7.8.1", - "eslint-config-codfish": "^6.0.1", + "eslint": "^7.12.1", + "eslint-config-codfish": "^7.0.0", "glob": "^7.1.5", "husky": "^4.3.0", "is-ci": "^2.0.0", - "jest": "^26.4.2", + "jest": "^26.6.1", "jest-watch-typeahead": "^0.6.1", - "lint-staged": "^10.3.0", + "lint-staged": "^10.5.1", "lodash.camelcase": "^4.3.0", "lodash.has": "^4.5.2", "lodash.omit": "^4.5.0", "mkdirp": "^1.0.4", - "prettier": "^2.1.1", - "react-app-polyfill": "^1.0.3", + "prettier": "^2.1.2", + "react-app-polyfill": "^2.0.0", "read-pkg-up": "^7.0.1", - "resolve": "^1.17.0", + "resolve": "^1.18.1", "rimraf": "^3.0.0", - "rollup": "^2.26.11", + "rollup": "^2.33.0", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "rollup-plugin-size-snapshot": "^0.12.0", "rollup-plugin-terser": "^7.0.2", "semver": "^7.3.2", "which": "^2.0.2", - "yargs-parser": "^20.0.0" + "yargs-parser": "^20.2.3" + }, + "devDependencies": { + "jest-in-case": "^1.0.2", + "slash": "^3.0.0" }, "eslintConfig": { "extends": [ @@ -136,9 +140,5 @@ "bugs": { "url": "https://github.com/codfish/cod-scripts/issues" }, - "homepage": "https://github.com/codfish/cod-scripts#readme", - "devDependencies": { - "jest-in-case": "^1.0.2", - "slash": "^3.0.0" - } + "homepage": "https://github.com/codfish/cod-scripts#readme" } From 9440bfb67037195d50783f30c5da0e1437a0eb51 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Mon, 7 Dec 2020 00:40:49 -0500 Subject: [PATCH 30/48] feat: bump deps --- package.json | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 88a91dc4..eeb8e38c 100644 --- a/package.json +++ b/package.json @@ -34,60 +34,60 @@ "author": "Chris O'Donnell (http://codfish.io/)", "license": "MIT", "dependencies": { - "@babel/cli": "^7.12.1", - "@babel/core": "^7.12.3", + "@babel/cli": "^7.12.8", + "@babel/core": "^7.12.9", "@babel/plugin-proposal-class-properties": "^7.12.1", "@babel/plugin-transform-modules-commonjs": "^7.12.1", "@babel/plugin-transform-runtime": "^7.12.1", - "@babel/preset-env": "^7.12.1", - "@babel/preset-react": "^7.12.5", - "@babel/preset-typescript": "^7.12.1", + "@babel/preset-env": "^7.12.7", + "@babel/preset-react": "^7.12.7", + "@babel/preset-typescript": "^7.12.7", "@babel/runtime": "^7.12.5", "@commitlint/cli": "^11.0.0", "@commitlint/config-conventional": "^11.0.0", - "@rollup/plugin-babel": "^5.2.1", - "@rollup/plugin-commonjs": "^16.0.0", + "@rollup/plugin-babel": "^5.2.2", + "@rollup/plugin-commonjs": "^17.0.0", "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^10.0.0", + "@rollup/plugin-node-resolve": "^11.0.0", "@rollup/plugin-replace": "^2.3.4", - "@types/jest": "^26.0.15", + "@types/jest": "^26.0.16", "arrify": "^2.0.1", "babel-jest": "^26.6.3", - "babel-plugin-macros": "^2.6.1", + "babel-plugin-macros": "^3.0.0", "babel-plugin-minify-dead-code-elimination": "^0.5.0", "babel-plugin-module-resolver": "^4.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.0", "babel-plugin-transform-react-remove-prop-types": "^0.4.21", - "browserslist": "^4.14.7", + "browserslist": "^4.15.0", "chalk": "^4.1.0", "concurrently": "^5.3.0", "cosmiconfig": "^7.0.0", - "cross-env": "^7.0.0", + "cross-env": "^7.0.3", "cross-spawn": "^7.0.3", "doctoc": "^1.4.0", - "eslint": "^7.13.0", - "eslint-config-codfish": "^8.0.0", + "eslint": "^7.15.0", + "eslint-config-codfish": "^8.1.0", "glob": "^7.1.5", "husky": "^4.3.0", "is-ci": "^2.0.0", "jest": "^26.6.1", "jest-watch-typeahead": "^0.6.1", - "lint-staged": "^10.5.1", + "lint-staged": "^10.5.3", "lodash.camelcase": "^4.3.0", "lodash.has": "^4.5.2", "lodash.omit": "^4.5.0", "mkdirp": "^1.0.4", - "prettier": "^2.1.2", + "prettier": "^2.2.1", "react-app-polyfill": "^2.0.0", "read-pkg-up": "^7.0.1", "resolve": "^1.19.0", "rimraf": "^3.0.0", - "rollup": "^2.33.2", + "rollup": "^2.34.2", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "rollup-plugin-size-snapshot": "^0.12.0", "rollup-plugin-terser": "^7.0.2", - "semver": "^7.3.2", + "semver": "^7.3.4", "which": "^2.0.2", "yargs-parser": "^20.2.4" }, From f16901cba665ac7b81bea08362f44d764ae71833 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Tue, 8 Dec 2020 12:40:52 -0500 Subject: [PATCH 31/48] feat: update deps --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 98e8a639..1b3e5588 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^11.0.0", "@rollup/plugin-replace": "^2.3.4", - "@types/jest": "^26.0.16", + "@types/jest": "^26.0.17", "arrify": "^2.0.1", "babel-jest": "^26.6.3", "babel-plugin-macros": "^3.0.0", @@ -65,12 +65,12 @@ "cosmiconfig": "^7.0.0", "cross-env": "^7.0.3", "cross-spawn": "^7.0.3", - "doctoc": "^1.4.0", + "doctoc": "^2.0.0", "eslint": "^7.15.0", - "eslint-config-codfish": "^8.1.0", - "eslint-config-prettier": "^6.15.0", + "eslint-config-codfish": "^8.2.0", + "eslint-config-prettier": "^7.0.0", "glob": "^7.1.5", - "husky": "^4.3.0", + "husky": "^4.3.5", "is-ci": "^2.0.0", "jest": "^26.6.1", "jest-serializer-path": "^0.1.15", From c13b516dae24cd9fe354481caf757285dbbff6c8 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Tue, 8 Dec 2020 12:53:14 -0500 Subject: [PATCH 32/48] feat: turn off commitlint in ci to prevent failures from upstream --- .github/workflows/validate.yml | 10 +--------- package.json | 19 +++++-------------- 2 files changed, 6 insertions(+), 23 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 27264963..4b433eda 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: - node: [10.x, 11.x, 12.x] + node: [10.x, 11.x, 12.x, 14.x] steps: - uses: actions/checkout@v1 @@ -22,14 +22,6 @@ jobs: env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - name: lint commits - run: - npx commitlint --config="./src/config/commitlint.config.js" - --from="origin/${{ github.base_ref }}" --to="origin/${{github.head_ref - }}" - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - - run: npm run build env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/package.json b/package.json index 1b3e5588..aa4ad755 100644 --- a/package.json +++ b/package.json @@ -116,20 +116,11 @@ "./src/config/commitlint.config" ], "rules": { - "scope-enum": [ - 2, - "always", - [ - "eslint", - "babel", - "rollup", - "commitlint", - "jest", - "lintstaged", - "lint-staged", - "husky", - "prettier" - ] + "scope-case": [ + 0 + ], + "subject-case": [ + 0 ] } }, From ab8c8ce9c3190dd16f824fd3dbb63b8d81998929 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 25 Feb 2021 20:56:58 -0500 Subject: [PATCH 33/48] fix: use built in prettier config for eslint if no local config found --- src/config/eslintrc.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/config/eslintrc.js b/src/config/eslintrc.js index 2aed3144..6ac90da4 100644 --- a/src/config/eslintrc.js +++ b/src/config/eslintrc.js @@ -1,8 +1,17 @@ const prettierConfig = require('./prettierrc'); +const { hasLocalConfig } = require('../utils'); + +const args = process.argv.slice(2); + +const useBuiltinConfig = + !args.includes('--config') && !hasLocalConfig('prettier'); +const ruleValue = useBuiltinConfig ? ['error', prettierConfig] : 'error'; module.exports = { extends: [require.resolve('eslint-config-codfish')].filter(Boolean), rules: { - 'prettier/prettier': ['error', prettierConfig], + // Explicitly set prettier rules to use our built in config if no + // local prettier config is found. + 'prettier/prettier': ruleValue, }, }; From 81bd3f94cc5c9f76ff1d920db941de334cb39e58 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 25 Feb 2021 20:57:25 -0500 Subject: [PATCH 34/48] style: update eslint to line up with upstream --- jest.config.js | 5 ++- package.json | 15 +++++++- src/__tests__/utils.js | 4 ++- src/config/babelrc.js | 43 ++++++++++++++++++----- src/config/jest.config.js | 21 +++++++++--- src/config/lintstagedrc.js | 5 ++- src/config/rollup.config.js | 68 ++++++++++++++++++++++++------------- src/run-script.js | 3 +- src/scripts/build/babel.js | 13 +++++-- src/scripts/build/rollup.js | 16 ++++++--- src/scripts/commitlint.js | 4 ++- src/scripts/format.js | 31 ++++++++++++----- src/scripts/lint.js | 22 +++++++++--- src/scripts/pre-commit.js | 4 ++- src/scripts/test.js | 4 ++- src/scripts/typecheck.js | 10 ++++-- src/scripts/validate.js | 21 +++++++++--- src/utils.js | 30 +++++++++++----- 18 files changed, 240 insertions(+), 79 deletions(-) diff --git a/jest.config.js b/jest.config.js index f0d8dab1..f6fbc3c1 100644 --- a/jest.config.js +++ b/jest.config.js @@ -2,5 +2,8 @@ const { jest: jestConfig } = require('./src/config'); module.exports = Object.assign(jestConfig, { coverageThreshold: null, - testPathIgnorePatterns: [...jestConfig.testPathIgnorePatterns, './src/scripts/test.js'], + testPathIgnorePatterns: [ + ...jestConfig.testPathIgnorePatterns, + './src/scripts/test.js', + ], }); diff --git a/package.json b/package.json index aa4ad755..8854f4bc 100644 --- a/package.json +++ b/package.json @@ -102,13 +102,26 @@ "no-console": "off", "no-process-exit": "off", "global-require": "off", + "no-prototype-builtins": "off", "no-useless-catch": "off", "import/no-dynamic-require": "off", "import/no-unassigned-import": "off", "no-nested-ternary": "off", "no-use-before-define": "off", "no-restricted-syntax": "off", - "no-param-reassign": "off" + "no-param-reassign": "off", + "max-len": [ + "error", + 80, + 2, + { + "ignoreUrls": true, + "ignoreComments": true, + "ignoreRegExpLiterals": true, + "ignoreStrings": true, + "ignoreTemplateLiterals": true + } + ] } }, "commitlint": { diff --git a/src/__tests__/utils.js b/src/__tests__/utils.js index f507e05a..1bed4d4f 100644 --- a/src/__tests__/utils.js +++ b/src/__tests__/utils.js @@ -117,7 +117,9 @@ test('parseEnv parses the existing environment variable', () => { test(`parseEnv returns the default if the environment variable doesn't exist`, () => { const defaultVal = { hello: 'world' }; - expect(require('../utils').parseEnv('DOES_NOT_EXIST', defaultVal)).toBe(defaultVal); + expect(require('../utils').parseEnv('DOES_NOT_EXIST', defaultVal)).toBe( + defaultVal, + ); }); test('ifAnyDep returns the true argument if true and false argument if false', () => { diff --git a/src/config/babelrc.js b/src/config/babelrc.js index 1be78a6b..dc4c871d 100644 --- a/src/config/babelrc.js +++ b/src/config/babelrc.js @@ -1,7 +1,14 @@ const browserslist = require('browserslist'); const semver = require('semver'); -const { ifDep, ifAnyDep, ifTypescript, parseEnv, appDirectory, pkg } = require('../utils'); +const { + ifDep, + ifAnyDep, + ifTypescript, + parseEnv, + appDirectory, + pkg, +} = require('../utils'); const { BABEL_ENV, NODE_ENV, BUILD_FORMAT } = process.env; const isTest = (BABEL_ENV || NODE_ENV) === 'test'; @@ -13,7 +20,9 @@ const isWebpack = parseEnv('BUILD_WEBPACK', false); const treeshake = parseEnv('BUILD_TREESHAKE', isRollup || isWebpack); const alias = parseEnv('BUILD_ALIAS', isPreact ? { react: 'preact' } : null); -const hasBabelRuntimeDep = Boolean(pkg.dependencies && pkg.dependencies['@babel/runtime']); +const hasBabelRuntimeDep = Boolean( + pkg.dependencies && pkg.dependencies['@babel/runtime'], +); const RUNTIME_HELPERS_WARN = 'You should add @babel/runtime as dependency to your package. It will allow reusing "babel helpers" from node_modules rather than bundling their copies into your files.'; @@ -44,7 +53,10 @@ function getNodeVersion({ engines: { node: nodeVersion = '10.13' } = {} }) { * * @see https://github.com/browserslist/browserslist/blob/master/node.js#L139 */ -const browsersConfig = browserslist.loadConfig({ path: appDirectory }) || ['ie 10', 'ios 7']; +const browsersConfig = browserslist.loadConfig({ path: appDirectory }) || [ + 'ie 10', + 'ios 7', +]; const envTargets = isTest ? { node: 'current' } @@ -66,16 +78,31 @@ module.exports = () => ({ ifTypescript([require.resolve('@babel/preset-typescript')]), ].filter(Boolean), plugins: [ - [require.resolve('@babel/plugin-transform-runtime'), { useESModules: treeshake && !isCJS }], + [ + require.resolve('@babel/plugin-transform-runtime'), + { useESModules: treeshake && !isCJS }, + ], require.resolve('babel-plugin-macros'), - alias ? [require.resolve('babel-plugin-module-resolver'), { root: ['./src'], alias }] : null, + alias + ? [ + require.resolve('babel-plugin-module-resolver'), + { root: ['./src'], alias }, + ] + : null, [ require.resolve('babel-plugin-transform-react-remove-prop-types'), isPreact ? { removeImport: true } : { mode: 'unsafe-wrap' }, ], - isUMD ? require.resolve('babel-plugin-transform-inline-environment-variables') : null, - [require.resolve('@babel/plugin-proposal-class-properties'), { loose: true }], + isUMD + ? require.resolve('babel-plugin-transform-inline-environment-variables') + : null, + [ + require.resolve('@babel/plugin-proposal-class-properties'), + { loose: true }, + ], require.resolve('babel-plugin-minify-dead-code-elimination'), - treeshake ? null : require.resolve('@babel/plugin-transform-modules-commonjs'), + treeshake + ? null + : require.resolve('@babel/plugin-transform-modules-commonjs'), ].filter(Boolean), }); diff --git a/src/config/jest.config.js b/src/config/jest.config.js index 8a140091..ae13d5b2 100644 --- a/src/config/jest.config.js +++ b/src/config/jest.config.js @@ -20,9 +20,17 @@ const jestConfig = { testEnvironment: ifAnyDep(['webpack', 'rollup', 'react'], 'jsdom', 'node'), testURL: 'http://localhost', moduleFileExtensions: ['js', 'jsx', 'json', 'ts', 'tsx'], - moduleDirectories: ['node_modules', fromRoot('src'), 'shared', fromRoot('tests')], + moduleDirectories: [ + 'node_modules', + fromRoot('src'), + 'shared', + fromRoot('tests'), + ], collectCoverageFrom: ['src/**/*.+(js|jsx|ts|tsx)'], - testMatch: ['**/__tests__/**/*.+(js|jsx|ts|tsx)', '**/?(*.)+(spec|test).[jt]s?(x)'], + testMatch: [ + '**/__tests__/**/*.+(js|jsx|ts|tsx)', + '**/?(*.)+(spec|test).[jt]s?(x)', + ], testPathIgnorePatterns: [...ignores], coveragePathIgnorePatterns: [...ignores, 'src/(umd|cjs|esm)-entry.js$'], transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx)$'], @@ -41,7 +49,10 @@ const jestConfig = { }; const setupFilesAfterEnv = [ - ifAnyDep('@testing-library/jest-dom', '@testing-library/jest-dom/extend-expect'), + ifAnyDep( + '@testing-library/jest-dom', + '@testing-library/jest-dom/extend-expect', + ), ifFile('jest.setup.js', fromRoot('jest.setup.js')), ifFile('setupTests.js', fromRoot('setupTests.js')), ifFile('setupTests.js', fromRoot('setupTests.js')), @@ -55,7 +66,9 @@ if (setupFilesAfterEnv.length) { } if (useBuiltInBabelConfig) { - jestConfig.transform = { '^.+\\.(js|jsx|ts|tsx)$': here('./babel-transform') }; + jestConfig.transform = { + '^.+\\.(js|jsx|ts|tsx)$': here('./babel-transform'), + }; } if (jestConfig.testEnvironment === 'jsdom') { diff --git a/src/config/lintstagedrc.js b/src/config/lintstagedrc.js index 18a35bb2..1245b6e8 100644 --- a/src/config/lintstagedrc.js +++ b/src/config/lintstagedrc.js @@ -10,5 +10,8 @@ module.exports = { '*.+(json|yml|yaml|css|less|scss|ts|tsx|md|graphql|mdx|vue)': [ `${codScripts} format --no-eslint`, ].filter(Boolean), - '*.js': [`${codScripts} lint --fix`, `${codScripts} test --findRelatedTests`].filter(Boolean), + '*.js': [ + `${codScripts} lint --fix`, + `${codScripts} test --findRelatedTests`, + ].filter(Boolean), }; diff --git a/src/config/rollup.config.js b/src/config/rollup.config.js index 9b49ff1c..6e8aec8f 100644 --- a/src/config/rollup.config.js +++ b/src/config/rollup.config.js @@ -2,7 +2,10 @@ const path = require('path'); const { babel: rollupBabel } = require('@rollup/plugin-babel'); const commonjs = require('@rollup/plugin-commonjs'); const json = require('@rollup/plugin-json'); -const { DEFAULTS: nodeResolveDefaults, nodeResolve } = require('@rollup/plugin-node-resolve'); +const { + DEFAULTS: nodeResolveDefaults, + nodeResolve, +} = require('@rollup/plugin-node-resolve'); const replace = require('@rollup/plugin-replace'); const glob = require('glob'); @@ -37,22 +40,31 @@ const useSizeSnapshot = parseEnv('BUILD_SIZE_SNAPSHOT', false); const esm = format === 'esm'; const umd = format === 'umd'; -const defaultGlobals = Object.keys(pkg.peerDependencies || {}).reduce((deps, dep) => { - // eslint-disable-next-line no-param-reassign - deps[dep] = capitalize(camelcase(dep)); - return deps; -}, {}); +const defaultGlobals = Object.keys(pkg.peerDependencies || {}).reduce( + (deps, dep) => { + // eslint-disable-next-line no-param-reassign + deps[dep] = capitalize(camelcase(dep)); + return deps; + }, + {}, +); const deps = Object.keys(pkg.dependencies || {}); const peerDeps = Object.keys(pkg.peerDependencies || {}); const defaultExternal = umd ? peerDeps : deps.concat(peerDeps); const input = glob.sync( - fromRoot(process.env.BUILD_INPUT || (hasTypescript ? 'src/index.{js,ts,tsx}' : 'src/index.js')), + fromRoot( + process.env.BUILD_INPUT || + (hasTypescript ? 'src/index.{js,ts,tsx}' : 'src/index.js'), + ), ); const codeSplitting = input.length > 1; -if (codeSplitting && uniq(input.map(single => path.basename(single))).length !== input.length) { +if ( + codeSplitting && + uniq(input.map(single => path.basename(single))).length !== input.length +) { throw new Error( 'Filenames of code-splitted entries should be unique to get deterministic output filenames.' + `\nReceived those: ${input}.`, @@ -60,10 +72,13 @@ if (codeSplitting && uniq(input.map(single => path.basename(single))).length !== } const filenameSuffix = process.env.BUILD_FILENAME_SUFFIX || ''; -const filenamePrefix = process.env.BUILD_FILENAME_PREFIX || (isPreact ? 'preact/' : ''); +const filenamePrefix = + process.env.BUILD_FILENAME_PREFIX || (isPreact ? 'preact/' : ''); const globals = parseEnv( 'BUILD_GLOBALS', - isPreact ? Object.assign(defaultGlobals, { preact: 'preact' }) : defaultGlobals, + isPreact + ? Object.assign(defaultGlobals, { preact: 'preact' }) + : defaultGlobals, ); const external = parseEnv( 'BUILD_EXTERNAL', @@ -91,7 +106,13 @@ function externalPredicate(id) { return isDep || (!isRelative && !path.isAbsolute(id)) || isNodeModule; } -const filename = [pkg.name, filenameSuffix, `.${format}`, minify ? '.min' : null, '.js'] +const filename = [ + pkg.name, + filenameSuffix, + `.${format}`, + minify ? '.min' : null, + '.js', +] .filter(Boolean) .join(''); @@ -116,19 +137,18 @@ const useBuiltinConfig = !hasPkgProp('babel'); const babelPresets = useBuiltinConfig ? [here('../config/babelrc.js')] : []; -const replacements = Object.entries(umd ? process.env : omit(process.env, ['NODE_ENV'])).reduce( - (acc, [key, value]) => { - let val; - if (value === 'true' || value === 'false' || Number.isInteger(+value)) { - val = value; - } else { - val = JSON.stringify(value); - } - acc[`process.env.${key}`] = val; - return acc; - }, - {}, -); +const replacements = Object.entries( + umd ? process.env : omit(process.env, ['NODE_ENV']), +).reduce((acc, [key, value]) => { + let val; + if (value === 'true' || value === 'false' || Number.isInteger(+value)) { + val = value; + } else { + val = JSON.stringify(value); + } + acc[`process.env.${key}`] = val; + return acc; +}, {}); const extensions = hasTypescript ? [...nodeResolveDefaults.extensions, '.ts', '.tsx'] diff --git a/src/run-script.js b/src/run-script.js index f9d657a4..e1d6bd1a 100755 --- a/src/run-script.js +++ b/src/run-script.js @@ -72,7 +72,8 @@ function attemptResolve(...resolveArgs) { } function spawnScript() { - // get all the arguments of the script and find the position of our script commands + // get all the arguments of the script and find the position of our script + // commands const args = process.argv.slice(2); const scriptIndex = args.findIndex(x => [ diff --git a/src/scripts/build/babel.js b/src/scripts/build/babel.js index 856802d8..3041b2e8 100644 --- a/src/scripts/build/babel.js +++ b/src/scripts/build/babel.js @@ -24,7 +24,9 @@ const useBuiltinConfig = !hasFile('.babelrc.js') && !hasFile('babel.config.js') && !hasPkgProp('babel'); -const config = useBuiltinConfig ? ['--presets', here('../../config/babelrc.js')] : []; +const config = useBuiltinConfig + ? ['--presets', here('../../config/babelrc.js')] + : []; const extensions = args.includes('--extensions') || args.includes('--x') @@ -50,7 +52,14 @@ if (!useSpecifiedOutDir && !args.includes('--no-clean')) { function go() { let result = spawn.sync( resolveBin('@babel/cli', { executable: 'babel' }), - [...outDir, ...copyFiles, ...ignore, ...extensions, ...config, 'src'].concat(args), + [ + ...outDir, + ...copyFiles, + ...ignore, + ...extensions, + ...config, + 'src', + ].concat(args), { stdio: 'inherit' }, ); if (result.status !== 0) return result.status; diff --git a/src/scripts/build/rollup.js b/src/scripts/build/rollup.js index c55dcf9d..daadaa0d 100644 --- a/src/scripts/build/rollup.js +++ b/src/scripts/build/rollup.js @@ -21,7 +21,8 @@ const here = p => path.join(__dirname, p); const hereRelative = p => here(p).replace(process.cwd(), '.'); const parsedArgs = yargsParser(args); -const useBuiltinConfig = !args.includes('--config') && !hasFile('rollup.config.js'); +const useBuiltinConfig = + !args.includes('--config') && !hasFile('rollup.config.js'); // eslint-disable-next-line const config = useBuiltinConfig ? `--config ${hereRelative('../../config/rollup.config.js')}` @@ -29,7 +30,9 @@ const config = useBuiltinConfig ? '' : '--config'; // --config will pick up the rollup.config.js file -const environment = parsedArgs.environment ? `--environment ${parsedArgs.environment}` : ''; +const environment = parsedArgs.environment + ? `--environment ${parsedArgs.environment}` + : ''; const watch = parsedArgs.watch ? '--watch' : ''; const sizeSnapshot = parsedArgs['size-snapshot']; @@ -47,7 +50,9 @@ const getCommand = (env, ...flags) => .join(' '); const buildPreact = args.includes('--p-react'); -const scripts = getConcurrentlyArgs(buildPreact ? getPReactCommands() : getCommands()); +const scripts = getConcurrentlyArgs( + buildPreact ? getPReactCommands() : getCommands(), +); const cleanBuildDirs = !args.includes('--no-clean'); @@ -86,7 +91,10 @@ function go() { const [formatFile] = glob.sync(fromRoot(`dist/*.${format}.js`)); const { name } = path.parse(formatFile); // make a .d.ts file for every generated file that re-exports index.d.ts - fs.writeFileSync(fromRoot('dist', `${name}.d.ts`), 'export * from ".";\n'); + fs.writeFileSync( + fromRoot('dist', `${name}.d.ts`), + 'export * from ".";\n', + ); } // because typescript generates type defs for ignored files, we need to diff --git a/src/scripts/commitlint.js b/src/scripts/commitlint.js index 36ec5bb7..38d8cf54 100644 --- a/src/scripts/commitlint.js +++ b/src/scripts/commitlint.js @@ -15,7 +15,9 @@ const useBuiltinConfig = !hasFile('.commitlintrc.yml') && !hasPkgProp('commitlint'); -const config = useBuiltinConfig ? ['--config', hereRelative('../config/commitlint.config.js')] : []; +const config = useBuiltinConfig + ? ['--config', hereRelative('../config/commitlint.config.js')] + : []; const result = spawn.sync(resolveBin('commitlint'), [...config, ...args], { stdio: 'inherit', diff --git a/src/scripts/format.js b/src/scripts/format.js index 3bd8e2e5..31ac7753 100644 --- a/src/scripts/format.js +++ b/src/scripts/format.js @@ -1,7 +1,12 @@ const path = require('path'); const spawn = require('cross-spawn'); const yargsParser = require('yargs-parser'); -const { resolveBin, hasFile, hasLocalConfig, resolveCodScripts } = require('../utils'); +const { + resolveBin, + hasFile, + hasLocalConfig, + resolveCodScripts, +} = require('../utils'); const args = process.argv.slice(2); const parsedArgs = yargsParser(args); @@ -9,10 +14,16 @@ const parsedArgs = yargsParser(args); const here = p => path.join(__dirname, p); const hereRelative = p => here(p).replace(process.cwd(), '.'); -const useBuiltinConfig = !args.includes('--config') && !hasLocalConfig('prettier'); -const config = useBuiltinConfig ? ['--config', hereRelative('../config/prettierrc.js')] : []; -const useBuiltinIgnore = !args.includes('--ignore-path') && !hasFile('.prettierignore'); -const ignore = useBuiltinIgnore ? ['--ignore-path', hereRelative('../config/prettierignore')] : []; +const useBuiltinConfig = + !args.includes('--config') && !hasLocalConfig('prettier'); +const config = useBuiltinConfig + ? ['--config', hereRelative('../config/prettierrc.js')] + : []; +const useBuiltinIgnore = + !args.includes('--ignore-path') && !hasFile('.prettierignore'); +const ignore = useBuiltinIgnore + ? ['--ignore-path', hereRelative('../config/prettierignore')] + : []; const write = args.includes('--no-write') ? [] : ['--write']; @@ -36,8 +47,12 @@ if (prettierResult.status !== 0 || args.includes('--no-eslint')) { } // run eslint for js files (`eslint-plugin-prettier` will run prettier for us) -const eslintResult = spawn.sync(resolveCodScripts(), ['lint', '--fix'].concat(args), { - stdio: 'inherit', -}); +const eslintResult = spawn.sync( + resolveCodScripts(), + ['lint', '--fix'].concat(args), + { + stdio: 'inherit', + }, +); process.exit(eslintResult.status); diff --git a/src/scripts/lint.js b/src/scripts/lint.js index bb148a91..1bed23f8 100644 --- a/src/scripts/lint.js +++ b/src/scripts/lint.js @@ -14,20 +14,30 @@ const useBuiltinConfig = !hasFile('.eslintrc.js') && !hasPkgProp('eslintConfig'); -const config = useBuiltinConfig ? ['--config', hereRelative('../config/eslintrc.js')] : []; +const config = useBuiltinConfig + ? ['--config', hereRelative('../config/eslintrc.js')] + : []; const defaultExtensions = 'js,ts,tsx'; const ext = args.includes('--ext') ? [] : ['--ext', defaultExtensions]; const extensions = (parsedArgs.ext || defaultExtensions).split(','); const useBuiltinIgnore = - !args.includes('--ignore-path') && !hasFile('.eslintignore') && !hasPkgProp('eslintIgnore'); + !args.includes('--ignore-path') && + !hasFile('.eslintignore') && + !hasPkgProp('eslintIgnore'); -const ignore = useBuiltinIgnore ? ['--ignore-path', hereRelative('../config/eslintignore')] : []; +const ignore = useBuiltinIgnore + ? ['--ignore-path', hereRelative('../config/eslintignore')] + : []; const cache = args.includes('--no-cache') ? [] - : ['--cache', '--cache-location', fromRoot('node_modules/.cache/.eslintcache')]; + : [ + '--cache', + '--cache-location', + fromRoot('node_modules/.cache/.eslintcache'), + ]; const filesGiven = parsedArgs._.length > 0; const filesToApply = filesGiven ? [] : ['.']; @@ -36,7 +46,9 @@ if (filesGiven) { // we need to take all the flag-less arguments (the files that should be linted) // and filter out the ones that aren't js files. Otherwise json or css files // may be passed through - args = args.filter(a => !parsedArgs._.includes(a) || extensions.some(e => a.endsWith(e))); + args = args.filter( + a => !parsedArgs._.includes(a) || extensions.some(e => a.endsWith(e)), + ); } const result = spawn.sync( diff --git a/src/scripts/pre-commit.js b/src/scripts/pre-commit.js index 9ba7545f..1ea2c0fe 100644 --- a/src/scripts/pre-commit.js +++ b/src/scripts/pre-commit.js @@ -13,7 +13,9 @@ const useBuiltInConfig = !hasFile('lint-staged.config.js') && !hasPkgProp('lint-staged'); -const config = useBuiltInConfig ? ['--config', hereRelative('../config/lintstagedrc.js')] : []; +const config = useBuiltInConfig + ? ['--config', hereRelative('../config/lintstagedrc.js')] + : []; function go() { let result; diff --git a/src/scripts/test.js b/src/scripts/test.js index f00d3adb..d02dad7b 100644 --- a/src/scripts/test.js +++ b/src/scripts/test.js @@ -16,7 +16,9 @@ const watch = : []; const config = - !args.includes('--config') && !hasFile('jest.config.js') && !hasPkgProp('jest') + !args.includes('--config') && + !hasFile('jest.config.js') && + !hasPkgProp('jest') ? ['--config', JSON.stringify(require('../config/jest.config'))] : []; diff --git a/src/scripts/typecheck.js b/src/scripts/typecheck.js index 4f096064..283d5365 100644 --- a/src/scripts/typecheck.js +++ b/src/scripts/typecheck.js @@ -24,8 +24,12 @@ if (!parsedArgs.project && !parsedArgs.build && !parsedArgs.noBuild) { args = ['--build', ...args]; } -const result = spawn.sync(resolveBin('typescript', { executable: 'tsc' }), args, { - stdio: 'inherit', -}); +const result = spawn.sync( + resolveBin('typescript', { executable: 'tsc' }), + args, + { + stdio: 'inherit', + }, +); process.exit(result.status); diff --git a/src/scripts/validate.js b/src/scripts/validate.js index 67941d50..543ad0d3 100644 --- a/src/scripts/validate.js +++ b/src/scripts/validate.js @@ -1,5 +1,10 @@ const spawn = require('cross-spawn'); -const { parseEnv, resolveBin, ifScript, getConcurrentlyArgs } = require('../utils'); +const { + parseEnv, + resolveBin, + ifScript, + getConcurrentlyArgs, +} = require('../utils'); // pre-commit runs linting and tests on the relevant files // so those scripts don't need to be run if we're running @@ -14,7 +19,9 @@ const scripts = useDefaultScripts ? { build: ifScript('build', 'npm run build --silent'), lint: preCommit ? null : ifScript('lint', 'npm run lint --silent'), - test: preCommit ? null : ifScript('test', 'npm run test --silent -- --coverage'), + test: preCommit + ? null + : ifScript('test', 'npm run test --silent -- --coverage'), typecheck: ifScript('typecheck', 'npm run typecheck --silent'), } : validateScripts.split(',').reduce( @@ -28,9 +35,13 @@ const scripts = useDefaultScripts const scriptCount = Object.values(scripts).filter(Boolean).length; if (scriptCount > 0) { - const result = spawn.sync(resolveBin('concurrently'), getConcurrentlyArgs(scripts), { - stdio: 'inherit', - }); + const result = spawn.sync( + resolveBin('concurrently'), + getConcurrentlyArgs(scripts), + { + stdio: 'inherit', + }, + ); process.exit(result.status); } else { diff --git a/src/utils.js b/src/utils.js index 78b6b75f..4b3c2c5c 100644 --- a/src/utils.js +++ b/src/utils.js @@ -14,7 +14,10 @@ const { packageJson: pkg, path: pkgPath } = readPkgUp.sync({ }); const appDirectory = path.dirname(pkgPath); -function resolveBin(modName, { executable = modName, cwd = process.cwd() } = {}) { +function resolveBin( + modName, + { executable = modName, cwd = process.cwd() } = {}, +) { let pathFromWhich; try { pathFromWhich = fs.realpathSync(which.sync(executable)); @@ -53,13 +56,16 @@ function resolveCodScripts() { const fromRoot = (...p) => path.join(appDirectory, ...p); const hasFile = (...p) => fs.existsSync(fromRoot(...p)); -const ifFile = (files, t, f) => (arrify(files).some(file => hasFile(file)) ? t : f); +const ifFile = (files, t, f) => + arrify(files).some(file => hasFile(file)) ? t : f; const hasPkgProp = props => arrify(props).some(prop => has(pkg, prop)); -const hasPkgSubProp = pkgProp => props => hasPkgProp(arrify(props).map(p => `${pkgProp}.${p}`)); +const hasPkgSubProp = pkgProp => props => + hasPkgProp(arrify(props).map(p => `${pkgProp}.${p}`)); -const ifPkgSubProp = pkgProp => (props, t, f) => (hasPkgSubProp(pkgProp)(props) ? t : f); +const ifPkgSubProp = pkgProp => (props, t, f) => + hasPkgSubProp(pkgProp)(props) ? t : f; const hasScript = hasPkgSubProp('scripts'); const hasPeerDep = hasPkgSubProp('peerDependencies'); @@ -74,8 +80,11 @@ const ifAnyDep = (deps, t, f) => (hasAnyDep(arrify(deps)) ? t : f); const ifScript = ifPkgSubProp('scripts'); function envIsSet(name) { - // eslint-disable-next-line no-prototype-builtins - return process.env.hasOwnProperty(name) && process.env[name] && process.env[name] !== 'undefined'; + return ( + process.env.hasOwnProperty(name) && + process.env[name] && + process.env[name] !== 'undefined' + ); } const hasTypescript = hasAnyDep('typescript') && hasFile('tsconfig.json'); @@ -112,7 +121,11 @@ function getConcurrentlyArgs(scripts, { killOthers = true } = {}) { return all; }, {}); const prefixColors = Object.keys(scripts) - .reduce((pColors, _s, i) => pColors.concat([`${colors[i % colors.length]}.bold.white`]), []) + .reduce( + (pColors, _s, i) => + pColors.concat([`${colors[i % colors.length]}.bold.white`]), + [], + ) .join(','); // prettier-ignore @@ -121,7 +134,8 @@ function getConcurrentlyArgs(scripts, { killOthers = true } = {}) { '--prefix', '[{name}]', '--names', Object.keys(scripts).join(','), '--prefix-colors', prefixColors, - ...Object.values(scripts).map(s => JSON.stringify(s)), // stringify escapes quotes ✨ + ...Object.values(scripts) + .map(s => JSON.stringify(s)), // stringify escapes quotes ✨ ].filter(Boolean); } From 10efceeab76cc6352364f93627c07133015fe118 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 25 Feb 2021 23:39:26 -0500 Subject: [PATCH 35/48] style: conform to kcd-scripts styling to avoid dumb conflicts --- .prettierrc.js | 2 + README.md | 8 +- babel.js | 2 +- commitlint.js | 2 +- config.js | 2 +- eslint.js | 2 +- husky.js | 2 +- jest.config.js | 4 +- jest.js | 2 +- package.json | 4 + prettier.js | 2 +- src/__mocks__/cross-spawn.js | 4 +- src/__tests__/index.js | 66 +++--- src/__tests__/utils.js | 204 +++++++++---------- src/config/__tests__/umbrella.js | 20 +- src/config/babel-transform.js | 4 +- src/config/babelrc.js | 69 +++---- src/config/commitlint.config.js | 2 +- src/config/eslintrc.js | 12 +- src/config/huskyrc.js | 6 +- src/config/index.js | 2 +- src/config/jest.config.js | 22 +- src/config/lintstagedrc.js | 8 +- src/config/prettierrc.js | 2 +- src/config/rollup.config.js | 132 ++++++------ src/index.js | 10 +- src/run-script.js | 56 ++--- src/scripts/__tests__/format.js | 48 ++--- src/scripts/__tests__/helpers/serializers.js | 12 +- src/scripts/__tests__/lint.js | 48 ++--- src/scripts/__tests__/pre-commit.js | 46 ++--- src/scripts/__tests__/test.js | 58 +++--- src/scripts/__tests__/validate.js | 94 ++++----- src/scripts/build/babel.js | 76 +++---- src/scripts/build/index.js | 6 +- src/scripts/build/rollup.js | 124 +++++------ src/scripts/commitlint.js | 20 +- src/scripts/format.js | 40 ++-- src/scripts/lint.js | 44 ++-- src/scripts/pre-commit.js | 30 +-- src/scripts/test.js | 16 +- src/scripts/typecheck.js | 28 ++- src/scripts/validate.js | 20 +- src/utils.js | 169 ++++++++------- 44 files changed, 762 insertions(+), 768 deletions(-) diff --git a/.prettierrc.js b/.prettierrc.js index 2cda2dfc..f209a68c 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -4,4 +4,6 @@ module.exports = Object.assign({}, prettierConfig, { // to prevent additional conflicts with update kcd-scripts, making // backmerging a little easier. printWidth: 80, + semi: false, + bracketSpacing: false, }) diff --git a/README.md b/README.md index 95c12c2d..983d8d40 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ Or, for `babel`, a `.babelrc` with: Or, for `jest`: ```js -const { jest: jestConfig } = require('cod-scripts/config'); +const {jest: jestConfig} = require('cod-scripts/config') module.exports = Object.assign(jestConfig, { // your overrides here @@ -96,7 +96,7 @@ module.exports = Object.assign(jestConfig, { transform: { '\\.(ts|tsx)$': '/node_modules/ts-jest/preprocessor.js', }, -}); +}) ``` Or, for `commitlint`, a `commitlint.config.js` file or `commitlint` prop in @@ -104,14 +104,14 @@ package.json: ```js // commitlint.config.js or .commitlintrc.js -const { commitlint: commitlintConfig } = require('cod-scripts/commitlint'); +const {commitlint: commitlintConfig} = require('cod-scripts/commitlint') module.exports = { ...commitlintConfig, rules: { // overrides here }, -}; +} ``` ```json diff --git a/babel.js b/babel.js index 953754cd..f46b0555 100644 --- a/babel.js +++ b/babel.js @@ -1 +1 @@ -module.exports = require('./dist/config/babelrc'); +module.exports = require('./dist/config/babelrc') diff --git a/commitlint.js b/commitlint.js index 23a4bda0..98e2af42 100644 --- a/commitlint.js +++ b/commitlint.js @@ -1 +1 @@ -module.exports = require('./dist/config/commitlint.config'); +module.exports = require('./dist/config/commitlint.config') diff --git a/config.js b/config.js index 6dc01060..bb07926b 100644 --- a/config.js +++ b/config.js @@ -1 +1 @@ -module.exports = require('./dist/config'); +module.exports = require('./dist/config') diff --git a/eslint.js b/eslint.js index 286e06ab..7cc6ee52 100644 --- a/eslint.js +++ b/eslint.js @@ -1 +1 @@ -module.exports = require('./dist/config/eslintrc'); +module.exports = require('./dist/config/eslintrc') diff --git a/husky.js b/husky.js index 8fa198b2..204c296c 100644 --- a/husky.js +++ b/husky.js @@ -1 +1 @@ -module.exports = require('./dist/config/huskyrc'); +module.exports = require('./dist/config/huskyrc') diff --git a/jest.config.js b/jest.config.js index f6fbc3c1..61f21edc 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,4 +1,4 @@ -const { jest: jestConfig } = require('./src/config'); +const {jest: jestConfig} = require('./src/config') module.exports = Object.assign(jestConfig, { coverageThreshold: null, @@ -6,4 +6,4 @@ module.exports = Object.assign(jestConfig, { ...jestConfig.testPathIgnorePatterns, './src/scripts/test.js', ], -}); +}) diff --git a/jest.js b/jest.js index 70169854..3a1bd4e9 100644 --- a/jest.js +++ b/jest.js @@ -1 +1 @@ -module.exports = require('./dist/config/jest.config'); +module.exports = require('./dist/config/jest.config') diff --git a/package.json b/package.json index fc5afd4b..9a725689 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,10 @@ ], "rules": { "no-console": "off", + "semi": "off", + "babel/semi": "off", + "object-curly-spacing": "off", + "babel/object-curly-spacing": "off", "no-process-exit": "off", "global-require": "off", "no-prototype-builtins": "off", diff --git a/prettier.js b/prettier.js index 898d0336..de4ba09d 100644 --- a/prettier.js +++ b/prettier.js @@ -1 +1 @@ -module.exports = require('./dist/config/prettierrc'); +module.exports = require('./dist/config/prettierrc') diff --git a/src/__mocks__/cross-spawn.js b/src/__mocks__/cross-spawn.js index fcad0923..a16265e8 100644 --- a/src/__mocks__/cross-spawn.js +++ b/src/__mocks__/cross-spawn.js @@ -1,3 +1,3 @@ module.exports = { - sync: jest.fn(() => ({ status: 0 })), -}; + sync: jest.fn(() => ({status: 0})), +} diff --git a/src/__tests__/index.js b/src/__tests__/index.js index 43c837ba..83150096 100644 --- a/src/__tests__/index.js +++ b/src/__tests__/index.js @@ -1,58 +1,58 @@ -import path from 'path'; -import slash from 'slash'; -import cases from 'jest-in-case'; -import { unquoteSerializer } from '../scripts/__tests__/helpers/serializers'; +import path from 'path' +import slash from 'slash' +import cases from 'jest-in-case' +import {unquoteSerializer} from '../scripts/__tests__/helpers/serializers' -const projectRoot = path.join(__dirname, '../../'); +const projectRoot = path.join(__dirname, '../../') -expect.addSnapshotSerializer(unquoteSerializer); +expect.addSnapshotSerializer(unquoteSerializer) expect.addSnapshotSerializer({ print: val => slash(val.replace(projectRoot, '/')), test: val => typeof val === 'string' && val.includes(projectRoot), -}); +}) cases( 'format', - ({ snapshotLog = false, throws = false, signal = false, args = [] }) => { + ({snapshotLog = false, throws = false, signal = false, args = []}) => { // beforeEach - const { sync: crossSpawnSyncMock } = require('cross-spawn'); - const originalExit = process.exit; - const originalArgv = process.argv; - const originalLog = console.log; - process.exit = jest.fn(); - console.log = jest.fn(); + const {sync: crossSpawnSyncMock} = require('cross-spawn') + const originalExit = process.exit + const originalArgv = process.argv + const originalLog = console.log + process.exit = jest.fn() + console.log = jest.fn() try { // tests - process.argv = ['node', '../', ...args]; - crossSpawnSyncMock.mockClear(); + process.argv = ['node', '../', ...args] + crossSpawnSyncMock.mockClear() if (signal) { - crossSpawnSyncMock.mockReturnValueOnce({ result: 1, signal }); + crossSpawnSyncMock.mockReturnValueOnce({result: 1, signal}) } - require('..'); + require('..') if (snapshotLog) { - expect(console.log.mock.calls).toMatchSnapshot(); + expect(console.log.mock.calls).toMatchSnapshot() } else if (signal) { - expect(process.exit).toHaveBeenCalledTimes(1); - expect(process.exit).toHaveBeenCalledWith(1); - expect(console.log.mock.calls).toMatchSnapshot(); + expect(process.exit).toHaveBeenCalledTimes(1) + expect(process.exit).toHaveBeenCalledWith(1) + expect(console.log.mock.calls).toMatchSnapshot() } else { - expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1); - const [firstCall] = crossSpawnSyncMock.mock.calls; - const [script, calledArgs] = firstCall; - expect([script, ...calledArgs].join(' ')).toMatchSnapshot(); + expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1) + const [firstCall] = crossSpawnSyncMock.mock.calls + const [script, calledArgs] = firstCall + expect([script, ...calledArgs].join(' ')).toMatchSnapshot() } } catch (error) { if (throws) { - expect(error.message).toMatchSnapshot(); + expect(error.message).toMatchSnapshot() } else { - throw error; + throw error } } finally { // afterEach - process.exit = originalExit; - process.argv = originalArgv; - console.log = originalLog; - jest.resetModules(); + process.exit = originalExit + process.argv = originalArgv + console.log = originalLog + jest.resetModules() } }, { @@ -82,6 +82,6 @@ cases( signal: 'SIGBREAK', }, }, -); +) /* eslint complexity:0 */ diff --git a/src/__tests__/utils.js b/src/__tests__/utils.js index 0b7728de..ade59b09 100644 --- a/src/__tests__/utils.js +++ b/src/__tests__/utils.js @@ -1,81 +1,81 @@ jest.mock('read-pkg-up', () => ({ - sync: jest.fn(() => ({ packageJson: {}, path: '/blah/package.json' })), -})); -jest.mock('which', () => ({ sync: jest.fn(() => {}) })); + sync: jest.fn(() => ({packageJson: {}, path: '/blah/package.json'})), +})) +jest.mock('which', () => ({sync: jest.fn(() => {})})) jest.mock('cosmiconfig', () => { - const cosmiconfigExports = jest.requireActual('cosmiconfig'); - return { ...cosmiconfigExports, cosmiconfigSync: jest.fn() }; -}); + const cosmiconfigExports = jest.requireActual('cosmiconfig') + return {...cosmiconfigExports, cosmiconfigSync: jest.fn()} +}) -let whichSyncMock; -let readPkgUpSyncMock; +let whichSyncMock +let readPkgUpSyncMock beforeEach(() => { - jest.resetModules(); - whichSyncMock = require('which').sync; - readPkgUpSyncMock = require('read-pkg-up').sync; -}); + jest.resetModules() + whichSyncMock = require('which').sync + readPkgUpSyncMock = require('read-pkg-up').sync +}) test('package is the package.json', () => { - const myPkg = { name: 'blah' }; - mockPkg({ package: myPkg }); - expect(require('../utils').pkg).toBe(myPkg); -}); + const myPkg = {name: 'blah'} + mockPkg({package: myPkg}) + expect(require('../utils').pkg).toBe(myPkg) +}) test('appDirectory is the dirname to the package.json', () => { - const pkgPath = '/some/path/to'; - mockPkg({ path: `${pkgPath}/package.json` }); - expect(require('../utils').appDirectory).toBe(pkgPath); -}); + const pkgPath = '/some/path/to' + mockPkg({path: `${pkgPath}/package.json`}) + expect(require('../utils').appDirectory).toBe(pkgPath) +}) test('resolveCodScripts resolves to src/index.js when in the cod-scripts package', () => { - mockPkg({ package: { name: 'cod-scripts' } }); + mockPkg({package: {name: 'cod-scripts'}}) expect(require('../utils').resolveCodScripts()).toBe( require.resolve('../').replace(process.cwd(), '.'), - ); -}); + ) +}) test('resolveCodScripts resolves to cod-scripts if not in the cod-scripts package', () => { - mockPkg({ package: { name: 'not-cod-scripts' } }); - whichSyncMock.mockImplementationOnce(() => require.resolve('../')); - expect(require('../utils').resolveCodScripts()).toBe('cod-scripts'); -}); + mockPkg({package: {name: 'not-cod-scripts'}}) + whichSyncMock.mockImplementationOnce(() => require.resolve('../')) + expect(require('../utils').resolveCodScripts()).toBe('cod-scripts') +}) test(`resolveBin resolves to the full path when it's not in $PATH`, () => { expect(require('../utils').resolveBin('cross-env')).toBe( require.resolve('cross-env/src/bin/cross-env').replace(process.cwd(), '.'), - ); -}); + ) +}) test(`resolveBin resolves to the binary if it's in $PATH`, () => { whichSyncMock.mockImplementationOnce(() => require.resolve('cross-env/src/bin/cross-env').replace(process.cwd(), '.'), - ); - expect(require('../utils').resolveBin('cross-env')).toBe('cross-env'); - expect(whichSyncMock).toHaveBeenCalledTimes(1); - expect(whichSyncMock).toHaveBeenCalledWith('cross-env'); -}); + ) + expect(require('../utils').resolveBin('cross-env')).toBe('cross-env') + expect(whichSyncMock).toHaveBeenCalledTimes(1) + expect(whichSyncMock).toHaveBeenCalledWith('cross-env') +}) describe('for windows', () => { - let realpathSync; + let realpathSync beforeEach(() => { - jest.doMock('fs', () => ({ realpathSync: jest.fn() })); + jest.doMock('fs', () => ({realpathSync: jest.fn()})) realpathSync = require('fs').realpathSync; // eslint-disable-line - }); + }) afterEach(() => { - jest.unmock('fs'); - }); + jest.unmock('fs') + }) test('resolveBin resolves to .bin path when which returns a windows-style cmd', () => { - const fullBinPath = '\\project\\node_modules\\.bin\\concurrently.CMD'; - realpathSync.mockImplementation(() => fullBinPath); - expect(require('../utils').resolveBin('concurrently')).toBe(fullBinPath); - expect(realpathSync).toHaveBeenCalledTimes(2); - }); -}); + const fullBinPath = '\\project\\node_modules\\.bin\\concurrently.CMD' + realpathSync.mockImplementation(() => fullBinPath) + expect(require('../utils').resolveBin('concurrently')).toBe(fullBinPath) + expect(realpathSync).toHaveBeenCalledTimes(2) + }) +}) test('getConcurrentlyArgs gives good args to pass to concurrently', () => { expect( @@ -95,90 +95,90 @@ test('getConcurrentlyArgs gives good args to pass to concurrently', () => { i: 'echo i', j: 'echo j', }), - ).toMatchSnapshot(); -}); + ).toMatchSnapshot() +}) test('parseEnv parses the existing environment variable', () => { - const globals = { react: 'React', 'prop-types': 'PropTypes' }; - process.env.BUILD_GLOBALS = JSON.stringify(globals); - expect(require('../utils').parseEnv('BUILD_GLOBALS')).toEqual(globals); - delete process.env.BUILD_GLOBALS; -}); + const globals = {react: 'React', 'prop-types': 'PropTypes'} + process.env.BUILD_GLOBALS = JSON.stringify(globals) + expect(require('../utils').parseEnv('BUILD_GLOBALS')).toEqual(globals) + delete process.env.BUILD_GLOBALS +}) test(`parseEnv returns the default if the environment variable doesn't exist`, () => { - const defaultVal = { hello: 'world' }; + const defaultVal = {hello: 'world'} expect(require('../utils').parseEnv('DOES_NOT_EXIST', defaultVal)).toBe( defaultVal, - ); -}); + ) +}) test('ifAnyDep returns the true argument if true and false argument if false', () => { - mockPkg({ package: { peerDependencies: { react: '*' } } }); - const t = { a: 'b' }; - const f = { c: 'd' }; - expect(require('../utils').ifAnyDep('react', t, f)).toBe(t); - expect(require('../utils').ifAnyDep('preact', t, f)).toBe(f); -}); + mockPkg({package: {peerDependencies: {react: '*'}}}) + const t = {a: 'b'} + const f = {c: 'd'} + expect(require('../utils').ifAnyDep('react', t, f)).toBe(t) + expect(require('../utils').ifAnyDep('preact', t, f)).toBe(f) +}) test('ifAnyDep works with arrays of dependencies', () => { - mockPkg({ package: { peerDependencies: { react: '*' } } }); - const t = { a: 'b' }; - const f = { c: 'd' }; - expect(require('../utils').ifAnyDep(['preact', 'react'], t, f)).toBe(t); - expect(require('../utils').ifAnyDep(['preact', 'webpack'], t, f)).toBe(f); -}); + mockPkg({package: {peerDependencies: {react: '*'}}}) + const t = {a: 'b'} + const f = {c: 'd'} + expect(require('../utils').ifAnyDep(['preact', 'react'], t, f)).toBe(t) + expect(require('../utils').ifAnyDep(['preact', 'webpack'], t, f)).toBe(f) +}) test('ifScript returns the true argument if true and the false argument if false', () => { - mockPkg({ package: { scripts: { build: 'echo build' } } }); - const t = { e: 'f' }; - const f = { g: 'h' }; - expect(require('../utils').ifScript('build', t, f)).toBe(t); - expect(require('../utils').ifScript('lint', t, f)).toBe(f); -}); + mockPkg({package: {scripts: {build: 'echo build'}}}) + const t = {e: 'f'} + const f = {g: 'h'} + expect(require('../utils').ifScript('build', t, f)).toBe(t) + expect(require('../utils').ifScript('lint', t, f)).toBe(f) +}) test('ifFile returns the true argument if true and the false argument if false', () => { - mockPkg({ path: require.resolve('../../package.json') }); - const t = { e: 'f' }; - const f = { g: 'h' }; - expect(require('../utils').ifFile('package.json', t, f)).toBe(t); - expect(require('../utils').ifFile('does-not-exist.blah', t, f)).toBe(f); -}); + mockPkg({path: require.resolve('../../package.json')}) + const t = {e: 'f'} + const f = {g: 'h'} + expect(require('../utils').ifFile('package.json', t, f)).toBe(t) + expect(require('../utils').ifFile('does-not-exist.blah', t, f)).toBe(f) +}) test('hasLocalConfiguration returns false if no local configuration found', () => { - mockCosmiconfig(); + mockCosmiconfig() - expect(require('../utils').hasLocalConfig('module')).toBe(false); -}); + expect(require('../utils').hasLocalConfig('module')).toBe(false) +}) test('hasLocalConfig returns true if a local configuration found', () => { - mockCosmiconfig({ config: {}, filepath: 'path/to/config' }); + mockCosmiconfig({config: {}, filepath: 'path/to/config'}) - expect(require('../utils').hasLocalConfig('module')).toBe(true); -}); + expect(require('../utils').hasLocalConfig('module')).toBe(true) +}) test('hasLocalConfiguration returns true if a local config found and it is empty', () => { - mockCosmiconfig({ isEmpty: true }); + mockCosmiconfig({isEmpty: true}) - expect(require('../utils').hasLocalConfig('module')).toBe(true); -}); + expect(require('../utils').hasLocalConfig('module')).toBe(true) +}) test('should generate typescript definitions into provided folder', () => { - whichSyncMock.mockImplementationOnce(() => require.resolve('../')); - const { sync: crossSpawnSyncMock } = require('cross-spawn'); - require('../utils').generateTypeDefs('destination folder'); - expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1); - const args = crossSpawnSyncMock.mock.calls[0][1]; - const outDirIndex = args.findIndex(arg => arg === '--outDir') + 1; - - expect(args[outDirIndex]).toBe('destination folder'); -}); - -function mockPkg({ package: pkg = {}, path = '/blah/package.json' }) { - readPkgUpSyncMock.mockImplementationOnce(() => ({ packageJson: pkg, path })); + whichSyncMock.mockImplementationOnce(() => require.resolve('../')) + const {sync: crossSpawnSyncMock} = require('cross-spawn') + require('../utils').generateTypeDefs('destination folder') + expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1) + const args = crossSpawnSyncMock.mock.calls[0][1] + const outDirIndex = args.findIndex(arg => arg === '--outDir') + 1 + + expect(args[outDirIndex]).toBe('destination folder') +}) + +function mockPkg({package: pkg = {}, path = '/blah/package.json'}) { + readPkgUpSyncMock.mockImplementationOnce(() => ({packageJson: pkg, path})) } function mockCosmiconfig(result = null) { - const { cosmiconfigSync } = require('cosmiconfig'); + const {cosmiconfigSync} = require('cosmiconfig') - cosmiconfigSync.mockImplementationOnce(() => ({ search: () => result })); + cosmiconfigSync.mockImplementationOnce(() => ({search: () => result})) } diff --git a/src/config/__tests__/umbrella.js b/src/config/__tests__/umbrella.js index 1edb1d54..51af51e9 100644 --- a/src/config/__tests__/umbrella.js +++ b/src/config/__tests__/umbrella.js @@ -1,11 +1,11 @@ test('requiring some files does not blow up', () => { - require('../babel-transform'); - require('../babelrc'); - require('../commitlint.config'); - require('../eslintrc'); - require('../jest.config'); - require('../lintstagedrc'); - require('../prettierrc'); - require('../rollup.config'); - require('..').getRollupConfig(); -}); + require('../babel-transform') + require('../babelrc') + require('../commitlint.config') + require('../eslintrc') + require('../jest.config') + require('../lintstagedrc') + require('../prettierrc') + require('../rollup.config') + require('..').getRollupConfig() +}) diff --git a/src/config/babel-transform.js b/src/config/babel-transform.js index f0f1f482..cbda1e7a 100644 --- a/src/config/babel-transform.js +++ b/src/config/babel-transform.js @@ -1,5 +1,5 @@ -const babelJest = require('babel-jest'); +const babelJest = require('babel-jest') module.exports = babelJest.createTransformer({ presets: [require.resolve('./babelrc')], -}); +}) diff --git a/src/config/babelrc.js b/src/config/babelrc.js index 60e56fe7..f382e372 100644 --- a/src/config/babelrc.js +++ b/src/config/babelrc.js @@ -1,5 +1,5 @@ -const browserslist = require('browserslist'); -const semver = require('semver'); +const browserslist = require('browserslist') +const semver = require('semver') const { ifDep, @@ -8,44 +8,44 @@ const { parseEnv, appDirectory, pkg, -} = require('../utils'); +} = require('../utils') -const { BABEL_ENV, NODE_ENV, BUILD_FORMAT } = process.env; -const isTest = (BABEL_ENV || NODE_ENV) === 'test'; -const isPreact = parseEnv('BUILD_PREACT', false); -const isRollup = parseEnv('BUILD_ROLLUP', false); -const isUMD = BUILD_FORMAT === 'umd'; -const isCJS = BUILD_FORMAT === 'cjs'; -const isWebpack = parseEnv('BUILD_WEBPACK', false); -const isMinify = parseEnv('BUILD_MINIFY', false); -const treeshake = parseEnv('BUILD_TREESHAKE', isRollup || isWebpack); -const alias = parseEnv('BUILD_ALIAS', isPreact ? { react: 'preact' } : null); +const {BABEL_ENV, NODE_ENV, BUILD_FORMAT} = process.env +const isTest = (BABEL_ENV || NODE_ENV) === 'test' +const isPreact = parseEnv('BUILD_PREACT', false) +const isRollup = parseEnv('BUILD_ROLLUP', false) +const isUMD = BUILD_FORMAT === 'umd' +const isCJS = BUILD_FORMAT === 'cjs' +const isWebpack = parseEnv('BUILD_WEBPACK', false) +const isMinify = parseEnv('BUILD_MINIFY', false) +const treeshake = parseEnv('BUILD_TREESHAKE', isRollup || isWebpack) +const alias = parseEnv('BUILD_ALIAS', isPreact ? {react: 'preact'} : null) const hasBabelRuntimeDep = Boolean( pkg.dependencies && pkg.dependencies['@babel/runtime'], -); +) const RUNTIME_HELPERS_WARN = - 'You should add @babel/runtime as dependency to your package. It will allow reusing "babel helpers" from node_modules rather than bundling their copies into your files.'; + 'You should add @babel/runtime as dependency to your package. It will allow reusing "babel helpers" from node_modules rather than bundling their copies into your files.' if (!treeshake && !hasBabelRuntimeDep && !isTest) { - throw new Error(RUNTIME_HELPERS_WARN); + throw new Error(RUNTIME_HELPERS_WARN) } else if (treeshake && !isUMD && !hasBabelRuntimeDep) { - console.warn(RUNTIME_HELPERS_WARN); + console.warn(RUNTIME_HELPERS_WARN) } -function getNodeVersion({ engines: { node: nodeVersion = '10.13' } = {} }) { +function getNodeVersion({engines: {node: nodeVersion = '10.13'} = {}}) { const oldestVersion = semver .validRange(nodeVersion) .replace(/[>=<|]/g, ' ') .split(' ') .filter(Boolean) - .sort(semver.compare)[0]; + .sort(semver.compare)[0] if (!oldestVersion) { throw new Error( `Unable to determine the oldest version in the range in your package.json at engines.node: "${nodeVersion}". Please attempt to make it less ambiguous.`, - ); + ) } - return oldestVersion; + return oldestVersion } /** @@ -54,17 +54,17 @@ function getNodeVersion({ engines: { node: nodeVersion = '10.13' } = {} }) { * * @see https://github.com/browserslist/browserslist/blob/master/node.js#L139 */ -const browsersConfig = browserslist.loadConfig({ path: appDirectory }) || [ +const browsersConfig = browserslist.loadConfig({path: appDirectory}) || [ 'ie 10', 'ios 7', -]; +] const envTargets = isTest - ? { node: 'current' } + ? {node: 'current'} : isWebpack || isRollup - ? { browsers: browsersConfig } - : { node: getNodeVersion(pkg) }; -const envOptions = { modules: false, loose: true, targets: envTargets }; + ? {browsers: browsersConfig} + : {node: getNodeVersion(pkg)} +const envOptions = {modules: false, loose: true, targets: envTargets} module.exports = () => ({ presets: [ @@ -73,7 +73,7 @@ module.exports = () => ({ ['react', 'preact'], [ require.resolve('@babel/preset-react'), - { pragma: isPreact ? ifDep('react', 'React.h', 'h') : undefined }, + {pragma: isPreact ? ifDep('react', 'React.h', 'h') : undefined}, ], ), ifTypescript([require.resolve('@babel/preset-typescript')]), @@ -81,29 +81,26 @@ module.exports = () => ({ plugins: [ [ require.resolve('@babel/plugin-transform-runtime'), - { useESModules: treeshake && !isCJS }, + {useESModules: treeshake && !isCJS}, ], require.resolve('babel-plugin-macros'), alias ? [ require.resolve('babel-plugin-module-resolver'), - { root: ['./src'], alias }, + {root: ['./src'], alias}, ] : null, ifAnyDep( ['react', 'preact'], [ require.resolve('babel-plugin-transform-react-remove-prop-types'), - isPreact ? { removeImport: true } : { mode: 'unsafe-wrap' }, + isPreact ? {removeImport: true} : {mode: 'unsafe-wrap'}, ], ), isUMD ? require.resolve('babel-plugin-transform-inline-environment-variables') : null, - [ - require.resolve('@babel/plugin-proposal-class-properties'), - { loose: true }, - ], + [require.resolve('@babel/plugin-proposal-class-properties'), {loose: true}], isMinify ? require.resolve('babel-plugin-minify-dead-code-elimination') : null, @@ -111,4 +108,4 @@ module.exports = () => ({ ? null : require.resolve('@babel/plugin-transform-modules-commonjs'), ].filter(Boolean), -}); +}) diff --git a/src/config/commitlint.config.js b/src/config/commitlint.config.js index 418698da..6768bc91 100644 --- a/src/config/commitlint.config.js +++ b/src/config/commitlint.config.js @@ -2,4 +2,4 @@ module.exports = { // https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum extends: ['@commitlint/config-conventional'], -}; +} diff --git a/src/config/eslintrc.js b/src/config/eslintrc.js index 6ac90da4..df0a23b6 100644 --- a/src/config/eslintrc.js +++ b/src/config/eslintrc.js @@ -1,11 +1,11 @@ -const prettierConfig = require('./prettierrc'); -const { hasLocalConfig } = require('../utils'); +const prettierConfig = require('./prettierrc') +const {hasLocalConfig} = require('../utils') -const args = process.argv.slice(2); +const args = process.argv.slice(2) const useBuiltinConfig = - !args.includes('--config') && !hasLocalConfig('prettier'); -const ruleValue = useBuiltinConfig ? ['error', prettierConfig] : 'error'; + !args.includes('--config') && !hasLocalConfig('prettier') +const ruleValue = useBuiltinConfig ? ['error', prettierConfig] : 'error' module.exports = { extends: [require.resolve('eslint-config-codfish')].filter(Boolean), @@ -14,4 +14,4 @@ module.exports = { // local prettier config is found. 'prettier/prettier': ruleValue, }, -}; +} diff --git a/src/config/huskyrc.js b/src/config/huskyrc.js index 0afde656..b74b6480 100644 --- a/src/config/huskyrc.js +++ b/src/config/huskyrc.js @@ -1,10 +1,10 @@ -const { resolveCodScripts } = require('../utils'); +const {resolveCodScripts} = require('../utils') -const codScripts = resolveCodScripts(); +const codScripts = resolveCodScripts() module.exports = { hooks: { 'pre-commit': `"${codScripts}" pre-commit`, 'commit-msg': `"${codScripts}" commitlint -E HUSKY_GIT_PARAMS`, }, -}; +} diff --git a/src/config/index.js b/src/config/index.js index 5ae6f9c5..a616a205 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -7,4 +7,4 @@ module.exports = { lintStaged: require('./lintstagedrc'), prettier: require('./prettierrc'), getRollupConfig: () => require('./rollup.config'), -}; +} diff --git a/src/config/jest.config.js b/src/config/jest.config.js index ae13d5b2..8e979623 100644 --- a/src/config/jest.config.js +++ b/src/config/jest.config.js @@ -1,10 +1,10 @@ -const path = require('path'); -const { ifAnyDep, hasFile, ifFile, hasPkgProp, fromRoot } = require('../utils'); +const path = require('path') +const {ifAnyDep, hasFile, ifFile, hasPkgProp, fromRoot} = require('../utils') -const here = p => path.join(__dirname, p); +const here = p => path.join(__dirname, p) const useBuiltInBabelConfig = - !hasFile('.babelrc') && !hasFile('.babelrc.js') && !hasPkgProp('babel'); + !hasFile('.babelrc') && !hasFile('.babelrc.js') && !hasPkgProp('babel') const ignores = [ '/node_modules/', @@ -13,7 +13,7 @@ const ignores = [ '/__tests__/helpers/', '/__tests__/utils/', '__mocks__', -]; +] const jestConfig = { roots: [fromRoot(hasFile('src') ? 'src' : '')], @@ -46,7 +46,7 @@ const jestConfig = { require.resolve('jest-watch-typeahead/filename'), require.resolve('jest-watch-typeahead/testname'), ], -}; +} const setupFilesAfterEnv = [ ifAnyDep( @@ -59,20 +59,20 @@ const setupFilesAfterEnv = [ ifFile('tests/setup-env.js', fromRoot('tests/setup-env.js')), ifFile('tests/setup-env.ts', fromRoot('tests/setup-env.ts')), ifFile('tests/setup-env.tsx', fromRoot('tests/setup-env.tsx')), -].filter(Boolean); +].filter(Boolean) if (setupFilesAfterEnv.length) { - jestConfig.setupFilesAfterEnv = setupFilesAfterEnv; + jestConfig.setupFilesAfterEnv = setupFilesAfterEnv } if (useBuiltInBabelConfig) { jestConfig.transform = { '^.+\\.(js|jsx|ts|tsx)$': here('./babel-transform'), - }; + } } if (jestConfig.testEnvironment === 'jsdom') { - jestConfig.setupFiles = [require.resolve('react-app-polyfill/jsdom')]; + jestConfig.setupFiles = [require.resolve('react-app-polyfill/jsdom')] } -module.exports = jestConfig; +module.exports = jestConfig diff --git a/src/config/lintstagedrc.js b/src/config/lintstagedrc.js index 1245b6e8..097ac432 100644 --- a/src/config/lintstagedrc.js +++ b/src/config/lintstagedrc.js @@ -1,7 +1,7 @@ -const { resolveCodScripts, resolveBin } = require('../utils'); +const {resolveCodScripts, resolveBin} = require('../utils') -const codScripts = resolveCodScripts(); -const doctoc = resolveBin('doctoc'); +const codScripts = resolveCodScripts() +const doctoc = resolveBin('doctoc') // differs from kcd because of my eslint setup. Want to format everything other // than js first, then format + lint js using eslint with prettier plugin @@ -14,4 +14,4 @@ module.exports = { `${codScripts} lint --fix`, `${codScripts} test --findRelatedTests`, ].filter(Boolean), -}; +} diff --git a/src/config/prettierrc.js b/src/config/prettierrc.js index b1bb8359..2dff51a0 100644 --- a/src/config/prettierrc.js +++ b/src/config/prettierrc.js @@ -17,4 +17,4 @@ module.exports = { jsxBracketSameLine: false, proseWrap: 'always', vueIndentScriptAndStyle: false, -}; +} diff --git a/src/config/rollup.config.js b/src/config/rollup.config.js index a30c3b8c..dfdf5092 100644 --- a/src/config/rollup.config.js +++ b/src/config/rollup.config.js @@ -1,19 +1,19 @@ -const path = require('path'); -const builtInModules = require('builtin-modules'); -const { babel: rollupBabel } = require('@rollup/plugin-babel'); -const commonjs = require('@rollup/plugin-commonjs'); -const json = require('@rollup/plugin-json'); +const path = require('path') +const builtInModules = require('builtin-modules') +const {babel: rollupBabel} = require('@rollup/plugin-babel') +const commonjs = require('@rollup/plugin-commonjs') +const json = require('@rollup/plugin-json') const { DEFAULTS: nodeResolveDefaults, nodeResolve, -} = require('@rollup/plugin-node-resolve'); -const replace = require('@rollup/plugin-replace'); -const camelcase = require('lodash.camelcase'); -const { terser } = require('rollup-plugin-terser'); -const nodeBuiltIns = require('rollup-plugin-node-builtins'); -const nodeGlobals = require('rollup-plugin-node-globals'); -const { sizeSnapshot } = require('rollup-plugin-size-snapshot'); -const omit = require('lodash.omit'); +} = require('@rollup/plugin-node-resolve') +const replace = require('@rollup/plugin-replace') +const camelcase = require('lodash.camelcase') +const {terser} = require('rollup-plugin-terser') +const nodeBuiltIns = require('rollup-plugin-node-builtins') +const nodeGlobals = require('rollup-plugin-node-globals') +const {sizeSnapshot} = require('rollup-plugin-size-snapshot') +const omit = require('lodash.omit') const { pkg, hasFile, @@ -25,94 +25,92 @@ const { getRollupOutput, uniq, writeExtraEntry, -} = require('../utils'); +} = require('../utils') -const here = p => path.join(__dirname, p); -const capitalize = s => s[0].toUpperCase() + s.slice(1); +const here = p => path.join(__dirname, p) +const capitalize = s => s[0].toUpperCase() + s.slice(1) -const minify = parseEnv('BUILD_MINIFY', false); -const format = process.env.BUILD_FORMAT; -const isPreact = parseEnv('BUILD_PREACT', false); -const isNode = parseEnv('BUILD_NODE', false); -const name = process.env.BUILD_NAME || capitalize(camelcase(pkg.name)); -const useSizeSnapshot = parseEnv('BUILD_SIZE_SNAPSHOT', false); +const minify = parseEnv('BUILD_MINIFY', false) +const format = process.env.BUILD_FORMAT +const isPreact = parseEnv('BUILD_PREACT', false) +const isNode = parseEnv('BUILD_NODE', false) +const name = process.env.BUILD_NAME || capitalize(camelcase(pkg.name)) +const useSizeSnapshot = parseEnv('BUILD_SIZE_SNAPSHOT', false) -const esm = format === 'esm'; -const umd = format === 'umd'; +const esm = format === 'esm' +const umd = format === 'umd' const defaultGlobals = Object.keys(pkg.peerDependencies || {}).reduce( (deps, dep) => { // eslint-disable-next-line no-param-reassign - deps[dep] = capitalize(camelcase(dep)); - return deps; + deps[dep] = capitalize(camelcase(dep)) + return deps }, {}, -); +) -const deps = Object.keys(pkg.dependencies || {}); -const peerDeps = Object.keys(pkg.peerDependencies || {}); +const deps = Object.keys(pkg.dependencies || {}) +const peerDeps = Object.keys(pkg.peerDependencies || {}) const defaultExternal = builtInModules.concat( umd ? peerDeps : deps.concat(peerDeps), -); +) const globals = parseEnv( 'BUILD_GLOBALS', - isPreact - ? Object.assign(defaultGlobals, { preact: 'preact' }) - : defaultGlobals, -); + isPreact ? Object.assign(defaultGlobals, {preact: 'preact'}) : defaultGlobals, +) const external = parseEnv( 'BUILD_EXTERNAL', isPreact ? defaultExternal.concat(['preact', 'prop-types']) : defaultExternal, -).filter((e, i, arry) => arry.indexOf(e) === i); +).filter((e, i, arry) => arry.indexOf(e) === i) if (isPreact) { - delete globals.react; - delete globals['prop-types']; // TODO: is this necessary? - external.splice(external.indexOf('react'), 1); + delete globals.react + delete globals['prop-types'] // TODO: is this necessary? + external.splice(external.indexOf('react'), 1) } -const externalPattern = new RegExp(`^(${external.join('|')})($|/)`); +const externalPattern = new RegExp(`^(${external.join('|')})($|/)`) function externalPredicate(id) { - const isDep = external.length > 0 && externalPattern.test(id); + const isDep = external.length > 0 && externalPattern.test(id) if (umd) { // for UMD, we want to bundle all non-peer deps - return isDep; + return isDep } // for esm/cjs we want to make all node_modules external // TODO: support bundledDependencies if someone needs it ever... - const isNodeModule = id.includes('node_modules'); - const isRelative = id.startsWith('.'); - return isDep || (!isRelative && !path.isAbsolute(id)) || isNodeModule; + const isNodeModule = id.includes('node_modules') + const isRelative = id.startsWith('.') + return isDep || (!isRelative && !path.isAbsolute(id)) || isNodeModule } const useBuiltinConfig = !hasFile('.babelrc') && !hasFile('.babelrc.js') && !hasFile('babel.config.js') && - !hasPkgProp('babel'); -const babelPresets = useBuiltinConfig ? [here('../config/babelrc.js')] : []; + !hasPkgProp('babel') +const babelPresets = useBuiltinConfig ? [here('../config/babelrc.js')] : [] const replacements = Object.entries( umd ? process.env : omit(process.env, ['NODE_ENV']), ).reduce((acc, [key, value]) => { - let val; + let val if (value === 'true' || value === 'false' || Number.isInteger(+value)) { - val = value; + val = value } else { - val = JSON.stringify(value); + val = JSON.stringify(value) } - acc[`process.env.${key}`] = val; - return acc; -}, {}); + acc[`process.env.${key}`] = val + return acc +}, {}) const extensions = hasTypescript ? [...nodeResolveDefaults.extensions, '.ts', '.tsx'] - : nodeResolveDefaults.extensions; + : nodeResolveDefaults.extensions -const input = getRollupInputs(); -const codeSplitting = input.length > 1; +const input = getRollupInputs() +const codeSplitting = input.length > 1 if ( codeSplitting && @@ -121,22 +119,22 @@ if ( throw new Error( 'Filenames of code-splitted entries should be unique to get deterministic output filenames.' + `\nReceived those: ${input}.`, - ); + ) } -const { dirpath, filename } = getRollupOutput(); +const {dirpath, filename} = getRollupOutput() const output = [ { name, ...(codeSplitting - ? { dir: path.join(dirpath, format) } - : { file: path.join(dirpath, filename) }), + ? {dir: path.join(dirpath, format)} + : {file: path.join(dirpath, filename)}), format: esm ? 'es' : format, exports: esm ? 'named' : 'auto', globals, }, -]; +] module.exports = { input: codeSplitting ? input : input[0], @@ -150,7 +148,7 @@ module.exports = { mainFields: ['module', 'main', 'jsnext', 'browser'], extensions, }), - commonjs({ include: 'node_modules/**' }), + commonjs({include: 'node_modules/**'}), json(), rollupBabel({ presets: babelPresets, @@ -159,27 +157,27 @@ module.exports = { extensions, }), replace(replacements), - useSizeSnapshot ? sizeSnapshot({ printInfo: false }) : null, + useSizeSnapshot ? sizeSnapshot({printInfo: false}) : null, minify ? terser() : null, codeSplitting && ((writes = 0) => ({ onwrite() { // eslint-disable-next-line if (++writes !== input.length) { - return; + return } input .filter(single => single.indexOf('index.js') === -1) .forEach(single => { - const chunk = path.basename(single); + const chunk = path.basename(single) writeExtraEntry(chunk.replace(/\..+$/, ''), { cjs: `${dirpath}/cjs/${chunk}`, esm: `${dirpath}/esm/${chunk}`, - }); - }); + }) + }) }, }))(), ].filter(Boolean), -}; +} diff --git a/src/index.js b/src/index.js index 5a8ba7f1..2dcdb9d1 100755 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,12 @@ #!/usr/bin/env node -let shouldThrow = false; +let shouldThrow = false try { - const [major, minor] = process.version.slice(1).split('.').map(Number); + const [major, minor] = process.version.slice(1).split('.').map(Number) shouldThrow = // eslint-disable-next-line global-require,import/no-dynamic-require require(`${process.cwd()}/package.json`).name === 'cod-scripts' && - (major < 10 || (major === 10 && minor < 18)); + (major < 10 || (major === 10 && minor < 18)) } catch (error) { // ignore } @@ -14,7 +14,7 @@ try { if (shouldThrow) { throw new Error( 'You must use Node version 10.18 or greater to run the scripts within cod-scripts, because we dogfood the untranspiled version of the scripts.', - ); + ) } -require('./run-script'); +require('./run-script') diff --git a/src/run-script.js b/src/run-script.js index e1d6bd1a..66705135 100755 --- a/src/run-script.js +++ b/src/run-script.js @@ -1,14 +1,14 @@ -const path = require('path'); -const spawn = require('cross-spawn'); -const glob = require('glob'); +const path = require('path') +const spawn = require('cross-spawn') +const glob = require('glob') -const [executor, ignoredBin, script] = process.argv; +const [executor, ignoredBin, script] = process.argv if (script && script !== '--help' && script !== 'help') { - spawnScript(); + spawnScript() } else { - const scriptsPath = path.join(__dirname, 'scripts/'); - const scriptsAvailable = glob.sync(path.join(__dirname, 'scripts', '*')); + const scriptsPath = path.join(__dirname, 'scripts/') + const scriptsAvailable = glob.sync(path.join(__dirname, 'scripts', '*')) // `glob.sync` returns paths with unix style path separators even on Windows. // So we normalize it before attempting to strip out the scripts path. const scriptsAvailableMessage = scriptsAvailable @@ -21,7 +21,7 @@ if (script && script !== '--help' && script !== 'help') { ) .filter(Boolean) .join('\n ') - .trim(); + .trim() const fullMessage = ` Usage: ${ignoredBin} [script] [--flags] @@ -32,8 +32,8 @@ Options: All options depend on the script. Docs will be improved eventually, but for most scripts you can assume that the args you pass will be forwarded to the respective tool that's being run under the hood. May the force be with you. - `.trim(); - console.log(`\n${fullMessage}\n`); + `.trim() + console.log(`\n${fullMessage}\n`) } function getEnv() { @@ -41,9 +41,9 @@ function getEnv() { // https://github.com/kentcdodds/kcd-scripts/issues/4 return Object.keys(process.env) .filter(key => process.env[key] !== undefined) - .reduce((envCopy, key) => ({ ...envCopy, [key]: process.env[key] }), { + .reduce((envCopy, key) => ({...envCopy, [key]: process.env[key]}), { [`SCRIPTS_${script.toUpperCase()}`]: true, - }); + }) } function handleSignal(result) { @@ -52,29 +52,29 @@ function handleSignal(result) { `The script "${script}" failed because the process exited too early. ` + 'This probably means the system ran out of memory or someone called ' + '`kill -9` on the process.', - ); + ) } else if (result.signal === 'SIGTERM') { console.log( `The script "${script}" failed because the process exited too early. ` + 'Someone might have called `kill` or `killall`, or the system could ' + 'be shutting down.', - ); + ) } - process.exit(1); + process.exit(1) } function attemptResolve(...resolveArgs) { try { - return require.resolve(...resolveArgs); + return require.resolve(...resolveArgs) } catch (error) { - return null; + return null } } function spawnScript() { // get all the arguments of the script and find the position of our script // commands - const args = process.argv.slice(2); + const args = process.argv.slice(2) const scriptIndex = args.findIndex(x => [ 'build', @@ -86,20 +86,20 @@ function spawnScript() { 'commitlint', 'typecheck', ].includes(x), - ); + ) // Extract the node arguments so we can pass them to node later on - const buildCommand = scriptIndex === -1 ? args[0] : args[scriptIndex]; - const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : []; + const buildCommand = scriptIndex === -1 ? args[0] : args[scriptIndex] + const nodeArgs = scriptIndex > 0 ? args.slice(0, scriptIndex) : [] if (!buildCommand) { - throw new Error(`Unknown script "${script}".`); + throw new Error(`Unknown script "${script}".`) } - const relativeScriptPath = path.join(__dirname, './scripts', buildCommand); - const scriptPath = attemptResolve(relativeScriptPath); + const relativeScriptPath = path.join(__dirname, './scripts', buildCommand) + const scriptPath = attemptResolve(relativeScriptPath) if (!scriptPath) { - throw new Error(`Unknown script "${script}".`); + throw new Error(`Unknown script "${script}".`) } // Attempt to strt the script with the passed node arguments @@ -110,11 +110,11 @@ function spawnScript() { stdio: 'inherit', env: getEnv(), }, - ); + ) if (result.signal) { - handleSignal(result); + handleSignal(result) } else { - process.exit(result.status); + process.exit(result.status) } } diff --git a/src/scripts/__tests__/format.js b/src/scripts/__tests__/format.js index d796bcae..489d0fc6 100644 --- a/src/scripts/__tests__/format.js +++ b/src/scripts/__tests__/format.js @@ -1,35 +1,35 @@ -import cases from 'jest-in-case'; -import { unquoteSerializer, winPathSerializer } from './helpers/serializers'; +import cases from 'jest-in-case' +import {unquoteSerializer, winPathSerializer} from './helpers/serializers' -expect.addSnapshotSerializer(unquoteSerializer); -expect.addSnapshotSerializer(winPathSerializer); +expect.addSnapshotSerializer(unquoteSerializer) +expect.addSnapshotSerializer(winPathSerializer) cases( 'format', - ({ args }) => { + ({args}) => { // beforeEach - const { sync: crossSpawnSyncMock } = require('cross-spawn'); - const originalExit = process.exit; - const originalArgv = process.argv; - const utils = require('../../utils'); - utils.resolveBin = (modName, { executable = modName } = {}) => executable; - process.exit = jest.fn(); + const {sync: crossSpawnSyncMock} = require('cross-spawn') + const originalExit = process.exit + const originalArgv = process.argv + const utils = require('../../utils') + utils.resolveBin = (modName, {executable = modName} = {}) => executable + process.exit = jest.fn() // tests - process.argv = ['node', '../format', ...args]; - require('../format'); - expect(crossSpawnSyncMock).toHaveBeenCalledTimes(2); - const [firstCall] = crossSpawnSyncMock.mock.calls; - const [script, calledArgs] = firstCall; - expect([script, ...calledArgs].join(' ')).toMatchSnapshot(); - const [secondCall] = crossSpawnSyncMock.mock.calls; - const [secondScript, secondCalledArgs] = secondCall; - expect([secondScript, ...secondCalledArgs].join(' ')).toMatchSnapshot(); + process.argv = ['node', '../format', ...args] + require('../format') + expect(crossSpawnSyncMock).toHaveBeenCalledTimes(2) + const [firstCall] = crossSpawnSyncMock.mock.calls + const [script, calledArgs] = firstCall + expect([script, ...calledArgs].join(' ')).toMatchSnapshot() + const [secondCall] = crossSpawnSyncMock.mock.calls + const [secondScript, secondCalledArgs] = secondCall + expect([secondScript, ...secondCalledArgs].join(' ')).toMatchSnapshot() // afterEach - process.exit = originalExit; - process.argv = originalArgv; - jest.resetModules(); + process.exit = originalExit + process.argv = originalArgv + jest.resetModules() }, { 'calls prettier CLI with args': { @@ -45,4 +45,4 @@ cases( args: ['--ignore-path', './.myignore'], }, }, -); +) diff --git a/src/scripts/__tests__/helpers/serializers.js b/src/scripts/__tests__/helpers/serializers.js index baede0a5..3cded83a 100644 --- a/src/scripts/__tests__/helpers/serializers.js +++ b/src/scripts/__tests__/helpers/serializers.js @@ -1,25 +1,25 @@ -import slash from 'slash'; +import slash from 'slash' // this removes the quotes around strings... export const unquoteSerializer = { print: val => val, test: val => typeof val === 'string', -}; +} // this converts windows style file paths to unix... export const winPathSerializer = { print: val => slash(val), test: val => typeof val === 'string' && val.includes('\\'), -}; +} function normalizePaths(value) { if (typeof value !== 'string') { - return value; + return value } - return slash(value.split(process.cwd()).join('')); + return slash(value.split(process.cwd()).join('')) } export const relativePathSerializer = { print: val => normalizePaths(val), test: val => normalizePaths(val) !== val, -}; +} diff --git a/src/scripts/__tests__/lint.js b/src/scripts/__tests__/lint.js index 3a3094d0..d3c0c3bf 100644 --- a/src/scripts/__tests__/lint.js +++ b/src/scripts/__tests__/lint.js @@ -1,13 +1,13 @@ -import cases from 'jest-in-case'; +import cases from 'jest-in-case' import { unquoteSerializer, winPathSerializer, relativePathSerializer, -} from './helpers/serializers'; +} from './helpers/serializers' -expect.addSnapshotSerializer(unquoteSerializer); -expect.addSnapshotSerializer(winPathSerializer); -expect.addSnapshotSerializer(relativePathSerializer); +expect.addSnapshotSerializer(unquoteSerializer) +expect.addSnapshotSerializer(winPathSerializer) +expect.addSnapshotSerializer(relativePathSerializer) cases( 'lint', @@ -19,34 +19,34 @@ cases( setup = () => () => {}, }) => { // beforeEach - const { sync: crossSpawnSyncMock } = require('cross-spawn'); - const originalArgv = process.argv; - const originalExit = process.exit; + const {sync: crossSpawnSyncMock} = require('cross-spawn') + const originalArgv = process.argv + const originalExit = process.exit Object.assign(utils, { hasPkgProp, hasFile, - resolveBin: (modName, { executable = modName } = {}) => executable, - }); - process.exit = jest.fn(); - const teardown = setup(); + resolveBin: (modName, {executable = modName} = {}) => executable, + }) + process.exit = jest.fn() + const teardown = setup() - process.argv = ['node', '../lint', ...args]; + process.argv = ['node', '../lint', ...args] try { // tests - require('../lint'); - expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1); - const [firstCall] = crossSpawnSyncMock.mock.calls; - const [script, calledArgs] = firstCall; - expect([script, ...calledArgs].join(' ')).toMatchSnapshot(); + require('../lint') + expect(crossSpawnSyncMock).toHaveBeenCalledTimes(1) + const [firstCall] = crossSpawnSyncMock.mock.calls + const [script, calledArgs] = firstCall + expect([script, ...calledArgs].join(' ')).toMatchSnapshot() } catch (error) { - throw error; + throw error } finally { - teardown(); + teardown() // afterEach - process.exit = originalExit; - process.argv = originalArgv; - jest.resetModules(); + process.exit = originalExit + process.argv = originalArgv + jest.resetModules() } }, { @@ -89,4 +89,4 @@ cases( ], }, }, -); +) diff --git a/src/scripts/__tests__/pre-commit.js b/src/scripts/__tests__/pre-commit.js index d9530a5e..12f653bc 100644 --- a/src/scripts/__tests__/pre-commit.js +++ b/src/scripts/__tests__/pre-commit.js @@ -1,8 +1,8 @@ -import cases from 'jest-in-case'; -import { unquoteSerializer, winPathSerializer } from './helpers/serializers'; +import cases from 'jest-in-case' +import {unquoteSerializer, winPathSerializer} from './helpers/serializers' -expect.addSnapshotSerializer(unquoteSerializer); -expect.addSnapshotSerializer(winPathSerializer); +expect.addSnapshotSerializer(unquoteSerializer) +expect.addSnapshotSerializer(winPathSerializer) cases( 'pre-commit', @@ -13,34 +13,34 @@ cases( hasFile = () => false, }) => { // beforeEach - const { sync: crossSpawnSyncMock } = require('cross-spawn'); - const originalArgv = process.argv; - const originalExit = process.exit; + const {sync: crossSpawnSyncMock} = require('cross-spawn') + const originalArgv = process.argv + const originalExit = process.exit Object.assign(utils, { hasPkgProp, hasFile, - resolveBin: (modName, { executable = modName } = {}) => executable, - }); - process.exit = jest.fn(); + resolveBin: (modName, {executable = modName} = {}) => executable, + }) + process.exit = jest.fn() - process.argv = ['node', '../pre-commit', ...args]; + process.argv = ['node', '../pre-commit', ...args] try { // tests - require('../pre-commit'); - expect(crossSpawnSyncMock).toHaveBeenCalledTimes(2); - const [firstCall, secondCall] = crossSpawnSyncMock.mock.calls; - const [scriptOne, calledArgsOne] = firstCall; - expect([scriptOne, ...calledArgsOne].join(' ')).toMatchSnapshot(); - const [scriptTwo, calledArgsTwo] = secondCall; - expect([scriptTwo, ...calledArgsTwo].join(' ')).toMatchSnapshot(); + require('../pre-commit') + expect(crossSpawnSyncMock).toHaveBeenCalledTimes(2) + const [firstCall, secondCall] = crossSpawnSyncMock.mock.calls + const [scriptOne, calledArgsOne] = firstCall + expect([scriptOne, ...calledArgsOne].join(' ')).toMatchSnapshot() + const [scriptTwo, calledArgsTwo] = secondCall + expect([scriptTwo, ...calledArgsTwo].join(' ')).toMatchSnapshot() } catch (error) { - throw error; + throw error } finally { // afterEach - process.exit = originalExit; - process.argv = originalArgv; - jest.resetModules(); + process.exit = originalExit + process.argv = originalArgv + jest.resetModules() } }, { @@ -61,4 +61,4 @@ cases( args: ['--verbose'], }, }, -); +) diff --git a/src/scripts/__tests__/test.js b/src/scripts/__tests__/test.js index c8add504..3069a317 100644 --- a/src/scripts/__tests__/test.js +++ b/src/scripts/__tests__/test.js @@ -1,12 +1,12 @@ -import cases from 'jest-in-case'; -import { unquoteSerializer } from './helpers/serializers'; +import cases from 'jest-in-case' +import {unquoteSerializer} from './helpers/serializers' -jest.mock('jest', () => ({ run: jest.fn() })); -jest.mock('../../config/jest.config', () => ({ builtInConfig: true })); -let mockIsCI = false; -jest.mock('is-ci', () => mockIsCI); +jest.mock('jest', () => ({run: jest.fn()})) +jest.mock('../../config/jest.config', () => ({builtInConfig: true})) +let mockIsCI = false +jest.mock('is-ci', () => mockIsCI) -expect.addSnapshotSerializer(unquoteSerializer); +expect.addSnapshotSerializer(unquoteSerializer) cases( 'test', @@ -21,37 +21,37 @@ cases( }) => { // beforeEach // eslint-disable-next-line jest/no-jest-import - const { run: jestRunMock } = require('jest'); - const originalArgv = process.argv; - const prevCI = mockIsCI; - const prevPreCommit = process.env['SCRIPTS_PRE-COMMIT']; - mockIsCI = ci; - process.env['SCRIPTS_PRE-COMMIT'] = preCommit; + const {run: jestRunMock} = require('jest') + const originalArgv = process.argv + const prevCI = mockIsCI + const prevPreCommit = process.env['SCRIPTS_PRE-COMMIT'] + mockIsCI = ci + process.env['SCRIPTS_PRE-COMMIT'] = preCommit Object.assign(utils, { hasPkgProp: () => pkgHasJestProp, hasFile: () => hasJestConfigFile, - }); - process.exit = jest.fn(); - const teardown = setup(); + }) + process.exit = jest.fn() + const teardown = setup() - process.argv = ['node', '../test', ...args]; + process.argv = ['node', '../test', ...args] try { // tests - require('../test'); - expect(jestRunMock).toHaveBeenCalledTimes(1); - const [firstCall] = jestRunMock.mock.calls; - const [jestArgs] = firstCall; - expect(jestArgs.join(' ')).toMatchSnapshot(); + require('../test') + expect(jestRunMock).toHaveBeenCalledTimes(1) + const [firstCall] = jestRunMock.mock.calls + const [jestArgs] = firstCall + expect(jestArgs.join(' ')).toMatchSnapshot() } catch (error) { - throw error; + throw error } finally { - teardown(); + teardown() // afterEach - process.argv = originalArgv; - mockIsCI = prevCI; - process.env['SCRIPTS_PRE-COMMIT'] = prevPreCommit; - jest.resetModules(); + process.argv = originalArgv + mockIsCI = prevCI + process.env['SCRIPTS_PRE-COMMIT'] = prevPreCommit + jest.resetModules() } }, { @@ -84,4 +84,4 @@ cases( args: ['--coverage', '--watch'], }, }, -); +) diff --git a/src/scripts/__tests__/validate.js b/src/scripts/__tests__/validate.js index 4e7b50df..c92380e3 100644 --- a/src/scripts/__tests__/validate.js +++ b/src/scripts/__tests__/validate.js @@ -1,73 +1,73 @@ -import cases from 'jest-in-case'; -import { unquoteSerializer } from './helpers/serializers'; +import cases from 'jest-in-case' +import {unquoteSerializer} from './helpers/serializers' -expect.addSnapshotSerializer(unquoteSerializer); +expect.addSnapshotSerializer(unquoteSerializer) function setupWithScripts(scripts = ['test', 'lint', 'build', 'typecheck']) { return function setup() { - const utils = require('../../utils'); - const originalIfScript = utils.ifScript; - utils.ifScript = (script, t, f) => (scripts.includes(script) ? t : f); + const utils = require('../../utils') + const originalIfScript = utils.ifScript + utils.ifScript = (script, t, f) => (scripts.includes(script) ? t : f) return function teardown() { - utils.ifScript = originalIfScript; - }; - }; + utils.ifScript = originalIfScript + } + } } function setupWithArgs(args = []) { return function setup() { - const utils = require('../../utils'); - const originalResolveBin = utils.resolveBin; - utils.resolveBin = (modName, { executable = modName } = {}) => executable; - const originalArgv = process.argv; - process.argv = ['node', '../format', ...args]; + const utils = require('../../utils') + const originalResolveBin = utils.resolveBin + utils.resolveBin = (modName, {executable = modName} = {}) => executable + const originalArgv = process.argv + process.argv = ['node', '../format', ...args] return function teardown() { - process.argv = originalArgv; - utils.resolveBin = originalResolveBin; - }; - }; + process.argv = originalArgv + utils.resolveBin = originalResolveBin + } + } } function withDefaultSetup(setupFn) { return function defaultSetup() { - const utils = require('../../utils'); - utils.resolveBin = (modName, { executable = modName } = {}) => executable; - const argsTeardown = setupWithArgs()(); - const teardownScripts = setupWithScripts()(); - const teardownFn = setupFn(); + const utils = require('../../utils') + utils.resolveBin = (modName, {executable = modName} = {}) => executable + const argsTeardown = setupWithArgs()() + const teardownScripts = setupWithScripts()() + const teardownFn = setupFn() return function defaultTeardown() { - argsTeardown(); - teardownFn(); - teardownScripts(); - }; - }; + argsTeardown() + teardownFn() + teardownScripts() + } + } } cases( 'validate', - ({ setup = () => () => {} }) => { + ({setup = () => () => {}}) => { // beforeEach - const { sync: crossSpawnSyncMock } = require('cross-spawn'); - const originalExit = process.exit; - process.exit = jest.fn(); - process.env['SCRIPTS_PRE-COMMIT'] = 'false'; - const teardown = setup(); + const {sync: crossSpawnSyncMock} = require('cross-spawn') + const originalExit = process.exit + process.exit = jest.fn() + process.env['SCRIPTS_PRE-COMMIT'] = 'false' + const teardown = setup() try { // tests - require('../validate'); - const [firstCall] = crossSpawnSyncMock.mock.calls; - const [script, calledArgs] = firstCall || ['', []]; - expect([script, ...calledArgs].join(' ')).toMatchSnapshot(); + require('../validate') + const [firstCall] = crossSpawnSyncMock.mock.calls + const [script, calledArgs] = firstCall || ['', []] + expect([script, ...calledArgs].join(' ')).toMatchSnapshot() } catch (error) { - throw error; + throw error } finally { - teardown(); + teardown() } // afterEach - process.exit = originalExit; - jest.resetModules(); + process.exit = originalExit + jest.resetModules() }, { 'calls concurrently with all scripts': { @@ -90,15 +90,15 @@ cases( }, [`doesn't use test or lint if it's in pre-commit`]: { setup: withDefaultSetup(() => { - const previousVal = process.env['SCRIPTS_PRE-COMMIT']; - process.env['SCRIPTS_PRE-COMMIT'] = 'true'; + const previousVal = process.env['SCRIPTS_PRE-COMMIT'] + process.env['SCRIPTS_PRE-COMMIT'] = 'true' return function teardown() { - process.env['SCRIPTS_PRE-COMMIT'] = previousVal; - }; + process.env['SCRIPTS_PRE-COMMIT'] = previousVal + } }), }, 'exits if there are no scripts to be run': { setup: withDefaultSetup(setupWithScripts([])), }, }, -); +) diff --git a/src/scripts/build/babel.js b/src/scripts/build/babel.js index e656eb3a..b176ceb0 100644 --- a/src/scripts/build/babel.js +++ b/src/scripts/build/babel.js @@ -1,9 +1,9 @@ -const path = require('path'); -const { DEFAULT_EXTENSIONS } = require('@babel/core'); -const spawn = require('cross-spawn'); -const yargsParser = require('yargs-parser'); -const rimraf = require('rimraf'); -const glob = require('glob'); +const path = require('path') +const {DEFAULT_EXTENSIONS} = require('@babel/core') +const spawn = require('cross-spawn') +const yargsParser = require('yargs-parser') +const rimraf = require('rimraf') +const glob = require('glob') const { hasPkgProp, fromRoot, @@ -11,52 +11,52 @@ const { hasFile, hasTypescript, generateTypeDefs, -} = require('../../utils'); +} = require('../../utils') -let args = process.argv.slice(2); -const here = p => path.join(__dirname, p); +let args = process.argv.slice(2) +const here = p => path.join(__dirname, p) -const parsedArgs = yargsParser(args); +const parsedArgs = yargsParser(args) const useBuiltinConfig = !args.includes('--presets') && !hasFile('.babelrc') && !hasFile('.babelrc.js') && !hasFile('babel.config.js') && - !hasPkgProp('babel'); + !hasPkgProp('babel') const config = useBuiltinConfig ? ['--presets', here('../../config/babelrc.js')] - : []; + : [] const extensions = args.includes('--extensions') || args.includes('--x') ? [] - : ['--extensions', [...DEFAULT_EXTENSIONS, '.ts', '.tsx']]; + : ['--extensions', [...DEFAULT_EXTENSIONS, '.ts', '.tsx']] -const builtInIgnore = '**/__tests__/**,**/__mocks__/**'; +const builtInIgnore = '**/__tests__/**,**/__mocks__/**' -const ignore = args.includes('--ignore') ? [] : ['--ignore', builtInIgnore]; +const ignore = args.includes('--ignore') ? [] : ['--ignore', builtInIgnore] -const copyFiles = args.includes('--no-copy-files') ? [] : ['--copy-files']; +const copyFiles = args.includes('--no-copy-files') ? [] : ['--copy-files'] -const useSpecifiedOutDir = args.includes('--out-dir'); -const builtInOutDir = 'dist'; -const outDir = useSpecifiedOutDir ? [] : ['--out-dir', builtInOutDir]; -const noTypeDefinitions = args.includes('--no-ts-defs'); +const useSpecifiedOutDir = args.includes('--out-dir') +const builtInOutDir = 'dist' +const outDir = useSpecifiedOutDir ? [] : ['--out-dir', builtInOutDir] +const noTypeDefinitions = args.includes('--no-ts-defs') if (!useSpecifiedOutDir && !args.includes('--no-clean')) { - rimraf.sync(fromRoot('dist')); + rimraf.sync(fromRoot('dist')) } else { - args = args.filter(a => a !== '--no-clean'); + args = args.filter(a => a !== '--no-clean') } if (noTypeDefinitions) { - args = args.filter(a => a !== '--no-ts-defs'); + args = args.filter(a => a !== '--no-ts-defs') } function go() { let result = spawn.sync( - resolveBin('@babel/cli', { executable: 'babel' }), + resolveBin('@babel/cli', {executable: 'babel'}), [ ...outDir, ...copyFiles, @@ -65,32 +65,32 @@ function go() { ...config, 'src', ].concat(args), - { stdio: 'inherit' }, - ); - if (result.status !== 0) return result.status; + {stdio: 'inherit'}, + ) + if (result.status !== 0) return result.status - const pathToOutDir = fromRoot(parsedArgs.outDir || builtInOutDir); + const pathToOutDir = fromRoot(parsedArgs.outDir || builtInOutDir) if (hasTypescript && !noTypeDefinitions) { - console.log('Generating TypeScript definitions'); - result = generateTypeDefs(pathToOutDir); - console.log('TypeScript definitions generated'); - if (result.status !== 0) return result.status; + console.log('Generating TypeScript definitions') + result = generateTypeDefs(pathToOutDir) + console.log('TypeScript definitions generated') + if (result.status !== 0) return result.status } // because babel will copy even ignored files, we need to remove the ignored files const ignoredPatterns = (parsedArgs.ignore || builtInIgnore) .split(',') - .map(pattern => path.join(pathToOutDir, pattern)); + .map(pattern => path.join(pathToOutDir, pattern)) const ignoredFiles = ignoredPatterns.reduce( (all, pattern) => [...all, ...glob.sync(pattern)], [], - ); + ) ignoredFiles.forEach(ignoredFile => { - rimraf.sync(ignoredFile); - }); + rimraf.sync(ignoredFile) + }) - return result.status; + return result.status } -process.exit(go()); +process.exit(go()) diff --git a/src/scripts/build/index.js b/src/scripts/build/index.js index f3f380db..a209b7aa 100644 --- a/src/scripts/build/index.js +++ b/src/scripts/build/index.js @@ -1,9 +1,9 @@ if (process.argv.includes('--browser')) { - console.error('--browser has been deprecated, use --bundle instead'); + console.error('--browser has been deprecated, use --bundle instead') } if (process.argv.includes('--bundle')) { - require('./rollup'); + require('./rollup') } else { - require('./babel'); + require('./babel') } diff --git a/src/scripts/build/rollup.js b/src/scripts/build/rollup.js index a472d418..19b858ed 100644 --- a/src/scripts/build/rollup.js +++ b/src/scripts/build/rollup.js @@ -1,9 +1,9 @@ -const path = require('path'); -const fs = require('fs'); -const spawn = require('cross-spawn'); -const glob = require('glob'); -const rimraf = require('rimraf'); -const yargsParser = require('yargs-parser'); +const path = require('path') +const fs = require('fs') +const spawn = require('cross-spawn') +const glob = require('glob') +const rimraf = require('rimraf') +const yargsParser = require('yargs-parser') const { hasFile, resolveBin, @@ -14,64 +14,64 @@ const { generateTypeDefs, getRollupInputs, getRollupOutput, -} = require('../../utils'); +} = require('../../utils') -const crossEnv = resolveBin('cross-env'); -const rollup = resolveBin('rollup'); -const args = process.argv.slice(2); -const here = p => path.join(__dirname, p); -const hereRelative = p => here(p).replace(process.cwd(), '.'); -const parsedArgs = yargsParser(args); +const crossEnv = resolveBin('cross-env') +const rollup = resolveBin('rollup') +const args = process.argv.slice(2) +const here = p => path.join(__dirname, p) +const hereRelative = p => here(p).replace(process.cwd(), '.') +const parsedArgs = yargsParser(args) const useBuiltinConfig = - !args.includes('--config') && !hasFile('rollup.config.js'); + !args.includes('--config') && !hasFile('rollup.config.js') // eslint-disable-next-line const config = useBuiltinConfig ? `--config ${hereRelative('../../config/rollup.config.js')}` : args.includes('--config') ? '' - : '--config'; // --config will pick up the rollup.config.js file + : '--config' // --config will pick up the rollup.config.js file const environment = parsedArgs.environment ? `--environment ${parsedArgs.environment}` - : ''; -const watch = parsedArgs.watch ? '--watch' : ''; -const sizeSnapshot = parsedArgs['size-snapshot']; + : '' +const watch = parsedArgs.watch ? '--watch' : '' +const sizeSnapshot = parsedArgs['size-snapshot'] -let formats = ['esm', 'cjs', 'umd', 'umd.min']; +let formats = ['esm', 'cjs', 'umd', 'umd.min'] if (typeof parsedArgs.bundle === 'string') { - formats = parsedArgs.bundle.split(','); + formats = parsedArgs.bundle.split(',') } -const defaultEnv = 'BUILD_ROLLUP=true'; +const defaultEnv = 'BUILD_ROLLUP=true' const getCommand = (env, ...flags) => [crossEnv, defaultEnv, env, rollup, config, environment, watch, ...flags] .filter(Boolean) - .join(' '); + .join(' ') -const buildPreact = args.includes('--p-react'); +const buildPreact = args.includes('--p-react') const scripts = getConcurrentlyArgs( buildPreact ? getPReactCommands() : getCommands(), -); +) -const cleanBuildDirs = !args.includes('--no-clean'); +const cleanBuildDirs = !args.includes('--no-clean') if (cleanBuildDirs) { - rimraf.sync(fromRoot('dist')); + rimraf.sync(fromRoot('dist')) if (buildPreact) { - rimraf.sync(fromRoot('preact')); + rimraf.sync(fromRoot('preact')) } } function go() { let result = spawn.sync(resolveBin('concurrently'), scripts, { stdio: 'inherit', - }); + }) - if (result.status !== 0) return result.status; + if (result.status !== 0) return result.status if (buildPreact && !args.includes('--no-package-json')) { writeExtraEntry( @@ -81,43 +81,43 @@ function go() { esm: glob.sync(fromRoot('preact/**/*.esm.js'))[0], }, false, - ); + ) } if (hasTypescript && !args.includes('--no-ts-defs')) { - console.log('Generating TypeScript definitions'); - result = generateTypeDefs(fromRoot('dist')); - if (result.status !== 0) return result.status; + console.log('Generating TypeScript definitions') + result = generateTypeDefs(fromRoot('dist')) + if (result.status !== 0) return result.status - const rollupInputs = getRollupInputs(); + const rollupInputs = getRollupInputs() const typeDefFiles = rollupInputs.map(input => { return input .replace(path.join(process.cwd(), 'src'), 'dist') - .replace(/\.(t|j)sx?$/, '.d.ts'); - }); + .replace(/\.(t|j)sx?$/, '.d.ts') + }) for (const format of formats) { - const { dirpath, filename } = getRollupOutput(format); + const {dirpath, filename} = getRollupOutput(format) - const isCodesplitting = rollupInputs.length > 1; + const isCodesplitting = rollupInputs.length > 1 const outputs = isCodesplitting ? glob.sync(fromRoot(path.join(dirpath, format, '*.js'))) - : [fromRoot(path.join(dirpath, filename))]; + : [fromRoot(path.join(dirpath, filename))] for (const output of outputs) { - const { name, dir } = path.parse(output); + const {name, dir} = path.parse(output) const typeDef = isCodesplitting ? typeDefFiles.find(f => path.basename(f) === `${name}.d.ts`) - : 'dist/index.d.ts'; + : 'dist/index.d.ts' const relativePath = path .join(path.relative(dir, process.cwd()), typeDef) - .replace(/\.d\.ts$/, ''); + .replace(/\.d\.ts$/, '') // make a .d.ts file for every generated file that re-exports index.d.ts fs.writeFileSync( path.join(dir, `${name}.d.ts`), `export * from "${relativePath}";\n`, - ); + ) } } @@ -126,36 +126,36 @@ function go() { const ignoredFiles = [ ...glob.sync(fromRoot('dist', '**/__tests__/**')), ...glob.sync(fromRoot('dist', '**/__mocks__/**')), - ]; + ] ignoredFiles.forEach(ignoredFile => { - rimraf.sync(ignoredFile); - }); - console.log('TypeScript definitions generated'); + rimraf.sync(ignoredFile) + }) + console.log('TypeScript definitions generated') } - return result.status; + return result.status } function getPReactCommands() { return { ...prefixKeys('react.', getCommands()), - ...prefixKeys('preact.', getCommands({ preact: true })), - }; + ...prefixKeys('preact.', getCommands({preact: true})), + } } function prefixKeys(prefix, object) { return Object.entries(object).reduce((cmds, [key, value]) => { - cmds[`${prefix}${key}`] = value; - return cmds; - }, {}); + cmds[`${prefix}${key}`] = value + return cmds + }, {}) } -function getCommands({ preact = false } = {}) { +function getCommands({preact = false} = {}) { return formats.reduce((cmds, format) => { - const [formatName, minify = false] = format.split('.'); - const nodeEnv = minify ? 'production' : 'development'; - const sourceMap = formatName === 'umd' ? '--sourcemap' : ''; - const buildMinify = Boolean(minify); + const [formatName, minify = false] = format.split('.') + const nodeEnv = minify ? 'production' : 'development' + const sourceMap = formatName === 'umd' ? '--sourcemap' : '' + const buildMinify = Boolean(minify) cmds[format] = getCommand( [ @@ -168,9 +168,9 @@ function getCommands({ preact = false } = {}) { `BUILD_REACT_NATIVE=${process.env.BUILD_REACT_NATIVE || false}`, ].join(' '), sourceMap, - ); - return cmds; - }, {}); + ) + return cmds + }, {}) } -process.exit(go()); +process.exit(go()) diff --git a/src/scripts/commitlint.js b/src/scripts/commitlint.js index 38d8cf54..fbbaa1ee 100644 --- a/src/scripts/commitlint.js +++ b/src/scripts/commitlint.js @@ -1,10 +1,10 @@ -const path = require('path'); -const spawn = require('cross-spawn'); -const { hasPkgProp, resolveBin, hasFile } = require('../utils'); +const path = require('path') +const spawn = require('cross-spawn') +const {hasPkgProp, resolveBin, hasFile} = require('../utils') -const args = process.argv.slice(2); -const here = p => path.join(__dirname, p); -const hereRelative = p => here(p).replace(process.cwd(), '.'); +const args = process.argv.slice(2) +const here = p => path.join(__dirname, p) +const hereRelative = p => here(p).replace(process.cwd(), '.') const useBuiltinConfig = !args.includes('--config') && @@ -13,14 +13,14 @@ const useBuiltinConfig = !hasFile('.commitlintrc.js') && !hasFile('.commitlintrc.json') && !hasFile('.commitlintrc.yml') && - !hasPkgProp('commitlint'); + !hasPkgProp('commitlint') const config = useBuiltinConfig ? ['--config', hereRelative('../config/commitlint.config.js')] - : []; + : [] const result = spawn.sync(resolveBin('commitlint'), [...config, ...args], { stdio: 'inherit', -}); +}) -process.exit(result.status); +process.exit(result.status) diff --git a/src/scripts/format.js b/src/scripts/format.js index 31ac7753..148da7b5 100644 --- a/src/scripts/format.js +++ b/src/scripts/format.js @@ -1,49 +1,49 @@ -const path = require('path'); -const spawn = require('cross-spawn'); -const yargsParser = require('yargs-parser'); +const path = require('path') +const spawn = require('cross-spawn') +const yargsParser = require('yargs-parser') const { resolveBin, hasFile, hasLocalConfig, resolveCodScripts, -} = require('../utils'); +} = require('../utils') -const args = process.argv.slice(2); -const parsedArgs = yargsParser(args); +const args = process.argv.slice(2) +const parsedArgs = yargsParser(args) -const here = p => path.join(__dirname, p); -const hereRelative = p => here(p).replace(process.cwd(), '.'); +const here = p => path.join(__dirname, p) +const hereRelative = p => here(p).replace(process.cwd(), '.') const useBuiltinConfig = - !args.includes('--config') && !hasLocalConfig('prettier'); + !args.includes('--config') && !hasLocalConfig('prettier') const config = useBuiltinConfig ? ['--config', hereRelative('../config/prettierrc.js')] - : []; + : [] const useBuiltinIgnore = - !args.includes('--ignore-path') && !hasFile('.prettierignore'); + !args.includes('--ignore-path') && !hasFile('.prettierignore') const ignore = useBuiltinIgnore ? ['--ignore-path', hereRelative('../config/prettierignore')] - : []; + : [] -const write = args.includes('--no-write') ? [] : ['--write']; +const write = args.includes('--no-write') ? [] : ['--write'] // this ensures that when running format as a pre-commit hook and we get // the full file path, we make that non-absolute so it is treated as a glob, // This way the prettierignore will be applied -const relativeArgs = args.map(a => a.replace(`${process.cwd()}/`, '')); +const relativeArgs = args.map(a => a.replace(`${process.cwd()}/`, '')) const filesToApply = parsedArgs._.length ? [] - : ['**/*.+(md|json|yml|yaml|css|less|scss|sass|graphql|ts|tsx)']; + : ['**/*.+(md|json|yml|yaml|css|less|scss|sass|graphql|ts|tsx)'] // run prettier on all non-js files const prettierResult = spawn.sync( resolveBin('prettier'), [...config, ...ignore, ...write, ...filesToApply].concat(relativeArgs), - { stdio: 'inherit' }, -); + {stdio: 'inherit'}, +) if (prettierResult.status !== 0 || args.includes('--no-eslint')) { - process.exit(prettierResult.status); + process.exit(prettierResult.status) } // run eslint for js files (`eslint-plugin-prettier` will run prettier for us) @@ -53,6 +53,6 @@ const eslintResult = spawn.sync( { stdio: 'inherit', }, -); +) -process.exit(eslintResult.status); +process.exit(eslintResult.status) diff --git a/src/scripts/lint.js b/src/scripts/lint.js index 1bed23f8..9baeebb2 100644 --- a/src/scripts/lint.js +++ b/src/scripts/lint.js @@ -1,35 +1,35 @@ -const path = require('path'); -const spawn = require('cross-spawn'); -const yargsParser = require('yargs-parser'); -const { hasPkgProp, resolveBin, hasFile, fromRoot } = require('../utils'); +const path = require('path') +const spawn = require('cross-spawn') +const yargsParser = require('yargs-parser') +const {hasPkgProp, resolveBin, hasFile, fromRoot} = require('../utils') -let args = process.argv.slice(2); -const here = p => path.join(__dirname, p); -const hereRelative = p => here(p).replace(process.cwd(), '.'); -const parsedArgs = yargsParser(args); +let args = process.argv.slice(2) +const here = p => path.join(__dirname, p) +const hereRelative = p => here(p).replace(process.cwd(), '.') +const parsedArgs = yargsParser(args) const useBuiltinConfig = !args.includes('--config') && !hasFile('.eslintrc') && !hasFile('.eslintrc.js') && - !hasPkgProp('eslintConfig'); + !hasPkgProp('eslintConfig') const config = useBuiltinConfig ? ['--config', hereRelative('../config/eslintrc.js')] - : []; + : [] -const defaultExtensions = 'js,ts,tsx'; -const ext = args.includes('--ext') ? [] : ['--ext', defaultExtensions]; -const extensions = (parsedArgs.ext || defaultExtensions).split(','); +const defaultExtensions = 'js,ts,tsx' +const ext = args.includes('--ext') ? [] : ['--ext', defaultExtensions] +const extensions = (parsedArgs.ext || defaultExtensions).split(',') const useBuiltinIgnore = !args.includes('--ignore-path') && !hasFile('.eslintignore') && - !hasPkgProp('eslintIgnore'); + !hasPkgProp('eslintIgnore') const ignore = useBuiltinIgnore ? ['--ignore-path', hereRelative('../config/eslintignore')] - : []; + : [] const cache = args.includes('--no-cache') ? [] @@ -37,10 +37,10 @@ const cache = args.includes('--no-cache') '--cache', '--cache-location', fromRoot('node_modules/.cache/.eslintcache'), - ]; + ] -const filesGiven = parsedArgs._.length > 0; -const filesToApply = filesGiven ? [] : ['.']; +const filesGiven = parsedArgs._.length > 0 +const filesToApply = filesGiven ? [] : ['.'] if (filesGiven) { // we need to take all the flag-less arguments (the files that should be linted) @@ -48,13 +48,13 @@ if (filesGiven) { // may be passed through args = args.filter( a => !parsedArgs._.includes(a) || extensions.some(e => a.endsWith(e)), - ); + ) } const result = spawn.sync( resolveBin('eslint'), [...config, ...ext, ...ignore, ...cache, ...args, ...filesToApply], - { stdio: 'inherit' }, -); + {stdio: 'inherit'}, +) -process.exit(result.status); +process.exit(result.status) diff --git a/src/scripts/pre-commit.js b/src/scripts/pre-commit.js index 1ea2c0fe..97f084aa 100644 --- a/src/scripts/pre-commit.js +++ b/src/scripts/pre-commit.js @@ -1,40 +1,40 @@ -const path = require('path'); -const spawn = require('cross-spawn'); -const { hasPkgProp, hasFile, resolveBin, ifScript } = require('../utils'); +const path = require('path') +const spawn = require('cross-spawn') +const {hasPkgProp, hasFile, resolveBin, ifScript} = require('../utils') -const here = p => path.join(__dirname, p); -const hereRelative = p => here(p).replace(process.cwd(), '.'); +const here = p => path.join(__dirname, p) +const hereRelative = p => here(p).replace(process.cwd(), '.') -const args = process.argv.slice(2); +const args = process.argv.slice(2) const useBuiltInConfig = !args.includes('--config') && !hasFile('.lintstagedrc') && !hasFile('lint-staged.config.js') && - !hasPkgProp('lint-staged'); + !hasPkgProp('lint-staged') const config = useBuiltInConfig ? ['--config', hereRelative('../config/lintstagedrc.js')] - : []; + : [] function go() { - let result; + let result result = spawn.sync(resolveBin('lint-staged'), [...config, ...args], { stdio: 'inherit', - }); + }) - if (result.status !== 0) return result.status; + if (result.status !== 0) return result.status if (ifScript('validate', true)) { result = spawn.sync('npm', ['run', 'validate'], { stdio: 'inherit', - }); + }) - return result.status; + return result.status } - return 0; + return 0 } -process.exit(go()); +process.exit(go()) diff --git a/src/scripts/test.js b/src/scripts/test.js index d02dad7b..106a2d09 100644 --- a/src/scripts/test.js +++ b/src/scripts/test.js @@ -1,10 +1,10 @@ -process.env.BABEL_ENV = 'test'; -process.env.NODE_ENV = 'test'; +process.env.BABEL_ENV = 'test' +process.env.NODE_ENV = 'test' -const isCI = require('is-ci'); -const { hasPkgProp, parseEnv, hasFile } = require('../utils'); +const isCI = require('is-ci') +const {hasPkgProp, parseEnv, hasFile} = require('../utils') -const args = process.argv.slice(2); +const args = process.argv.slice(2) const watch = !isCI && @@ -13,14 +13,14 @@ const watch = !args.includes('--coverage') && !args.includes('--updateSnapshot') ? ['--watch'] - : []; + : [] const config = !args.includes('--config') && !hasFile('jest.config.js') && !hasPkgProp('jest') ? ['--config', JSON.stringify(require('../config/jest.config'))] - : []; + : [] // eslint-disable-next-line jest/no-jest-import -require('jest').run([...config, ...watch, ...args]); +require('jest').run([...config, ...watch, ...args]) diff --git a/src/scripts/typecheck.js b/src/scripts/typecheck.js index 283d5365..155fa9b0 100644 --- a/src/scripts/typecheck.js +++ b/src/scripts/typecheck.js @@ -1,35 +1,31 @@ -const spawn = require('cross-spawn'); -const yargsParser = require('yargs-parser'); -const { hasAnyDep, resolveBin, hasFile } = require('../utils'); +const spawn = require('cross-spawn') +const yargsParser = require('yargs-parser') +const {hasAnyDep, resolveBin, hasFile} = require('../utils') -let args = process.argv.slice(2); -const parsedArgs = yargsParser(args); +let args = process.argv.slice(2) +const parsedArgs = yargsParser(args) if (!hasAnyDep('typescript')) { throw new Error( 'Cannot use the "typecheck" script in a project that does not have typescript listed as a dependency (or devDependency).', - ); + ) } if (!parsedArgs.project && !parsedArgs.build && !hasFile('tsconfig.json')) { throw new Error( 'Cannot use the "typecheck" script without --project or --build in a project that does not have a tsconfig.json file.', - ); + ) } // if --project is provided, we can't pass --build // if --build is provided, we don't need to add it // if --no-build is passed, we'll just trust they know what they're doing if (!parsedArgs.project && !parsedArgs.build && !parsedArgs.noBuild) { - args = ['--build', ...args]; + args = ['--build', ...args] } -const result = spawn.sync( - resolveBin('typescript', { executable: 'tsc' }), - args, - { - stdio: 'inherit', - }, -); +const result = spawn.sync(resolveBin('typescript', {executable: 'tsc'}), args, { + stdio: 'inherit', +}) -process.exit(result.status); +process.exit(result.status) diff --git a/src/scripts/validate.js b/src/scripts/validate.js index 543ad0d3..a3b74c6c 100644 --- a/src/scripts/validate.js +++ b/src/scripts/validate.js @@ -1,19 +1,19 @@ -const spawn = require('cross-spawn'); +const spawn = require('cross-spawn') const { parseEnv, resolveBin, ifScript, getConcurrentlyArgs, -} = require('../utils'); +} = require('../utils') // pre-commit runs linting and tests on the relevant files // so those scripts don't need to be run if we're running // this in the context of a pre-commit hook. -const preCommit = parseEnv('SCRIPTS_PRE-COMMIT', false); +const preCommit = parseEnv('SCRIPTS_PRE-COMMIT', false) -const validateScripts = process.argv[2]; +const validateScripts = process.argv[2] -const useDefaultScripts = typeof validateScripts !== 'string'; +const useDefaultScripts = typeof validateScripts !== 'string' const scripts = useDefaultScripts ? { @@ -30,9 +30,9 @@ const scripts = useDefaultScripts [name]: `npm run ${name} --silent`, }), {}, - ); + ) -const scriptCount = Object.values(scripts).filter(Boolean).length; +const scriptCount = Object.values(scripts).filter(Boolean).length if (scriptCount > 0) { const result = spawn.sync( @@ -41,9 +41,9 @@ if (scriptCount > 0) { { stdio: 'inherit', }, - ); + ) - process.exit(result.status); + process.exit(result.status) } else { - process.exit(0); + process.exit(0) } diff --git a/src/utils.js b/src/utils.js index e8146dd5..9fc7f921 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,46 +1,43 @@ -const fs = require('fs'); -const path = require('path'); -const spawn = require('cross-spawn'); -const rimraf = require('rimraf'); -const mkdirp = require('mkdirp'); -const arrify = require('arrify'); -const has = require('lodash.has'); -const glob = require('glob'); -const readPkgUp = require('read-pkg-up'); -const which = require('which'); -const { cosmiconfigSync } = require('cosmiconfig'); - -const { packageJson: pkg, path: pkgPath } = readPkgUp.sync({ +const fs = require('fs') +const path = require('path') +const spawn = require('cross-spawn') +const rimraf = require('rimraf') +const mkdirp = require('mkdirp') +const arrify = require('arrify') +const has = require('lodash.has') +const glob = require('glob') +const readPkgUp = require('read-pkg-up') +const which = require('which') +const {cosmiconfigSync} = require('cosmiconfig') + +const {packageJson: pkg, path: pkgPath} = readPkgUp.sync({ cwd: fs.realpathSync(process.cwd()), -}); -const appDirectory = path.dirname(pkgPath); - -function resolveBin( - modName, - { executable = modName, cwd = process.cwd() } = {}, -) { - let pathFromWhich; +}) +const appDirectory = path.dirname(pkgPath) + +function resolveBin(modName, {executable = modName, cwd = process.cwd()} = {}) { + let pathFromWhich try { - pathFromWhich = fs.realpathSync(which.sync(executable)); - if (pathFromWhich && pathFromWhich.includes('.CMD')) return pathFromWhich; + pathFromWhich = fs.realpathSync(which.sync(executable)) + if (pathFromWhich && pathFromWhich.includes('.CMD')) return pathFromWhich } catch (_error) { // ignore _error } try { - const modPkgPath = require.resolve(`${modName}/package.json`); - const modPkgDir = path.dirname(modPkgPath); + const modPkgPath = require.resolve(`${modName}/package.json`) + const modPkgDir = path.dirname(modPkgPath) const { bin } = require(modPkgPath); // eslint-disable-line - const binPath = typeof bin === 'string' ? bin : bin[executable]; - const fullPathToBin = path.join(modPkgDir, binPath); + const binPath = typeof bin === 'string' ? bin : bin[executable] + const fullPathToBin = path.join(modPkgDir, binPath) if (fullPathToBin === pathFromWhich) { - return executable; + return executable } - return fullPathToBin.replace(cwd, '.'); + return fullPathToBin.replace(cwd, '.') } catch (error) { if (pathFromWhich) { - return executable; + return executable } - throw error; + throw error } } @@ -50,59 +47,59 @@ function resolveCodScripts() { // this happens on install of husky within cod-scripts locally appDirectory.includes(path.join(__dirname, '..')) ) { - return require.resolve('./').replace(process.cwd(), '.'); + return require.resolve('./').replace(process.cwd(), '.') } - return resolveBin('cod-scripts'); + return resolveBin('cod-scripts') } -const fromRoot = (...p) => path.join(appDirectory, ...p); -const hasFile = (...p) => fs.existsSync(fromRoot(...p)); +const fromRoot = (...p) => path.join(appDirectory, ...p) +const hasFile = (...p) => fs.existsSync(fromRoot(...p)) const ifFile = (files, t, f) => - arrify(files).some(file => hasFile(file)) ? t : f; + arrify(files).some(file => hasFile(file)) ? t : f -const hasPkgProp = props => arrify(props).some(prop => has(pkg, prop)); +const hasPkgProp = props => arrify(props).some(prop => has(pkg, prop)) const hasPkgSubProp = pkgProp => props => - hasPkgProp(arrify(props).map(p => `${pkgProp}.${p}`)); + hasPkgProp(arrify(props).map(p => `${pkgProp}.${p}`)) const ifPkgSubProp = pkgProp => (props, t, f) => - hasPkgSubProp(pkgProp)(props) ? t : f; + hasPkgSubProp(pkgProp)(props) ? t : f -const hasScript = hasPkgSubProp('scripts'); -const hasPeerDep = hasPkgSubProp('peerDependencies'); -const hasDep = hasPkgSubProp('dependencies'); -const hasDevDep = hasPkgSubProp('devDependencies'); -const hasAnyDep = args => [hasDep, hasDevDep, hasPeerDep].some(fn => fn(args)); +const hasScript = hasPkgSubProp('scripts') +const hasPeerDep = hasPkgSubProp('peerDependencies') +const hasDep = hasPkgSubProp('dependencies') +const hasDevDep = hasPkgSubProp('devDependencies') +const hasAnyDep = args => [hasDep, hasDevDep, hasPeerDep].some(fn => fn(args)) -const ifPeerDep = ifPkgSubProp('peerDependencies'); -const ifDep = ifPkgSubProp('dependencies'); -const ifDevDep = ifPkgSubProp('devDependencies'); -const ifAnyDep = (deps, t, f) => (hasAnyDep(arrify(deps)) ? t : f); -const ifScript = ifPkgSubProp('scripts'); +const ifPeerDep = ifPkgSubProp('peerDependencies') +const ifDep = ifPkgSubProp('dependencies') +const ifDevDep = ifPkgSubProp('devDependencies') +const ifAnyDep = (deps, t, f) => (hasAnyDep(arrify(deps)) ? t : f) +const ifScript = ifPkgSubProp('scripts') function envIsSet(name) { return ( process.env.hasOwnProperty(name) && process.env[name] && process.env[name] !== 'undefined' - ); + ) } -const hasTypescript = hasAnyDep('typescript') && hasFile('tsconfig.json'); -const ifTypescript = (t, f) => (hasTypescript ? t : f); +const hasTypescript = hasAnyDep('typescript') && hasFile('tsconfig.json') +const ifTypescript = (t, f) => (hasTypescript ? t : f) function parseEnv(name, def) { if (envIsSet(name)) { try { - return JSON.parse(process.env[name]); + return JSON.parse(process.env[name]) } catch (err) { - return process.env[name]; + return process.env[name] } } - return def; + return def } -function getConcurrentlyArgs(scripts, { killOthers = true } = {}) { +function getConcurrentlyArgs(scripts, {killOthers = true} = {}) { const colors = [ 'bgBlue', 'bgGreen', @@ -112,22 +109,22 @@ function getConcurrentlyArgs(scripts, { killOthers = true } = {}) { 'bgRed', 'bgBlack', 'bgYellow', - ]; + ] // eslint-disable-next-line no-param-reassign scripts = Object.entries(scripts).reduce((all, [name, script]) => { if (script) { // eslint-disable-next-line no-param-reassign - all[name] = script; + all[name] = script } - return all; - }, {}); + return all + }, {}) const prefixColors = Object.keys(scripts) .reduce( (pColors, _s, i) => pColors.concat([`${colors[i % colors.length]}.bold.white`]), [], ) - .join(','); + .join(',') // prettier-ignore return [ @@ -141,17 +138,17 @@ function getConcurrentlyArgs(scripts, { killOthers = true } = {}) { } function uniq(arr) { - return Array.from(new Set(arr)); + return Array.from(new Set(arr)) } -function writeExtraEntry(name, { cjs, esm }, clean = true) { +function writeExtraEntry(name, {cjs, esm}, clean = true) { if (clean) { - rimraf.sync(fromRoot(name)); + rimraf.sync(fromRoot(name)) } - mkdirp.sync(fromRoot(name)); + mkdirp.sync(fromRoot(name)) - const pkgJson = fromRoot(`${name}/package.json`); - const entryDir = fromRoot(name); + const pkgJson = fromRoot(`${name}/package.json`) + const entryDir = fromRoot(name) fs.writeFileSync( pkgJson, @@ -164,19 +161,19 @@ function writeExtraEntry(name, { cjs, esm }, clean = true) { null, 2, ), - ); + ) } function hasLocalConfig(moduleName, searchOptions = {}) { - const explorerSync = cosmiconfigSync(moduleName, searchOptions); - const result = explorerSync.search(pkgPath); + const explorerSync = cosmiconfigSync(moduleName, searchOptions) + const result = explorerSync.search(pkgPath) - return result !== null; + return result !== null } function generateTypeDefs(outputDir) { return spawn.sync( - resolveBin('typescript', { executable: 'tsc' }), + resolveBin('typescript', {executable: 'tsc'}), // prettier-ignore [ '--declaration', @@ -184,24 +181,24 @@ function generateTypeDefs(outputDir) { '--noEmit', 'false', '--outDir', outputDir, ], - { stdio: 'inherit' }, - ); + {stdio: 'inherit'}, + ) } function getRollupInputs() { const buildInputGlob = process.env.BUILD_INPUT || - (hasTypescript ? 'src/index.{js,ts,tsx}' : 'src/index.js'); - const input = glob.sync(fromRoot(buildInputGlob)); + (hasTypescript ? 'src/index.{js,ts,tsx}' : 'src/index.js') + const input = glob.sync(fromRoot(buildInputGlob)) if (!input.length) { - throw new Error(`Unable to find files with this glob: ${buildInputGlob}`); + throw new Error(`Unable to find files with this glob: ${buildInputGlob}`) } - return input; + return input } function getRollupOutput(format = process.env.BUILD_FORMAT) { - const minify = parseEnv('BUILD_MINIFY', false); - const filenameSuffix = process.env.BUILD_FILENAME_SUFFIX || ''; + const minify = parseEnv('BUILD_MINIFY', false) + const filenameSuffix = process.env.BUILD_FILENAME_SUFFIX || '' const filename = [ pkg.name, filenameSuffix, @@ -210,13 +207,13 @@ function getRollupOutput(format = process.env.BUILD_FORMAT) { '.js', ] .filter(Boolean) - .join(''); + .join('') - const isPreact = parseEnv('BUILD_PREACT', false); + const isPreact = parseEnv('BUILD_PREACT', false) const filenamePrefix = - process.env.BUILD_FILENAME_PREFIX || (isPreact ? 'preact/' : ''); - const dirpath = path.join(...[filenamePrefix, 'dist'].filter(Boolean)); - return { dirpath, filename }; + process.env.BUILD_FILENAME_PREFIX || (isPreact ? 'preact/' : '') + const dirpath = path.join(...[filenamePrefix, 'dist'].filter(Boolean)) + return {dirpath, filename} } module.exports = { @@ -246,4 +243,4 @@ module.exports = { generateTypeDefs, getRollupInputs, getRollupOutput, -}; +} From a1244d749f12a440f5506e9e7b4dba28dc79de64 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 25 Feb 2021 23:43:45 -0500 Subject: [PATCH 36/48] feat: bump deps --- package.json | 54 ++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/package.json b/package.json index 9a725689..cbe8d574 100644 --- a/package.json +++ b/package.json @@ -35,23 +35,23 @@ "author": "Chris O'Donnell (http://codfish.io/)", "license": "MIT", "dependencies": { - "@babel/cli": "^7.12.8", - "@babel/core": "^7.12.9", - "@babel/plugin-proposal-class-properties": "^7.12.1", - "@babel/plugin-transform-modules-commonjs": "^7.12.1", - "@babel/plugin-transform-runtime": "^7.12.1", - "@babel/preset-env": "^7.12.7", - "@babel/preset-react": "^7.12.7", - "@babel/preset-typescript": "^7.12.7", - "@babel/runtime": "^7.12.5", - "@commitlint/cli": "^11.0.0", - "@commitlint/config-conventional": "^11.0.0", - "@rollup/plugin-babel": "^5.2.2", - "@rollup/plugin-commonjs": "^17.0.0", + "@babel/cli": "^7.13.0", + "@babel/core": "^7.13.1", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-transform-modules-commonjs": "^7.13.0", + "@babel/plugin-transform-runtime": "^7.13.7", + "@babel/preset-env": "^7.13.5", + "@babel/preset-react": "^7.12.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/runtime": "^7.13.7", + "@commitlint/cli": "^12.0.0", + "@commitlint/config-conventional": "^12.0.0", + "@rollup/plugin-babel": "^5.3.0", + "@rollup/plugin-commonjs": "^17.1.0", "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^11.0.0", - "@rollup/plugin-replace": "^2.3.4", - "@types/jest": "^26.0.17", + "@rollup/plugin-node-resolve": "^11.2.0", + "@rollup/plugin-replace": "^2.4.1", + "@types/jest": "^26.0.20", "arrify": "^2.0.1", "babel-jest": "^26.6.3", "babel-plugin-macros": "^3.0.0", @@ -59,24 +59,24 @@ "babel-plugin-module-resolver": "^4.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.3", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", - "browserslist": "^4.14.7", + "browserslist": "^4.16.3", "builtin-modules": "^3.2.0", "chalk": "^4.1.0", - "concurrently": "^5.3.0", + "concurrently": "^6.0.0", "cosmiconfig": "^7.0.0", "cross-env": "^7.0.3", "cross-spawn": "^7.0.3", "doctoc": "^2.0.0", - "eslint": "^7.15.0", - "eslint-config-codfish": "^8.2.0", - "eslint-config-prettier": "^7.0.0", + "eslint": "^7.20.0", + "eslint-config-codfish": "^8.3.0", + "eslint-config-prettier": "^8.1.0", "glob": "^7.1.5", - "husky": "^4.3.5", - "is-ci": "^2.0.0", + "husky": "^5.1.1", + "is-ci": "^3.0.0", "jest": "^26.6.1", "jest-serializer-path": "^0.1.15", "jest-watch-typeahead": "^0.6.1", - "lint-staged": "^10.5.3", + "lint-staged": "^10.5.4", "lodash.camelcase": "^4.3.0", "lodash.has": "^4.5.2", "lodash.omit": "^4.5.0", @@ -84,16 +84,16 @@ "prettier": "2.2.1", "react-app-polyfill": "^2.0.0", "read-pkg-up": "^7.0.1", - "resolve": "^1.19.0", + "resolve": "^1.20.0", "rimraf": "^3.0.2", - "rollup": "^2.34.2", + "rollup": "^2.39.1", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "rollup-plugin-size-snapshot": "^0.12.0", "rollup-plugin-terser": "^7.0.2", "semver": "^7.3.4", "which": "^2.0.2", - "yargs-parser": "^20.2.4" + "yargs-parser": "^20.2.6" }, "eslintConfig": { "extends": [ From 5b547d9626de103d1293893fb4767b4a6b0edfb4 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sun, 28 Feb 2021 14:39:53 -0500 Subject: [PATCH 37/48] ci: run validation scripts for node 15.x --- .github/workflows/validate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 4b433eda..e1ffd91b 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: - node: [10.x, 11.x, 12.x, 14.x] + node: [10.x, 11.x, 12.x, 14.x, 15.x] steps: - uses: actions/checkout@v1 From d90dfd4f318507027e264b8bd46d763ec3860f6f Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sun, 28 Feb 2021 14:40:33 -0500 Subject: [PATCH 38/48] fix: bump eslint-config-codfish, remove direct dep of eslint-config-prettier --- package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package.json b/package.json index cbe8d574..f7878c3c 100644 --- a/package.json +++ b/package.json @@ -68,8 +68,7 @@ "cross-spawn": "^7.0.3", "doctoc": "^2.0.0", "eslint": "^7.20.0", - "eslint-config-codfish": "^8.3.0", - "eslint-config-prettier": "^8.1.0", + "eslint-config-codfish": "^8.3.1", "glob": "^7.1.5", "husky": "^5.1.1", "is-ci": "^3.0.0", From e16daedb81bde225303d3a4e7f6ccb79c18b8cde Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sun, 28 Feb 2021 19:13:38 -0500 Subject: [PATCH 39/48] feat: bump eslint-config-codfish@9 BREAKING CHANGE: All `babel/` eslint rules are renamed to '@babel/'. i.e. `babel/semi` -> `@babel/semi` --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index f7878c3c..bf3e868c 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "cross-spawn": "^7.0.3", "doctoc": "^2.0.0", "eslint": "^7.20.0", - "eslint-config-codfish": "^8.3.1", + "eslint-config-codfish": "^9.0.0", "glob": "^7.1.5", "husky": "^5.1.1", "is-ci": "^3.0.0", @@ -101,9 +101,9 @@ "rules": { "no-console": "off", "semi": "off", - "babel/semi": "off", + "@babel/semi": "off", "object-curly-spacing": "off", - "babel/object-curly-spacing": "off", + "@babel/object-curly-spacing": "off", "no-process-exit": "off", "global-require": "off", "no-prototype-builtins": "off", From 0003867997dce85dc65c8d4a2ae6f5ad351e045e Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Thu, 18 Mar 2021 21:47:32 -0400 Subject: [PATCH 40/48] ci: add pr versions --- .github/workflows/validate.yml | 48 ++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index e1ffd91b..245a5eda 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -13,26 +13,58 @@ jobs: steps: - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v2 with: node-version: ${{ matrix.node }} - name: install dependencies run: npm install --no-save - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - run: npm run build - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - name: lint js run: npm run lint - env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} - name: run tests run: npm run test env: - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} CI: true + + pr-version: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + + - uses: actions/setup-node@v2 + with: + node-version: '14' + registry-url: 'https://registry.npmjs.org' + + - name: install dependencies + run: npm install --no-save + + - run: npm run build + + - name: publish to npm + id: pr-publish + run: | + version="0.0.0-PR-${PR}--$(echo ${SHA} | cut -c -7)" + npm version $version --no-git-tag-version + npm publish --access public --tag pr + echo "::set-output name=pr_version::$version" + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + PR: ${{ github.event.number }} + SHA: ${{ github.event.pull_request.head.sha }} + + - uses: actions/github-script@v3 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + github.issues.createComment({ + issue_number: context.issue.number, + owner: context.repo.owner, + repo: context.repo.repo, + body: 'πŸš€ PR version published: `${{ steps.pr-publish.outputs.pr_version }}`' + }) From ca157f0da8c23aef7aa41ad2c2034c77524eba92 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sat, 24 Apr 2021 12:29:14 -0400 Subject: [PATCH 41/48] fix: reference builtin babel config for @babel/eslint-parser --- src/config/babelrc.js | 87 +++++++++++++++++++++++------------------- src/config/eslintrc.js | 18 ++++++--- 2 files changed, 60 insertions(+), 45 deletions(-) diff --git a/src/config/babelrc.js b/src/config/babelrc.js index f382e372..ba3f5f65 100644 --- a/src/config/babelrc.js +++ b/src/config/babelrc.js @@ -1,6 +1,5 @@ const browserslist = require('browserslist') const semver = require('semver') - const { ifDep, ifAnyDep, @@ -66,46 +65,54 @@ const envTargets = isTest : {node: getNodeVersion(pkg)} const envOptions = {modules: false, loose: true, targets: envTargets} -module.exports = () => ({ - presets: [ - [require.resolve('@babel/preset-env'), envOptions], - ifAnyDep( - ['react', 'preact'], +module.exports = api => { + // Cache the returned value forever and don't call this function again. + api.cache(true) + + return { + presets: [ + [require.resolve('@babel/preset-env'), envOptions], + ifAnyDep( + ['react', 'preact'], + [ + require.resolve('@babel/preset-react'), + {pragma: isPreact ? ifDep('react', 'React.h', 'h') : undefined}, + ], + ), + ifTypescript([require.resolve('@babel/preset-typescript')]), + ].filter(Boolean), + plugins: [ [ - require.resolve('@babel/preset-react'), - {pragma: isPreact ? ifDep('react', 'React.h', 'h') : undefined}, + require.resolve('@babel/plugin-transform-runtime'), + {useESModules: treeshake && !isCJS}, ], - ), - ifTypescript([require.resolve('@babel/preset-typescript')]), - ].filter(Boolean), - plugins: [ - [ - require.resolve('@babel/plugin-transform-runtime'), - {useESModules: treeshake && !isCJS}, - ], - require.resolve('babel-plugin-macros'), - alias - ? [ - require.resolve('babel-plugin-module-resolver'), - {root: ['./src'], alias}, - ] - : null, - ifAnyDep( - ['react', 'preact'], + require.resolve('babel-plugin-macros'), + alias + ? [ + require.resolve('babel-plugin-module-resolver'), + {root: ['./src'], alias}, + ] + : null, + ifAnyDep( + ['react', 'preact'], + [ + require.resolve('babel-plugin-transform-react-remove-prop-types'), + isPreact ? {removeImport: true} : {mode: 'unsafe-wrap'}, + ], + ), + isUMD + ? require.resolve('babel-plugin-transform-inline-environment-variables') + : null, [ - require.resolve('babel-plugin-transform-react-remove-prop-types'), - isPreact ? {removeImport: true} : {mode: 'unsafe-wrap'}, + require.resolve('@babel/plugin-proposal-class-properties'), + {loose: true}, ], - ), - isUMD - ? require.resolve('babel-plugin-transform-inline-environment-variables') - : null, - [require.resolve('@babel/plugin-proposal-class-properties'), {loose: true}], - isMinify - ? require.resolve('babel-plugin-minify-dead-code-elimination') - : null, - treeshake - ? null - : require.resolve('@babel/plugin-transform-modules-commonjs'), - ].filter(Boolean), -}) + isMinify + ? require.resolve('babel-plugin-minify-dead-code-elimination') + : null, + treeshake + ? null + : require.resolve('@babel/plugin-transform-modules-commonjs'), + ].filter(Boolean), + } +} diff --git a/src/config/eslintrc.js b/src/config/eslintrc.js index df0a23b6..8cd8326a 100644 --- a/src/config/eslintrc.js +++ b/src/config/eslintrc.js @@ -1,17 +1,25 @@ +const path = require('path') const prettierConfig = require('./prettierrc') const {hasLocalConfig} = require('../utils') -const args = process.argv.slice(2) +const here = p => path.join(__dirname, p) +const hereRelative = p => here(p).replace(process.cwd(), '.') -const useBuiltinConfig = - !args.includes('--config') && !hasLocalConfig('prettier') -const ruleValue = useBuiltinConfig ? ['error', prettierConfig] : 'error' +const useBuiltinPrettierConfig = !hasLocalConfig('prettier') +const useBuiltinBabelConfig = !hasLocalConfig('babel') module.exports = { extends: [require.resolve('eslint-config-codfish')].filter(Boolean), + parserOptions: { + babelOptions: useBuiltinBabelConfig + ? {configFile: hereRelative('./babelrc.js')} + : {}, + }, rules: { // Explicitly set prettier rules to use our built in config if no // local prettier config is found. - 'prettier/prettier': ruleValue, + 'prettier/prettier': useBuiltinPrettierConfig + ? ['error', prettierConfig] + : 'error', }, } From fc1416996975439d47a257e097e79d7e2e379f6e Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sat, 24 Apr 2021 12:10:26 -0400 Subject: [PATCH 42/48] feat: bump deps BREAKING CHANGE: eslint-plugin-testing-library will now report aggressively when linting (change from eslint-config-codfish v10) --- package.json | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index bf3e868c..b3af9450 100644 --- a/package.json +++ b/package.json @@ -35,23 +35,23 @@ "author": "Chris O'Donnell (http://codfish.io/)", "license": "MIT", "dependencies": { - "@babel/cli": "^7.13.0", - "@babel/core": "^7.13.1", + "@babel/cli": "^7.13.16", + "@babel/core": "^7.13.16", "@babel/plugin-proposal-class-properties": "^7.13.0", "@babel/plugin-transform-modules-commonjs": "^7.13.0", - "@babel/plugin-transform-runtime": "^7.13.7", - "@babel/preset-env": "^7.13.5", - "@babel/preset-react": "^7.12.13", + "@babel/plugin-transform-runtime": "^7.13.15", + "@babel/preset-env": "^7.13.15", + "@babel/preset-react": "^7.13.13", "@babel/preset-typescript": "^7.13.0", - "@babel/runtime": "^7.13.7", - "@commitlint/cli": "^12.0.0", - "@commitlint/config-conventional": "^12.0.0", + "@babel/runtime": "^7.13.17", + "@commitlint/cli": "^12.1.1", + "@commitlint/config-conventional": "^12.1.1", "@rollup/plugin-babel": "^5.3.0", - "@rollup/plugin-commonjs": "^17.1.0", + "@rollup/plugin-commonjs": "^18.0.0", "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^11.2.0", - "@rollup/plugin-replace": "^2.4.1", - "@types/jest": "^26.0.20", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.2", + "@types/jest": "^26.0.22", "arrify": "^2.0.1", "babel-jest": "^26.6.3", "babel-plugin-macros": "^3.0.0", @@ -59,22 +59,22 @@ "babel-plugin-module-resolver": "^4.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.3", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", - "browserslist": "^4.16.3", + "browserslist": "^4.16.5", "builtin-modules": "^3.2.0", - "chalk": "^4.1.0", - "concurrently": "^6.0.0", + "chalk": "^4.1.1", + "concurrently": "^6.0.2", "cosmiconfig": "^7.0.0", "cross-env": "^7.0.3", "cross-spawn": "^7.0.3", "doctoc": "^2.0.0", - "eslint": "^7.20.0", - "eslint-config-codfish": "^9.0.0", + "eslint": "^7.25.0", + "eslint-config-codfish": "^10.0.0", "glob": "^7.1.5", - "husky": "^5.1.1", + "husky": "^6.0.0", "is-ci": "^3.0.0", "jest": "^26.6.1", "jest-serializer-path": "^0.1.15", - "jest-watch-typeahead": "^0.6.1", + "jest-watch-typeahead": "^0.6.3", "lint-staged": "^10.5.4", "lodash.camelcase": "^4.3.0", "lodash.has": "^4.5.2", @@ -85,14 +85,14 @@ "read-pkg-up": "^7.0.1", "resolve": "^1.20.0", "rimraf": "^3.0.2", - "rollup": "^2.39.1", + "rollup": "^2.45.2", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "rollup-plugin-size-snapshot": "^0.12.0", "rollup-plugin-terser": "^7.0.2", - "semver": "^7.3.4", + "semver": "^7.3.5", "which": "^2.0.2", - "yargs-parser": "^20.2.6" + "yargs-parser": "^20.2.7" }, "eslintConfig": { "extends": [ From 904d76ee53171ad8deab293366fad54ef94f19c7 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sat, 24 Apr 2021 12:12:23 -0400 Subject: [PATCH 43/48] ci: update branch patterns for release workflow --- .github/workflows/release.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 073d4c8c..980dfedc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,12 @@ on: push: branches: - master + - main + - alpha + - beta + - next + - 'next-major' + - '+([0-9])?(.{+([0-9]),x}).x' jobs: release: From f205e8069dae8352e84fb08f18c3dffb4e49e21e Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sat, 24 Apr 2021 12:13:08 -0400 Subject: [PATCH 44/48] ci: use semantic-release to speed up releases --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 980dfedc..1203f0df 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,7 +33,7 @@ jobs: CI: true - name: semantic release - uses: codfish/semantic-release-action@v1 + uses: docker://ghcr.io/codfish/semantic-release-action:v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_TOKEN }} From c4298f4522a70b709b1570a80ee2962e3958d21f Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sat, 24 Apr 2021 12:28:30 -0400 Subject: [PATCH 45/48] feat: update node engine requirement to >=12.0.0 BREAKING CHANGE: Require node v12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b3af9450..8f5cb4f0 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.0-semantically-released", "description": "CLI for common scripts for my projects", "engines": { - "node": ">=10.18", + "node": ">=12", "npm": ">=6", "yarn": ">=1" }, From 92a123be8a0677d83cb706640541aa9146162134 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sat, 24 Apr 2021 12:10:26 -0400 Subject: [PATCH 46/48] feat: bump deps BREAKING CHANGE: eslint-plugin-testing-library will now report aggressively when linting (change from eslint-config-codfish v10) --- package.json | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/package.json b/package.json index efc3f328..001e801c 100644 --- a/package.json +++ b/package.json @@ -35,23 +35,23 @@ "author": "Chris O'Donnell (http://codfish.io/)", "license": "MIT", "dependencies": { - "@babel/cli": "^7.13.0", - "@babel/core": "^7.13.1", + "@babel/cli": "^7.13.16", + "@babel/core": "^7.13.16", "@babel/plugin-proposal-class-properties": "^7.13.0", "@babel/plugin-transform-modules-commonjs": "^7.13.0", - "@babel/plugin-transform-runtime": "^7.13.7", - "@babel/preset-env": "^7.13.5", - "@babel/preset-react": "^7.12.13", + "@babel/plugin-transform-runtime": "^7.13.15", + "@babel/preset-env": "^7.13.15", + "@babel/preset-react": "^7.13.13", "@babel/preset-typescript": "^7.13.0", - "@babel/runtime": "^7.13.7", - "@commitlint/cli": "^12.0.0", - "@commitlint/config-conventional": "^12.0.0", + "@babel/runtime": "^7.13.17", + "@commitlint/cli": "^12.1.1", + "@commitlint/config-conventional": "^12.1.1", "@rollup/plugin-babel": "^5.3.0", - "@rollup/plugin-commonjs": "^17.1.0", + "@rollup/plugin-commonjs": "^18.0.0", "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^11.2.0", - "@rollup/plugin-replace": "^2.4.1", - "@types/jest": "^26.0.20", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-replace": "^2.4.2", + "@types/jest": "^26.0.22", "arrify": "^2.0.1", "babel-jest": "^26.6.3", "babel-plugin-macros": "^3.0.0", @@ -59,23 +59,23 @@ "babel-plugin-module-resolver": "^4.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.3", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", - "browserslist": "^4.16.3", + "browserslist": "^4.16.5", "builtin-modules": "^3.2.0", - "chalk": "^4.1.0", - "concurrently": "^6.0.0", + "chalk": "^4.1.1", + "concurrently": "^6.0.2", "cosmiconfig": "^7.0.0", "cpy": "^8.1.2", "cross-env": "^7.0.3", "cross-spawn": "^7.0.3", "doctoc": "^2.0.0", - "eslint": "^7.20.0", - "eslint-config-codfish": "^9.0.0", + "eslint": "^7.25.0", + "eslint-config-codfish": "^10.0.0", "glob": "^7.1.5", - "husky": "^5.1.1", + "husky": "^6.0.0", "is-ci": "^3.0.0", "jest": "^26.6.1", "jest-serializer-path": "^0.1.15", - "jest-watch-typeahead": "^0.6.1", + "jest-watch-typeahead": "^0.6.3", "lint-staged": "^10.5.4", "lodash.camelcase": "^4.3.0", "lodash.has": "^4.5.2", @@ -86,14 +86,14 @@ "read-pkg-up": "^7.0.1", "resolve": "^1.20.0", "rimraf": "^3.0.2", - "rollup": "^2.39.1", + "rollup": "^2.45.2", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "rollup-plugin-size-snapshot": "^0.12.0", "rollup-plugin-terser": "^7.0.2", - "semver": "^7.3.4", + "semver": "^7.3.5", "which": "^2.0.2", - "yargs-parser": "^20.2.6" + "yargs-parser": "^20.2.7" }, "eslintConfig": { "extends": [ From 064acfa08f7ebd5cc267bc8d61157d8e0bb3c2f6 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sat, 24 Apr 2021 12:28:30 -0400 Subject: [PATCH 47/48] feat: update node engine requirement to >=12.0.0 BREAKING CHANGE: Require node v12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 001e801c..708ec022 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.0-semantically-released", "description": "CLI for common scripts for my projects", "engines": { - "node": ">=10.18", + "node": ">=12", "npm": ">=6", "yarn": ">=1" }, From f24a1e85df62bf2136e75f9bf666e68444f3bda0 Mon Sep 17 00:00:00 2001 From: Chris O'Donnell Date: Sun, 16 May 2021 21:13:20 -0400 Subject: [PATCH 48/48] feat: bump deps and backmerge upstream --- .github/workflows/validate.yml | 5 +++-- package.json | 36 +++++++++++++++++----------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 245a5eda..5eb7f444 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -8,7 +8,8 @@ jobs: strategy: matrix: - node: [10.x, 11.x, 12.x, 14.x, 15.x] + # Test with Node.js v12 (LTS), v14 (LTS), and v16 (latest) + node: [12.x, 14.x, 15.x, 16.x] steps: - uses: actions/checkout@v1 @@ -38,7 +39,7 @@ jobs: - uses: actions/setup-node@v2 with: - node-version: '14' + node-version: '14.x' registry-url: 'https://registry.npmjs.org' - name: install dependencies diff --git a/package.json b/package.json index 8ac15b90..9d5692f8 100644 --- a/package.json +++ b/package.json @@ -36,58 +36,58 @@ "license": "MIT", "dependencies": { "@babel/cli": "^7.13.16", - "@babel/core": "^7.13.16", + "@babel/core": "^7.14.2", "@babel/plugin-proposal-class-properties": "^7.13.0", - "@babel/plugin-transform-modules-commonjs": "^7.13.0", - "@babel/plugin-transform-runtime": "^7.13.15", - "@babel/preset-env": "^7.13.15", + "@babel/plugin-transform-modules-commonjs": "^7.14.0", + "@babel/plugin-transform-runtime": "^7.14.2", + "@babel/preset-env": "^7.14.2", "@babel/preset-react": "^7.13.13", "@babel/preset-typescript": "^7.13.0", - "@babel/runtime": "^7.13.17", - "@commitlint/cli": "^12.1.1", - "@commitlint/config-conventional": "^12.1.1", + "@babel/runtime": "^7.14.0", + "@commitlint/cli": "^12.1.4", + "@commitlint/config-conventional": "^12.1.4", "@rollup/plugin-babel": "^5.3.0", - "@rollup/plugin-commonjs": "^18.0.0", + "@rollup/plugin-commonjs": "^19.0.0", "@rollup/plugin-json": "^4.1.0", - "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-node-resolve": "^13.0.0", "@rollup/plugin-replace": "^2.4.2", - "@types/jest": "^26.0.22", + "@types/jest": "^26.0.23", "arrify": "^2.0.1", "babel-jest": "^26.6.3", - "babel-plugin-macros": "^3.0.0", + "babel-plugin-macros": "^3.1.0", "babel-plugin-minify-dead-code-elimination": "^0.5.1", "babel-plugin-module-resolver": "^4.0.0", "babel-plugin-transform-inline-environment-variables": "^0.4.3", "babel-plugin-transform-react-remove-prop-types": "^0.4.24", - "browserslist": "^4.16.5", + "browserslist": "^4.16.6", "builtin-modules": "^3.2.0", "chalk": "^4.1.1", - "concurrently": "^6.0.2", + "concurrently": "^6.1.0", "cosmiconfig": "^7.0.0", "cpy": "^8.1.2", "cross-env": "^7.0.3", "cross-spawn": "^7.0.3", "doctoc": "^2.0.0", - "eslint": "^7.25.0", + "eslint": "^7.26.0", "eslint-config-codfish": "^10.0.0", - "glob": "^7.1.5", + "glob": "^7.1.7", "husky": "^6.0.0", "is-ci": "^3.0.0", "jest": "^26.6.1", "jest-serializer-path": "^0.1.15", "jest-snapshot-serializer-raw": "^1.2.0", "jest-watch-typeahead": "^0.6.2", - "lint-staged": "^10.5.4", + "lint-staged": "^11.0.0", "lodash.camelcase": "^4.3.0", "lodash.has": "^4.5.2", "lodash.omit": "^4.5.0", "mkdirp": "^1.0.4", - "prettier": "2.2.1", + "prettier": "^2.3.0", "react-app-polyfill": "^2.0.0", "read-pkg-up": "^7.0.1", "resolve": "^1.20.0", "rimraf": "^3.0.2", - "rollup": "^2.45.2", + "rollup": "^2.48.0", "rollup-plugin-node-builtins": "^2.1.2", "rollup-plugin-node-globals": "^1.4.0", "rollup-plugin-size-snapshot": "^0.12.0",