From c4b353709e336818c4de974dced79da79159d285 Mon Sep 17 00:00:00 2001 From: Chris Smothers Date: Tue, 10 Nov 2020 19:32:27 -0500 Subject: [PATCH 1/6] chore(cd): setup cd to release to npm (#10) --- .releaserc.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.releaserc.json b/.releaserc.json index abf27451..b20a4898 100644 --- a/.releaserc.json +++ b/.releaserc.json @@ -4,8 +4,6 @@ "@semantic-release/release-notes-generator", "@semantic-release/changelog", "@semantic-release/npm", - ["@semantic-release/github", { - "assets": ["dist/**"] - }] + "@semantic-release/github" ] } \ No newline at end of file From d047daa5b7322a8c63df08be11e531fb466c5697 Mon Sep 17 00:00:00 2001 From: rubinovitz Date: Tue, 10 Nov 2020 18:09:04 -0800 Subject: [PATCH 2/6] docs(readme): copy edits (#11) * Update README.md * Update README.md with more purpose copy edits --- README.md | 53 ++++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 5b0b14e9..15fa5abd 100644 --- a/README.md +++ b/README.md @@ -18,31 +18,29 @@ npm install homebase-react --save yarn add homebase-react ``` -## Docs -https://www.notion.so/Homebase-Alpha-Docs-0f0e22f3adcd4e9d87a13440ab0c7a0b - -## Examples -### Live Demos -You can see our hosted live demos [here](https://homebaseio.github.io/homebase-react) - -### Code Examples -You can clone and run our React code examples [here](https://github.com/homebaseio/homebase-react-examples). - ## Purpose -We want data to be a first class citizen on the client. We love relational databases in our servers and we want that same experience in our React apps. In other words, we want our applications to be [local-first](https://news.ycombinator.com/item?id=21581444). That means we need to make it easier to work with complex data on clients. +Data should be a first class citizen on the client. We deserve the ergonomics and power of relational databases not just on the server, but in our React applications. -Homebase React lets you plug a relational database into your React app with 3 lines of code. In fact it's the same database that powers Roam Research and many other ClojureScript applications, but with an API that's familiar to React and JS developers. +Homebase React lets you plug a relational database into your React application with just 3 lines of code. In fact, it's the same database that powers Roam Research and many other ClojureScript applications, but with an API that's familiar to React and JS developers. - Replace Redux with something simpler and more declarative +- Stop spending time wiring up custom datatypes, reducers, caches and other bespoke state mumbo jumbo - Gain all the benefits of relational data like a single source of truth -- Query your database with a convenient JSON query syntax -- Query your database with Clojure style datalog if you need more power - Traverse your data graph like it's one big JSON object -- Stop spending time wiring up custom datatypes, reducers, caches and other bespoke state mumbo jumbo +- Query your database with a convenient JSON query syntax +- Query your database with Clojure style [Datalog](https://docs.datomic.com/on-prem/query.html) if you need more power - It's just data -We think that Homebase React is immediately more intuitive than any denormalized JSON store, and over time it will get better as we eliminate all the tedious aspects of manipulating data on clients. +The goal of Homebase React is to be immediately more intuitive than any denormalized JSON store and over time we will eliminate all the tedious aspects of manipulating data on clients. Homebase React makes it easier to work with complex data on client by making our applications [local-first](https://news.ycombinator.com/item?id=21581444). + +## Examples +### Live Demos +You can see our hosted live demos [here](https://homebaseio.github.io/homebase-react) + +### Code Examples +You can clone and run our React code examples [here](https://github.com/homebaseio/homebase-react-examples). + ## API Overview @@ -151,6 +149,20 @@ todos .map(todo => todo.get('name')) ``` + +## Docs +https://www.notion.so/Homebase-Alpha-Docs-0f0e22f3adcd4e9d87a13440ab0c7a0b + +## Roadmap + +1. Improve performance +1. Document integration with backends +1. Swap [Datascript](https://github.com/tonsky/datascript) out for [Datahike](https://github.com/replikativ/datahike) + 1. Immutability + 1. History / Change Tracking +1. Persist to IndexDB +1. Local-first conflict resolution for offline caching and sync between multiple devices + ## Development ```bash @@ -167,15 +179,6 @@ yarn install yarn test ``` -## Roadmap - -1. Improve performance -1. Document integration with backends -1. Swap [Datascript](https://github.com/tonsky/datascript) out for [Datahike](https://github.com/replikativ/datahike) - 1. Immutability - 1. History / Change Tracking -1. Persist to IndexDB -1. Local-first conflict resolution for offline caching and sync between multiple devices ## Authors From 1c4f1e80988b4da67a69eefa205f6d812a828af4 Mon Sep 17 00:00:00 2001 From: Chris Smothers Date: Wed, 11 Nov 2020 15:53:27 -0500 Subject: [PATCH 3/6] docs(todo-example): clarify schema comments (#12) --- js/todo-example.jsx | 16 ++++++++++------ src/js_gen/todo-example.js | 18 +++++++++--------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/js/todo-example.jsx b/js/todo-example.jsx index b14b2228..5658de11 100644 --- a/js/todo-example.jsx +++ b/js/todo-example.jsx @@ -10,9 +10,10 @@ export const App = () => { } const config = { - // Schema is optional. Add as much or as little as you want. + // Schema is only used to enforce + // unique constraints and relationships. + // It is not a type system, yet. schema: { - user: { name: { type: 'string' } }, project: { name: { unique: 'identity' } }, todo: { // refs are relationships @@ -20,18 +21,21 @@ const config = { owner: { type: 'ref' } } }, + // Initial data let's you conveniently transact some + // starting data on DB creation to hydrate your components. initialData: [ { todoFilter: { - // identity is a special attribute for user generated ids - // E.g. this is a setting that should be easy to lookup by name + // identity is a special unique attribute for user generated ids + // E.g. todoFilters are settings that should be easy to lookup by their identity identity: 'todoFilters', showCompleted: true, project: 0 } }, { user: { - // negative numbers can be used as temporary ids in a transaction + // Negative numbers can be used as temporary ids in a transaction. + // Use them to relate multiple entities together at once. id: -1, name: 'Stella' } @@ -87,7 +91,7 @@ const NewTodo = () => { transact([{ todo: { name: e.target.elements['todo-name'].value, - createdAt: new Date + createdAt: new Date() } }]) e.target.reset() diff --git a/src/js_gen/todo-example.js b/src/js_gen/todo-example.js index e7c07932..69150f00 100644 --- a/src/js_gen/todo-example.js +++ b/src/js_gen/todo-example.js @@ -24,13 +24,10 @@ const App = () => { exports.App = App; const config = { - // Schema is optional. Add as much or as little as you want. + // Schema is only used to enforce + // unique constraints and relationships. + // It is not a type system, yet. schema: { - user: { - name: { - type: 'string' - } - }, project: { name: { unique: 'identity' @@ -46,17 +43,20 @@ const config = { } } }, + // Initial data let's you conveniently transact some + // starting data on DB creation to hydrate your components. initialData: [{ todoFilter: { - // identity is a special attribute for user generated ids - // E.g. this is a setting that should be easy to lookup by name + // identity is a special unique attribute for user generated ids + // E.g. todoFilters are settings that should be easy to lookup by their identity identity: 'todoFilters', showCompleted: true, project: 0 } }, { user: { - // negative numbers can be used as temporary ids in a transaction + // Negative numbers can be used as temporary ids in a transaction. + // Use them to relate multiple entities together at once. id: -1, name: 'Stella' } From 0b627e6045c06f17d9d06ccc2a3e622d19f5a598 Mon Sep 17 00:00:00 2001 From: Chris Smothers Date: Wed, 11 Nov 2020 21:20:40 -0500 Subject: [PATCH 4/6] ci: document and enforce our contribution protocols (#13) --- .husky/.gitignore | 1 + .husky/commit-msg | 4 + .husky/prepare-commit-msg | 7 + CHANGELOG.md | 4 - CONTRIBUTING.md | 21 ++ README.md | 5 + commitlint.config.js | 1 + package.json | 33 +- yarn.lock | 755 +++++++++++++++++++++++++++++++++++--- 9 files changed, 772 insertions(+), 59 deletions(-) create mode 100644 .husky/.gitignore create mode 100755 .husky/commit-msg create mode 100755 .husky/prepare-commit-msg delete mode 100644 CHANGELOG.md create mode 100644 CONTRIBUTING.md create mode 100644 commitlint.config.js diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 00000000..31354ec1 --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100755 index 00000000..b1743d7f --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,4 @@ +#!/bin/sh +. "$(dirname $0)/_/husky.sh" + +yarn commitlint -e "$(git rev-parse --git-dir)/COMMIT_EDITMSG" \ No newline at end of file diff --git a/.husky/prepare-commit-msg b/.husky/prepare-commit-msg new file mode 100755 index 00000000..e551897c --- /dev/null +++ b/.husky/prepare-commit-msg @@ -0,0 +1,7 @@ +#!/bin/sh +. "$(dirname $0)/_/husky.sh" + +NOCOLOR='\033[0m' +PURPLE='\033[1;35m' +exec < /dev/tty && yarn git-cz --hook || +echo "${PURPLE}FIX: Try upgrading git, --absolute-git-dir was introduced in v2.13${NOCOLOR}" && true \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 9b65b46a..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,4 +0,0 @@ -# v0.0.1 -- React component to provide a declarative relational DB with minimal fuss. -- React hooks for transact, query and find one entity. -- Make Datascript's syntax more JS and React friendly. \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..ee89150c --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,21 @@ +# Contribution guide + +## Developing homebase-react + +If you consider contributing changes to homebase-react – thank you! +Please review these guidelines when filing a pull request: + +- Commits follow the [Angular commit convention](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines) +- 2 spaces indentation +- Features and bug fixes should be covered by test cases + +## Creating releases + +homebase-react uses [semantic-release](https://github.com/semantic-release/semantic-release) +to release new versions automatically on merge to master. + +- Commits of type `fix` will trigger bugfix releases, think `0.0.1` +- Commits of type `feat` will trigger feature releases, think `0.1.0` +- Commits with `BREAKING CHANGE` in body or footer will trigger breaking releases, think `1.0.0` + +All other commit types will trigger no new release. \ No newline at end of file diff --git a/README.md b/README.md index 15fa5abd..e265eba7 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,11 @@ yarn install yarn test ``` +## Contributing + +Welcome and thank you! Writing docs, patches and features are all incredibly helpful and appreciated. + +We only ask that you provide test coverage for code changes, and conform to our [commit guidelines](CONTRIBUTING.md). ## Authors diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 00000000..28fe5c5b --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1 @@ +module.exports = {extends: ['@commitlint/config-conventional']} diff --git a/package.json b/package.json index 0a496774..8fba02e7 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "license": "MIT", "homepage": "https://github.com/homebaseio/homebase-react", "main": "./dist/js/homebase.react.js", + "private": false, "scripts": { "dev": "shadow-cljs watch dev", "build": "rm -rf dist && shadow-cljs release npm", @@ -15,7 +16,15 @@ "test": "yarn test:cljs && yarn test:js", "test:dev": "yarn test:cljs && yarn test:js:dev", "report": "rm -rf dist && shadow-cljs run shadow.cljs.build-report npm report.html", - "semantic-release": "semantic-release" + "semantic-release": "semantic-release", + "_postinstall": "husky install", + "prepublish": "pinst --disable", + "postpublish": "pinst --enable" + }, + "config": { + "commitizen": { + "path": "./node_modules/cz-conventional-changelog" + } }, "peerDependencies": { "react": ">=16.8.0" @@ -25,24 +34,30 @@ "@babel/core": "7.11.6", "@babel/plugin-transform-modules-commonjs": "7.12.1", "@babel/plugin-transform-react-jsx": "7.10.4", - "@semantic-release/changelog": "^5.0.1", - "@semantic-release/commit-analyzer": "^8.0.1", - "@semantic-release/git": "^9.0.0", - "@semantic-release/github": "^7.1.1", - "@semantic-release/npm": "^7.0.6", - "@semantic-release/release-notes-generator": "^9.0.1", + "@commitlint/cli": "^11.0.0", + "@commitlint/config-conventional": "^11.0.0", + "@semantic-release/changelog": "5.0.1", + "@semantic-release/commit-analyzer": "8.0.1", + "@semantic-release/git": "9.0.0", + "@semantic-release/github": "7.1.1", + "@semantic-release/npm": "7.0.6", + "@semantic-release/release-notes-generator": "9.0.1", "babel-runtime": "6.26.0", + "commitizen": "^4.2.2", "create-react-class": "15.6.3", + "cz-conventional-changelog": "^3.3.0", "enzyme": "3.11.0", "enzyme-adapter-react-16": "1.15.5", "highlight.js": "10.2.1", + "husky": "5.0.0-beta.0", "jest": "26.6.0", "marked": "1.2.0", + "pinst": "2.0.0", "react": "16.14.0", "react-component-benchmark": "0.0.4", "react-dom": "16.14.0", - "semantic-release": "^17.2.2", - "semantic-release-cli": "^5.4.0", + "semantic-release": "17.2.2", + "semantic-release-cli": "5.4.0", "shadow-cljs": "2.11.4" }, "keywords": [ diff --git a/yarn.lock b/yarn.lock index abc8ac49..188bf812 100644 --- a/yarn.lock +++ b/yarn.lock @@ -322,6 +322,13 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-jsx" "^7.10.4" +"@babel/runtime@^7.11.2": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e" + integrity sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg== + dependencies: + regenerator-runtime "^0.13.4" + "@babel/template@^7.10.4", "@babel/template@^7.3.3": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278" @@ -368,6 +375,142 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@commitlint/cli@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-11.0.0.tgz#698199bc52afed50aa28169237758fa14a67b5d3" + integrity sha512-YWZWg1DuqqO5Zjh7vUOeSX76vm0FFyz4y0cpGMFhrhvUi5unc4IVfCXZ6337R9zxuBtmveiRuuhQqnRRer+13g== + dependencies: + "@babel/runtime" "^7.11.2" + "@commitlint/format" "^11.0.0" + "@commitlint/lint" "^11.0.0" + "@commitlint/load" "^11.0.0" + "@commitlint/read" "^11.0.0" + chalk "4.1.0" + core-js "^3.6.1" + get-stdin "8.0.0" + lodash "^4.17.19" + resolve-from "5.0.0" + resolve-global "1.0.0" + yargs "^15.1.0" + +"@commitlint/config-conventional@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/config-conventional/-/config-conventional-11.0.0.tgz#3fa300a1b639273946de3c3f15e1cda518333422" + integrity sha512-SNDRsb5gLuDd2PL83yCOQX6pE7gevC79UPFx+GLbLfw6jGnnbO9/tlL76MLD8MOViqGbo7ZicjChO9Gn+7tHhA== + dependencies: + conventional-changelog-conventionalcommits "^4.3.1" + +"@commitlint/ensure@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-11.0.0.tgz#3e796b968ab5b72bc6f8a6040076406306c987fb" + integrity sha512-/T4tjseSwlirKZdnx4AuICMNNlFvRyPQimbZIOYujp9DSO6XRtOy9NrmvWujwHsq9F5Wb80QWi4WMW6HMaENug== + dependencies: + "@commitlint/types" "^11.0.0" + lodash "^4.17.19" + +"@commitlint/execute-rule@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-11.0.0.tgz#3ed60ab7a33019e58d90e2d891b75d7df77b4b4d" + integrity sha512-g01p1g4BmYlZ2+tdotCavrMunnPFPhTzG1ZiLKTCYrooHRbmvqo42ZZn4QMStUEIcn+jfLb6BRZX3JzIwA1ezQ== + +"@commitlint/format@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/format/-/format-11.0.0.tgz#ac47b0b9ca46540c0082c721b290794e67bdc51b" + integrity sha512-bpBLWmG0wfZH/svzqD1hsGTpm79TKJWcf6EXZllh2J/LSSYKxGlv967lpw0hNojme0sZd4a/97R3qA2QHWWSLg== + dependencies: + "@commitlint/types" "^11.0.0" + chalk "^4.0.0" + +"@commitlint/is-ignored@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/is-ignored/-/is-ignored-11.0.0.tgz#7b803eda56276dbe7fec51eb1510676198468f39" + integrity sha512-VLHOUBN+sOlkYC4tGuzE41yNPO2w09sQnOpfS+pSPnBFkNUUHawEuA44PLHtDvQgVuYrMAmSWFQpWabMoP5/Xg== + dependencies: + "@commitlint/types" "^11.0.0" + semver "7.3.2" + +"@commitlint/lint@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/lint/-/lint-11.0.0.tgz#01e062cd1b0e7c3d756aa2c246462e0b6a3348a4" + integrity sha512-Q8IIqGIHfwKr8ecVZyYh6NtXFmKw4YSEWEr2GJTB/fTZXgaOGtGFZDWOesCZllQ63f1s/oWJYtVv5RAEuwN8BQ== + dependencies: + "@commitlint/is-ignored" "^11.0.0" + "@commitlint/parse" "^11.0.0" + "@commitlint/rules" "^11.0.0" + "@commitlint/types" "^11.0.0" + +"@commitlint/load@>6.1.1", "@commitlint/load@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-11.0.0.tgz#f736562f0ffa7e773f8808fea93319042ee18211" + integrity sha512-t5ZBrtgvgCwPfxmG811FCp39/o3SJ7L+SNsxFL92OR4WQxPcu6c8taD0CG2lzOHGuRyuMxZ7ps3EbngT2WpiCg== + dependencies: + "@commitlint/execute-rule" "^11.0.0" + "@commitlint/resolve-extends" "^11.0.0" + "@commitlint/types" "^11.0.0" + chalk "4.1.0" + cosmiconfig "^7.0.0" + lodash "^4.17.19" + resolve-from "^5.0.0" + +"@commitlint/message@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/message/-/message-11.0.0.tgz#83554c3cbbc884fd07b473593bc3e94bcaa3ee05" + integrity sha512-01ObK/18JL7PEIE3dBRtoMmU6S3ecPYDTQWWhcO+ErA3Ai0KDYqV5VWWEijdcVafNpdeUNrEMigRkxXHQLbyJA== + +"@commitlint/parse@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/parse/-/parse-11.0.0.tgz#d18b08cf67c35d02115207d7009306a2e8e7c901" + integrity sha512-DekKQAIYWAXIcyAZ6/PDBJylWJ1BROTfDIzr9PMVxZRxBPc1gW2TG8fLgjZfBP5mc0cuthPkVi91KQQKGri/7A== + dependencies: + conventional-changelog-angular "^5.0.0" + conventional-commits-parser "^3.0.0" + +"@commitlint/read@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-11.0.0.tgz#f24240548c63587bba139fa5a364cab926077016" + integrity sha512-37V0V91GSv0aDzMzJioKpCoZw6l0shk7+tRG8RkW1GfZzUIytdg3XqJmM+IaIYpaop0m6BbZtfq+idzUwJnw7g== + dependencies: + "@commitlint/top-level" "^11.0.0" + fs-extra "^9.0.0" + git-raw-commits "^2.0.0" + +"@commitlint/resolve-extends@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-11.0.0.tgz#158ecbe27d4a2a51d426111a01478e216fbb1036" + integrity sha512-WinU6Uv6L7HDGLqn/To13KM1CWvZ09VHZqryqxXa1OY+EvJkfU734CwnOEeNlSCK7FVLrB4kmodLJtL1dkEpXw== + dependencies: + import-fresh "^3.0.0" + lodash "^4.17.19" + resolve-from "^5.0.0" + resolve-global "^1.0.0" + +"@commitlint/rules@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-11.0.0.tgz#bdb310cc6fc55c9f8d7d917a22b69055c535c375" + integrity sha512-2hD9y9Ep5ZfoNxDDPkQadd2jJeocrwC4vJ98I0g8pNYn/W8hS9+/FuNpolREHN8PhmexXbkjrwyQrWbuC0DVaA== + dependencies: + "@commitlint/ensure" "^11.0.0" + "@commitlint/message" "^11.0.0" + "@commitlint/to-lines" "^11.0.0" + "@commitlint/types" "^11.0.0" + +"@commitlint/to-lines@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/to-lines/-/to-lines-11.0.0.tgz#86dea151c10eea41e39ea96fa4de07839258a7fe" + integrity sha512-TIDTB0Y23jlCNubDROUVokbJk6860idYB5cZkLWcRS9tlb6YSoeLn1NLafPlrhhkkkZzTYnlKYzCVrBNVes1iw== + +"@commitlint/top-level@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/top-level/-/top-level-11.0.0.tgz#bb2d1b6e5ed3be56874633b59e1f7de118c32783" + integrity sha512-O0nFU8o+Ws+py5pfMQIuyxOtfR/kwtr5ybqTvR+C2lUPer2x6lnQU+OnfD7hPM+A+COIUZWx10mYQvkR3MmtAA== + dependencies: + find-up "^5.0.0" + +"@commitlint/types@^11.0.0": + version "11.0.0" + resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-11.0.0.tgz#719cf05fcc1abb6533610a2e0f5dd1e61eac14fe" + integrity sha512-VoNqai1vR5anRF5Tuh/+SWDFk7xi7oMwHrHrbm1BprYXjB2RJsWLhUrStMssDxEl5lW/z3EUdg8RvH/IUBccSQ== + "@iarna/cli@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@iarna/cli/-/cli-1.2.0.tgz#0f7af5e851afe895104583c4ca07377a8094d641" @@ -689,7 +832,7 @@ dependencies: "@types/node" ">= 8" -"@semantic-release/changelog@^5.0.1": +"@semantic-release/changelog@5.0.1": version "5.0.1" resolved "https://registry.yarnpkg.com/@semantic-release/changelog/-/changelog-5.0.1.tgz#50a84b63e5d391b7debfe021421589fa2bcdafe4" integrity sha512-unvqHo5jk4dvAf2nZ3aw4imrlwQ2I50eVVvq9D47Qc3R+keNqepx1vDYwkjF8guFXnOYaYcR28yrZWno1hFbiw== @@ -699,7 +842,7 @@ fs-extra "^9.0.0" lodash "^4.17.4" -"@semantic-release/commit-analyzer@^8.0.0", "@semantic-release/commit-analyzer@^8.0.1": +"@semantic-release/commit-analyzer@8.0.1", "@semantic-release/commit-analyzer@^8.0.0": version "8.0.1" resolved "https://registry.yarnpkg.com/@semantic-release/commit-analyzer/-/commit-analyzer-8.0.1.tgz#5d2a37cd5a3312da0e3ac05b1ca348bf60b90bca" integrity sha512-5bJma/oB7B4MtwUkZC2Bf7O1MHfi4gWe4mA+MIQ3lsEV0b422Bvl1z5HRpplDnMLHH3EXMoRdEng6Ds5wUqA3A== @@ -717,7 +860,7 @@ resolved "https://registry.yarnpkg.com/@semantic-release/error/-/error-2.2.0.tgz#ee9d5a09c9969eade1ec864776aeda5c5cddbbf0" integrity sha512-9Tj/qn+y2j+sjCI3Jd+qseGtHjOAeg7dU2/lVcqIQ9TV3QDaDXDYXcoOHU+7o2Hwh8L8ymL4gfuO7KxDs3q2zg== -"@semantic-release/git@^9.0.0": +"@semantic-release/git@9.0.0": version "9.0.0" resolved "https://registry.yarnpkg.com/@semantic-release/git/-/git-9.0.0.tgz#304c4883c87d095b1faaae93300f1f1e0466e9a5" integrity sha512-AZ4Zha5NAPAciIJH3ipzw/WU9qLAn8ENaoVAhD6srRPxTpTzuV3NhNh14rcAo8Paj9dO+5u4rTKcpetOBluYVw== @@ -731,7 +874,7 @@ micromatch "^4.0.0" p-reduce "^2.0.0" -"@semantic-release/github@^7.0.0", "@semantic-release/github@^7.1.1": +"@semantic-release/github@7.1.1", "@semantic-release/github@^7.0.0": version "7.1.1" resolved "https://registry.yarnpkg.com/@semantic-release/github/-/github-7.1.1.tgz#e998aa9a9cd770838d9f27c64f060c2b686b9d95" integrity sha512-w8CLCvGVKNe2FPOYQ68OFxFVNNha7YRzptnwTZYdjXYtgTDKw0XVfnMSd9NlJeQPYGfQmIhIVPNBU/cA6zUY0A== @@ -753,7 +896,7 @@ p-retry "^4.0.0" url-join "^4.0.0" -"@semantic-release/npm@^7.0.0", "@semantic-release/npm@^7.0.6": +"@semantic-release/npm@7.0.6", "@semantic-release/npm@^7.0.0": version "7.0.6" resolved "https://registry.yarnpkg.com/@semantic-release/npm/-/npm-7.0.6.tgz#1301bd57d246eae048d7104a735467bb0829f3d8" integrity sha512-F4judxdeLe8f7+vDva1TkqNc5Tb2tcltZYW0tLtvP2Xt7CD/gGiz7UxAWEOPsXBvIqAP+uTidvGLPl9U3/uRoQ== @@ -772,7 +915,7 @@ semver "^7.1.2" tempy "^0.5.0" -"@semantic-release/release-notes-generator@^9.0.0", "@semantic-release/release-notes-generator@^9.0.1": +"@semantic-release/release-notes-generator@9.0.1", "@semantic-release/release-notes-generator@^9.0.0": version "9.0.1" resolved "https://registry.yarnpkg.com/@semantic-release/release-notes-generator/-/release-notes-generator-9.0.1.tgz#732d285d103064f2a64f08a32031551ebb4f918b" integrity sha512-bOoTiH6SiiR0x2uywSNR7uZcRDl22IpZhj+Q5Bn0v+98MFtOMhCxFhbrKQjhbYoZw7vps1mvMRmFkp/g6R9cvQ== @@ -1041,6 +1184,11 @@ ansi-align@^3.0.0: dependencies: string-width "^3.0.0" +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" @@ -1173,6 +1321,11 @@ array-filter@^1.0.0: resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= + array-ify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" @@ -2200,6 +2353,11 @@ cacheable-request@^6.0.0: normalize-url "^4.1.0" responselike "^1.0.2" +cachedir@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.2.0.tgz#19afa4305e05d79e417566882e0c8f960f62ff0e" + integrity sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ== + call-bind@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.0.tgz#24127054bb3f9bdcb4b1fb82418186072f77b8ce" @@ -2218,6 +2376,15 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelcase-keys@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" + integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c= + dependencies: + camelcase "^4.1.0" + map-obj "^2.0.0" + quick-lru "^1.0.0" + camelcase-keys@^6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" @@ -2272,6 +2439,14 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= +chalk@4.1.0, chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -2283,7 +2458,7 @@ chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.2, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2292,14 +2467,6 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.2, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.0.0, chalk@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" - integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" @@ -2409,6 +2576,13 @@ cli-columns@^3.1.2: string-width "^2.0.0" strip-ansi "^3.0.1" +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -2433,6 +2607,11 @@ cli-table@^0.3.1: dependencies: colors "1.0.3" +cli-width@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" + integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== + cli-width@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" @@ -2576,6 +2755,26 @@ commander@^4.0.1: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +commitizen@^4.0.3, commitizen@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/commitizen/-/commitizen-4.2.2.tgz#1a93dd07208521ea1ebbf832593542dac714cc79" + integrity sha512-uz+E6lGsDBDI2mYA4QfOxFeqdWUYwR1ky11YmLgg2BnEEP3YbeejpT4lxzGjkYqumnXr062qTOGavR9NtX/iwQ== + dependencies: + cachedir "2.2.0" + cz-conventional-changelog "3.3.0" + dedent "0.7.0" + detect-indent "6.0.0" + find-node-modules "2.0.0" + find-root "1.1.0" + fs-extra "8.1.0" + glob "7.1.4" + inquirer "6.5.2" + is-utf8 "^0.2.1" + lodash "^4.17.20" + minimist "1.2.5" + strip-bom "4.0.0" + strip-json-comments "3.0.1" + compare-func@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3" @@ -2659,6 +2858,15 @@ conventional-changelog-angular@^5.0.0: compare-func "^2.0.0" q "^1.5.1" +conventional-changelog-conventionalcommits@^4.3.1: + version "4.5.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.5.0.tgz#a02e0b06d11d342fdc0f00c91d78265ed0bc0a62" + integrity sha512-buge9xDvjjOxJlyxUnar/+6i/aVEVGA7EEh4OafBCXPlLUQPGbRUBhBUveWRxzvR8TEjhKEP4BdepnpG2FSZXw== + dependencies: + compare-func "^2.0.0" + lodash "^4.17.15" + q "^1.5.1" + conventional-changelog-writer@^4.0.0: version "4.0.18" resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.18.tgz#10b73baa59c7befc69b360562f8b9cd19e63daf8" @@ -2675,6 +2883,11 @@ conventional-changelog-writer@^4.0.0: split "^1.0.0" through2 "^4.0.0" +conventional-commit-types@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/conventional-commit-types/-/conventional-commit-types-3.0.0.tgz#7c9214e58eae93e85dd66dbfbafe7e4fffa2365b" + integrity sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg== + conventional-commits-filter@^2.0.0, conventional-commits-filter@^2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz#f8d9b4f182fce00c9af7139da49365b136c8a0b3" @@ -2730,6 +2943,11 @@ core-js@^2.4.0, core-js@^2.5.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== +core-js@^3.6.1: + version "3.7.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.7.0.tgz#b0a761a02488577afbf97179e4681bf49568520f" + integrity sha512-NwS7fI5M5B85EwpWuIwJN4i/fbisQUwLwiSNUWeXlkAZ0sbBjLEvLvFLf1uzAUV66PcEPt4xCGCmOZSxVf3xzA== + core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -2746,6 +2964,17 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" +cosmiconfig@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.0.tgz#ef9b44d773959cae63ddecd122de23853b60f8d3" + integrity sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA== + dependencies: + "@types/parse-json" "^4.0.0" + import-fresh "^3.2.1" + parse-json "^5.0.0" + path-type "^4.0.0" + yaml "^1.10.0" + create-ecdh@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" @@ -2881,11 +3110,37 @@ cssstyle@^2.2.0: dependencies: cssom "~0.3.6" +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= + dependencies: + array-find-index "^1.0.1" + cyclist@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= +cz-conventional-changelog@3.3.0, cz-conventional-changelog@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz#9246947c90404149b3fe2cf7ee91acad3b7d22d2" + integrity sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw== + dependencies: + chalk "^2.4.1" + commitizen "^4.0.3" + conventional-commit-types "^3.0.0" + lodash.map "^4.5.1" + longest "^2.0.1" + word-wrap "^1.0.3" + optionalDependencies: + "@commitlint/load" ">6.1.1" + +dargs@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" + integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== + dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -2940,7 +3195,7 @@ debuglog@^1.0.1: resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= -decamelize-keys@^1.1.0: +decamelize-keys@^1.0.0, decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= @@ -2970,6 +3225,11 @@ decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" +dedent@0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= + deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -3049,6 +3309,16 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" +detect-file@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" + integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= + +detect-indent@6.0.0, detect-indent@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd" + integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA== + detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" @@ -3542,6 +3812,13 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" +expand-tilde@^2.0.0, expand-tilde@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" + integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= + dependencies: + homedir-polyfill "^1.0.1" + expect@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" @@ -3702,11 +3979,24 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +find-node-modules@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/find-node-modules/-/find-node-modules-2.0.0.tgz#5db1fb9e668a3d451db3d618cd167cdd59e41b69" + integrity sha512-8MWIBRgJi/WpjjfVXumjPKCtmQ10B+fjx6zmSA+770GMJirLhWIzg8l763rhjl9xaeaHbnxPNRQKq2mgMhr+aw== + dependencies: + findup-sync "^3.0.0" + merge "^1.2.1" + find-npm-prefix@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/find-npm-prefix/-/find-npm-prefix-1.0.2.tgz#8d8ce2c78b3b4b9e66c8acc6a37c231eb841cfdf" integrity sha512-KEftzJ+H90x6pcKtdXZEPsQse8/y/UnvzRKrOSQFprnrGaFuJ62fVkP34Iu2IYuMvyauCyoLTNkJZgrrGA2wkA== +find-root@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + find-up@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -3729,6 +4019,14 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + find-versions@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" @@ -3736,6 +4034,16 @@ find-versions@^3.0.0: dependencies: semver-regex "^2.0.0" +findup-sync@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" + integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== + dependencies: + detect-file "^1.0.0" + is-glob "^4.0.0" + micromatch "^3.0.4" + resolve-dir "^1.0.1" + flush-write-stream@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" @@ -3786,6 +4094,15 @@ from2@^2.1.0, from2@^2.3.0: inherits "^2.0.1" readable-stream "^2.0.0" +fs-extra@8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + fs-extra@^9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.0.1.tgz#910da0062437ba4c39fedd863f1675ccfefcb9fc" @@ -3929,6 +4246,11 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== +get-stdin@8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" + integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -3977,6 +4299,17 @@ git-log-parser@^1.2.0: through2 "~2.0.0" traverse "~0.6.6" +git-raw-commits@^2.0.0: + version "2.0.8" + resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.8.tgz#65cef91ae8307281b6ee31ca481fa1164e166156" + integrity sha512-6Gk7tQHGMLEL1bSnrMJTCVt2AQl4EmCcJDtzs/JJacCb2+TNEyHM67Gp7Ri9faF7OcGpjGGRjHLvs/AG7QKZ2Q== + dependencies: + dargs "^7.0.0" + lodash.template "^4.0.2" + meow "^8.0.0" + split2 "^2.0.0" + through2 "^4.0.0" + github-url-from-git@^1.4.0: version "1.5.0" resolved "https://registry.yarnpkg.com/github-url-from-git/-/github-url-from-git-1.5.0.tgz#f985fedcc0a9aa579dc88d7aff068d55cc6251a0" @@ -4002,6 +4335,18 @@ glob-parent@^5.1.0: dependencies: is-glob "^4.0.1" +glob@7.1.4: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -4014,13 +4359,33 @@ glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -global-dirs@^0.1.0: +global-dirs@^0.1.0, global-dirs@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= dependencies: ini "^1.3.4" +global-modules@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" + integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== + dependencies: + global-prefix "^1.0.1" + is-windows "^1.0.1" + resolve-dir "^1.0.0" + +global-prefix@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" + integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= + dependencies: + expand-tilde "^2.0.2" + homedir-polyfill "^1.0.1" + ini "^1.3.4" + is-windows "^1.0.1" + which "^1.2.14" + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -4226,6 +4591,13 @@ home-or-tmp@^2.0.0: os-homedir "^1.0.0" os-tmpdir "^1.0.1" +homedir-polyfill@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" + integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== + dependencies: + parse-passwd "^1.0.0" + hook-std@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/hook-std/-/hook-std-2.0.0.tgz#ff9aafdebb6a989a354f729bb6445cf4a3a7077c" @@ -4343,6 +4715,11 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" +husky@5.0.0-beta.0: + version "5.0.0-beta.0" + resolved "https://registry.yarnpkg.com/husky/-/husky-5.0.0-beta.0.tgz#b09c5a7da1da884cfd9ff0d7cfd328b77e068516" + integrity sha512-gemLvVKIeuSuu+xp+hY5DUNjNSNk4YIgdsFhC3Wwv6tpc8VIGNR+0g+5uOpsiNNlAekcaMfO06mwSSokqLAlhQ== + iconv-lite@0.4.24, iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -4384,7 +4761,7 @@ ignore@^5.1.4: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== -import-fresh@^3.1.0: +import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1: version "3.2.2" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.2.tgz#fc129c160c5d68235507f4331a6baad186bdbc3e" integrity sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw== @@ -4417,6 +4794,11 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= + indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" @@ -4469,6 +4851,25 @@ init-package-json@^1.10.3: validate-npm-package-license "^3.0.1" validate-npm-package-name "^3.0.0" +inquirer@6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + inquirer@^7.0.0: version "7.3.3" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" @@ -4749,6 +5150,11 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= +is-plain-obj@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -4822,7 +5228,12 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= -is-windows@^1.0.2: +is-utf8@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== @@ -5421,6 +5832,13 @@ json5@^2.1.2: dependencies: minimist "^1.2.5" +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -5679,6 +6097,16 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" +load-json-file@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-6.2.0.tgz#5c7770b42cafa97074ca2848707c61662f4251a1" + integrity sha512-gUD/epcRms75Cw8RT1pUdHugZYM5ce64ucs2GEISABwkRsOQr0q2wm/MV2TKThycIe5e0ytRweW2RZxclogCdQ== + dependencies: + graceful-fs "^4.1.15" + parse-json "^5.0.0" + strip-bom "^4.0.0" + type-fest "^0.6.0" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -5702,6 +6130,13 @@ locate-path@^5.0.0: dependencies: p-locate "^4.1.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + lock-verify@^2.0.2, lock-verify@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/lock-verify/-/lock-verify-2.2.1.tgz#81107948c51ed16f97b96ff8b60675affb243fc1" @@ -5731,6 +6166,11 @@ lodash._createset@~4.0.0: resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY= +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + lodash._root@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" @@ -5781,11 +6221,36 @@ lodash.isstring@^4.0.1: resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= +lodash.map@^4.5.1: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" + integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= + +lodash.mapkeys@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mapkeys/-/lodash.mapkeys-4.6.0.tgz#df2cfa231d7c57c7a8ad003abdad5d73d3ea5195" + integrity sha1-3yz6Ix18V8eorQA6va1dc9PqUZU= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= +lodash.template@^4.0.2: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.toarray@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" @@ -5811,7 +6276,7 @@ lodash.without@~4.4.0: resolved "https://registry.yarnpkg.com/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac" integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw= -lodash@^4.15.0, lodash@^4.16.4, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.4: +lodash@^4.15.0, lodash@^4.16.4, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== @@ -5821,6 +6286,11 @@ lodash@~1.3.1: resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.3.1.tgz#a4663b53686b895ff074e2ba504dfb76a8e2b770" integrity sha1-pGY7U2hriV/wdOK6UE37dqjit3A= +longest@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-2.0.1.tgz#781e183296aa94f6d4d916dc335d0d17aefa23f8" + integrity sha1-eB4YMpaqlPbU2RbcM10NF676I/g= + loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -5828,6 +6298,14 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4 dependencies: js-tokens "^3.0.0 || ^4.0.0" +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -5921,6 +6399,11 @@ map-obj@^1.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= +map-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" + integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= + map-obj@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5" @@ -5976,6 +6459,21 @@ mem@^1.1.0: dependencies: mimic-fn "^1.0.0" +meow@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" + integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== + dependencies: + camelcase-keys "^4.0.0" + decamelize-keys "^1.0.0" + loud-rejection "^1.0.0" + minimist-options "^3.0.1" + normalize-package-data "^2.3.4" + read-pkg-up "^3.0.0" + redent "^2.0.0" + trim-newlines "^2.0.0" + yargs-parser "^10.0.0" + meow@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/meow/-/meow-8.0.0.tgz#1aa10ee61046719e334ffdc038bb5069250ec99a" @@ -6003,7 +6501,12 @@ merge2@^1.3.0: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^3.1.10, micromatch@^3.1.4: +merge@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/merge/-/merge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145" + integrity sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ== + +micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -6101,7 +6604,15 @@ minimist-options@4.1.0: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: +minimist-options@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" + integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + +minimist@1.2.5, minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -6189,6 +6700,11 @@ ms@2.1.2, ms@^2.0.0, ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + mute-stream@0.0.8, mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" @@ -6352,7 +6868,7 @@ nopt@^4.0.0, nopt@^4.0.1, nopt@^4.0.3: abbrev "1" osenv "^0.1.4" -normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0: +normalize-package-data@^2.0.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== @@ -6767,6 +7283,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0, once@~1.4.0: dependencies: wrappy "1" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + onetime@^5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" @@ -6880,6 +7403,13 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" +p-limit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -6901,6 +7431,13 @@ p-locate@^4.1.0: dependencies: p-limit "^2.2.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + p-map@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" @@ -7055,6 +7592,11 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= + parse5@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" @@ -7124,6 +7666,13 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -7165,6 +7714,16 @@ pify@^4.0.0, pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== +pinst@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pinst/-/pinst-2.0.0.tgz#220d3dff268eb133b51c23ef2b382cf1b782ca86" + integrity sha512-ZfR7vITsD/kBzxZLBz8GhPDenSs33p/3qNPyxhQEQef2rxyOrLmhkUtZnKQyk4cKKGMDC7piuebZSOor4XISeQ== + dependencies: + load-json-file "^6.2.0" + lodash.mapkeys "^4.6.0" + meow "^5.0.0" + write-json-file "^4.2.0" + pirates@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" @@ -7398,6 +7957,11 @@ querystring@0.2.0: resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= +quick-lru@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" + integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= + quick-lru@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" @@ -7545,6 +8109,14 @@ read-pkg-up@^2.0.0: find-up "^2.0.0" read-pkg "^2.0.0" +read-pkg-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" + integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= + dependencies: + find-up "^2.0.0" + read-pkg "^3.0.0" + read-pkg-up@^7.0.0, read-pkg-up@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" @@ -7563,6 +8135,15 @@ read-pkg@^2.0.0: normalize-package-data "^2.3.2" path-type "^2.0.0" +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + read-pkg@^5.0.0, read-pkg@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" @@ -7636,6 +8217,14 @@ readline-sync@^1.4.7: resolved "https://registry.yarnpkg.com/readline-sync/-/readline-sync-1.4.10.tgz#41df7fbb4b6312d673011594145705bf56d8873b" integrity sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw== +redent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" + integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= + dependencies: + indent-string "^3.0.0" + strip-indent "^2.0.0" + redent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" @@ -7671,6 +8260,11 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== +regenerator-runtime@^0.13.4: + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + regenerator-transform@^0.10.0: version "0.10.1" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" @@ -7841,15 +8435,30 @@ resolve-cwd@^3.0.0: dependencies: resolve-from "^5.0.0" +resolve-dir@^1.0.0, resolve-dir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" + integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= + dependencies: + expand-tilde "^2.0.0" + global-modules "^1.0.0" + +resolve-from@5.0.0, resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== +resolve-global@1.0.0, resolve-global@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-global/-/resolve-global-1.0.0.tgz#a2a79df4af2ca3f49bf77ef9ddacd322dad19255" + integrity sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw== + dependencies: + global-dirs "^0.1.1" resolve-url@^0.2.1: version "0.2.1" @@ -7871,6 +8480,14 @@ responselike@^1.0.2: dependencies: lowercase-keys "^1.0.0" +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -7934,7 +8551,7 @@ rsvp@^4.8.4: resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== -run-async@^2.4.0: +run-async@^2.2.0, run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== @@ -7951,7 +8568,7 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@^6.6.0: +rxjs@^6.4.0, rxjs@^6.6.0: version "6.6.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== @@ -8010,7 +8627,7 @@ scheduler@^0.19.1: loose-envify "^1.1.0" object-assign "^4.1.1" -semantic-release-cli@^5.4.0: +semantic-release-cli@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/semantic-release-cli/-/semantic-release-cli-5.4.0.tgz#35df971e22cd08da099ebe43536a2479a71a8162" integrity sha512-bhl5LsfZax3VdX5yOpebufiZiVzhxEJlh4Cx8p7t9lfoGJnWvIi1rgWRKghZ+nR8OKFARuc+5oYeJOGkhyZxYg== @@ -8043,7 +8660,7 @@ semantic-release-cli@^5.4.0: user-home "^2.0.0" validator "^12.0.0" -semantic-release@^17.2.2: +semantic-release@17.2.2: version "17.2.2" resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-17.2.2.tgz#520dae9cd188c7cdcc5216a7aad131548fc5cec7" integrity sha512-LNU68ud3a3oU46H11OThXaKAK430jGGGTIF4VsiP843kRmS6s8kVCceLRdi7yWWz/sCCMD0zygPTQV2Jw79J5g== @@ -8101,16 +8718,16 @@ semver-regex@^2.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@7.3.2, semver@^7.1.2, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.1.2, semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== - set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -8282,6 +8899,13 @@ socks@~2.3.2: ip "1.1.5" smart-buffer "^4.1.0" +sort-keys@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-4.1.0.tgz#727edc12fee49ce482848db07369ec44e0f3e9f2" + integrity sha512-/sRdxzkkPFUYiCrTr/2t+104nDc9AgDmEpeVYuvOWYQe3Djk1GWO6lVw3Vx2jfh1SsR0eehhd1nvFYlzt5e99w== + dependencies: + is-plain-obj "^2.0.0" + sorted-object@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/sorted-object/-/sorted-object-2.0.1.tgz#7d631f4bd3a798a24af1dffcfbfe83337a5df5fc" @@ -8522,7 +9146,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -8629,16 +9253,16 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" +strip-bom@4.0.0, strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -8649,6 +9273,11 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= + strip-indent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" @@ -8656,6 +9285,11 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" +strip-json-comments@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" @@ -8900,6 +9534,11 @@ travis-ci@^2.1.1: request "^2.87.0" underscore.string "~2.2.0rc" +trim-newlines@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" + integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= + trim-newlines@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30" @@ -9084,6 +9723,11 @@ universal-user-agent@^6.0.0: resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + universalify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d" @@ -9355,7 +9999,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@^1.2.9, which@^1.3.0, which@^1.3.1: +which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -9390,7 +10034,7 @@ windows-release@^3.1.0: dependencies: execa "^1.0.0" -word-wrap@~1.2.3: +word-wrap@^1.0.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -9462,6 +10106,18 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +write-json-file@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-4.3.0.tgz#908493d6fd23225344af324016e4ca8f702dd12d" + integrity sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ== + dependencies: + detect-indent "^6.0.0" + graceful-fs "^4.1.15" + is-plain-obj "^2.0.0" + make-dir "^3.0.0" + sort-keys "^4.0.0" + write-file-atomic "^3.0.0" + ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -9521,11 +10177,18 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^1.7.2: +yaml@^1.10.0, yaml@^1.7.2: version "1.10.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== +yargs-parser@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" + integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== + dependencies: + camelcase "^4.1.0" + yargs-parser@^15.0.1: version "15.0.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.1.tgz#54786af40b820dcb2fb8025b11b4d659d76323b3" @@ -9571,7 +10234,7 @@ yargs@^14.2.3: y18n "^4.0.0" yargs-parser "^15.0.1" -yargs@^15.0.1, yargs@^15.4.1: +yargs@^15.0.1, yargs@^15.1.0, yargs@^15.4.1: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== From 798daf0b409b2b402bcbe8dc554c61df632982f1 Mon Sep 17 00:00:00 2001 From: Chris Smothers Date: Wed, 11 Nov 2020 21:36:03 -0500 Subject: [PATCH 5/6] build(npm): remove ci and cd code from releases (#14) --- .npmignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.npmignore b/.npmignore index 85a395a0..622012ea 100644 --- a/.npmignore +++ b/.npmignore @@ -1,3 +1,8 @@ +.github/ +.husky/ +.releaserc.json +commitlint.config.js + node_modules/ public/js out/ From 2cba32f4223f8fc6c94ffbc0b2c08ad5faa6e2eb Mon Sep 17 00:00:00 2001 From: Chris Smothers Date: Mon, 16 Nov 2020 16:52:54 -0500 Subject: [PATCH 6/6] perf(entity.get): add attribute change tracking (#15) - improve re-render performance by ~2x on light pages - improve re-render performance by ~4x on heavy pages with ~10k components - only trigger re-renders on attributes that have changed - instrument `entity.get` to track used attributes and scope them to their respective hook - update the todo example to better leverage these new performance features - add performance section to readme --- .github/workflows/publish-examples.yml | 2 +- README.md | 31 ++++ js/todo-example.jsx | 207 +++++++++++------------ package.json | 1 + shadow-cljs.edn | 4 + src/homebase/js.cljs | 151 ++++++++++------- src/homebase/js_test.cljs | 73 ++++++--- src/homebase/react.cljs | 52 +++++- src/js_gen/todo-example.js | 219 +++++++++++++------------ 9 files changed, 431 insertions(+), 309 deletions(-) diff --git a/.github/workflows/publish-examples.yml b/.github/workflows/publish-examples.yml index e2b3052e..2aacb891 100644 --- a/.github/workflows/publish-examples.yml +++ b/.github/workflows/publish-examples.yml @@ -44,7 +44,7 @@ jobs: - run: yarn install --frozen-lockfile - - run: yarn shadow-cljs compile dev + - run: yarn shadow-cljs release dev - name: Publish to GitHub Pages 🚀 uses: JamesIves/github-pages-deploy-action@releases/v3 diff --git a/README.md b/README.md index e265eba7..00abd0dd 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,37 @@ todos .map(todo => todo.get('name')) ``` +## Performance + +Homebase React tracks the attributes consumed in each component via the `entity.get` function and scopes those attributes to their respective `useEntity` or `useQuery` hook. Re-renders are only triggered when an attribute changes. + +The default caching reduces unnecessary re-renders and virtual DOM thrashing a lot. That said, it is still possible to trigger more re-renders than you might want. + +One top level `useQuery` + prop drilling the entities it returns will cause all children to re-render on any change to the parent or their siblings. + +To fix this we recommend passing ids to children, not whole entities. Instead get the entity in the child with `useEntity(id)`. This creates a new scope for each child so they are not affected by changes in the state of the parent or sibling components. + +```js +const TodoList = () => { + const [todos] = useQuery({ + $find: 'todo', + $where: { todo: { name: '$any' } } + }) + return (todos.map(t => )) +} + +// Good +const Todo = React.memo(({ id }) => { + const [todo] = useEntity(id) + // ... +}) + +// Bad +const Todo = React.memo(({ todo }) => { + // ... +}) +``` + ## Docs https://www.notion.so/Homebase-Alpha-Docs-0f0e22f3adcd4e9d87a13440ab0c7a0b diff --git a/js/todo-example.jsx b/js/todo-example.jsx index 5658de11..7e7c815c 100644 --- a/js/todo-example.jsx +++ b/js/todo-example.jsx @@ -29,8 +29,7 @@ const config = { // identity is a special unique attribute for user generated ids // E.g. todoFilters are settings that should be easy to lookup by their identity identity: 'todoFilters', - showCompleted: true, - project: 0 + showCompleted: true } }, { user: { @@ -110,57 +109,6 @@ const NewTodo = () => { ) } -const TodoFilters = () => { - const [filters] = useEntity({ identity: 'todoFilters' }) - const [transact] = useTransact() - return ( -
- - transact([{ todoFilter: { id: filters.get('id'), showCompleted: e.target.checked }}])} - /> -  ·  - transact([{ todoFilter: { id: filters.get('id'), project }}])} - /> -
- ) -} - -const ProjectSelect = ({ value, onChange }) => { - const [projects] = useQuery({ - $find: 'project', - $where: { project: { name: '$any' } } - }) - return ( - <> - -   - - - ) -} - const TodoList = () => { const [filters] = useEntity({ identity: 'todoFilters' }) const [todos] = useQuery({ @@ -169,36 +117,42 @@ const TodoList = () => { }) return (
- {todos - .filter(todo => { + {todos.filter(todo => { if (!filters.get('showCompleted') && todo.get('isCompleted')) return false if (filters.get('project') && todo.get('project', 'id') !== filters.get('project')) return false + if (filters.get('owner') && todo.get('owner', 'id') !== filters.get('owner')) return false return true - }) - .sort((a, b) => a.get('createdAt') > b.get('createdAt') ? -1 : 1) - .map(todo => )} + }).sort((a, b) => a.get('createdAt') > b.get('createdAt') ? -1 : 1) + .map(todo => )}
) } -const Todo = ({ todo }) => ( -
-
- - -
+// PERFORMANCE: By accepting an `id` prop instead of a whole `todo` entity +// this component stays disconnected from the useQuery in the parent TodoList. +// useEntity creates a separate scope for every Todo so changes to TodoList +// or sibling Todos don't trigger unnecessary re-renders. +const Todo = React.memo(({ id }) => { + const [todo] = useEntity(id) + return (
- -  ·  - -  ·  - +
+ + +
+
+ +  ·  + +  ·  + +
+ + {todo.get('createdAt').toLocaleString()} +
- - {todo.get('createdAt').toLocaleString()} - -
-) + ) +}) const TodoCheck = ({ todo }) => { const [transact] = useTransact() @@ -207,12 +161,7 @@ const TodoCheck = ({ todo }) => { type="checkbox" style={{ width: 20, height: 20, cursor: 'pointer' }} checked={!!todo.get('isCompleted')} - onChange={e => transact([{ - todo: { - id: todo.get('id'), - isCompleted: e.target.checked - } - }])} + onChange={e => transact([{ todo: { id: todo.get('id'), isCompleted: e.target.checked } }])} /> ) } @@ -222,10 +171,10 @@ const TodoName = ({ todo }) => { return ( transact([{ todo: { id: todo.get('id'), name: e.target.value }}])} /> ) @@ -234,41 +183,24 @@ const TodoName = ({ todo }) => { const TodoProject = ({ todo }) => { const [transact] = useTransact() return ( - transact([{ todo: { id: todo.get('id'), 'project': projectId || null }}])} + transact([{ todo: { id: todo.get('id'), project }}])} /> ) } const TodoOwner = ({ todo }) => { const [transact] = useTransact() - const [users] = useQuery({ - $find: 'user', - $where: { user: { name: '$any' } } - }) return ( - <> - -   - - + transact([{ todo: { id: todo.get('id'), owner }}])} + /> ) } @@ -279,4 +211,57 @@ const TodoDelete = ({ todo }) => { Delete ) -} \ No newline at end of file +} + +const TodoFilters = () => { + const [filters] = useEntity({ identity: 'todoFilters' }) + const [transact] = useTransact() + return ( +
+ +  ·  + transact([{ todoFilter: { id: filters.get('id'), project }}])} + /> +  ·  + transact([{ todoFilter: { id: filters.get('id'), owner }}])} + /> +
+ ) +} + +const EntitySelect = React.memo(({ label, entityType, value, onChange }) => { + const [entities] = useQuery({ + $find: entityType, + $where: { [entityType]: { name: '$any' } } + }) + return ( + + ) +}) \ No newline at end of file diff --git a/package.json b/package.json index 8fba02e7..99d89571 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "test:js": "yarn build && jest js/tests", "test:js:dev": "yarn build:dev && jest js/tests", "test:cljs": "shadow-cljs compile test && node out/node-tests.js", + "test:cljs:watch": "shadow-cljs watch test-autorun", "test": "yarn test:cljs && yarn test:js", "test:dev": "yarn test:cljs && yarn test:js:dev", "report": "rm -rf dist && shadow-cljs run shadow.cljs.build-report npm report.html", diff --git a/shadow-cljs.edn b/shadow-cljs.edn index ab1ee824..9bec04f7 100644 --- a/shadow-cljs.edn +++ b/shadow-cljs.edn @@ -23,6 +23,10 @@ :output-to "out/node-tests.js" :ns-regexp "-test$" :autorun false} + :test-autorun {:target :node-test + :output-to "out/node-tests.js" + :ns-regexp "-test$" + :autorun true} :npm {:target :npm-module :output-dir "dist/js" :entries [homebase.react] diff --git a/src/homebase/js.cljs b/src/homebase/js.cljs index 3e5dbebb..a84d4948 100644 --- a/src/homebase/js.cljs +++ b/src/homebase/js.cljs @@ -26,13 +26,14 @@ (when-let [[_ verb _ key] (re-find bool-re string)] (if (= "is" verb) (str key "?") (str verb "-" key "?")))) -(defn js->key-not-memo [namespace string] +(defn js->key-not-memo [namespace key] (or - (get js->db-attr-overrides string) + (get js->db-attr-overrides key) (keyword (csk/->kebab-case namespace) - (csk/->kebab-case - (or (js->bool-key string) - string))))) + (str (if (= (subs key 0 1) "_") "_" "") + (csk/->kebab-case + (or (js->bool-key key) + key)))))) (def js->key (memoize js->key-not-memo)) (comment @@ -99,11 +100,6 @@ "unique" "identity"} "owner" {"type" "ref"}}}))) -(defn q-entity-array [query conn & args] - (->> (apply d/q query conn args) - (map (fn id->entity [[id]] (d/entity conn id))) - to-array)) - (defn js->datalog [data] (let [{find "$find" where "$where"} (js->clj data)] {:find [(symbol (str "?" find))] @@ -136,6 +132,13 @@ (object? query) (js->datalog query) :else nil)) +(defn nil->retract [tx] + (if-let [id (:db/id tx)] + (map (fn [[k v]] + [(if (nil? v) :db/retract :db/add) id k v]) + (dissoc tx :db/id)) + [tx])) + (defn js-get [entity name] (case name "id" (:db/id entity) @@ -143,64 +146,111 @@ "identity" (:db/ident entity) (let [ks (remove #{:db/id :db/ident} (keys entity)) ; This assumes that every entity only has keys of the same namespace once the :db keys are removed - nms (namespace (first ks)) - k (js->key nms name)] - (get entity k)))) + ; E.g. :db/id 1, :todo/name "", :todo/email "" + ; Not: :db/id 1, :todo/name "", :email/address "" + k (when (first ks) + (js->key (namespace (first ks)) name))] + (when k (get entity k))))) + +(defn entity-in-db? [entity] + (not (nil? (first (d/datoms (.-db entity) :eavt (:db/id entity)))))) + +(declare HBEntity) + +(defn Entity->HBEntity [v] + (if (= Entity (type v)) + (HBEntity. v nil) v)) + +(defn lookup-entity + ([entity attrs] (lookup-entity entity attrs false)) + ([entity attrs nil-attrs-if-not-in-db?] + (Entity->HBEntity + (reduce + (fn [acc attr] + (if-not acc nil + (let [attr (keywordize attr) + f (if (keyword? attr) get js-get)] + (cond + (and nil-attrs-if-not-in-db? + (or (= :db/id attr) (= "id" attr)) + (not (entity-in-db? acc))) nil + (set? acc) (f (first acc) attr) + acc (f acc attr) + :else nil)))) + entity attrs)))) (extend-type Entity Object - (get [this & keys] - (reduce - (fn [acc key] - (let [key (keywordize key) - f (if (keyword? key) get js-get)] - (cond - (set? acc) (f (first acc) (keywordize key)) - acc (f acc (keywordize key)) - :else nil))) - this keys))) + (get [entity & attrs] (lookup-entity entity attrs))) -(defn nil->retract [tx] - (if-let [id (:db/id tx)] - (map (fn [[k v]] - [(if (nil? v) :db/retract :db/add) id k v]) - (dissoc tx :db/id)) - [tx])) +(deftype HBEntity [^datascript.impl.entity/Entity entity _meta] + IMeta + (-meta [_] _meta) + IWithMeta + (-with-meta [_ new-meta] (HBEntity. entity new-meta)) + ILookup + (-lookup [_ attr] (lookup-entity entity [attr] true)) + (-lookup [_ attr not-found] (or (lookup-entity entity [attr] true) not-found)) + IAssociative + (-contains-key? [_ k] (not (nil? (lookup-entity entity [k] true)))) + Object + (get [this & attrs] + (let [v (lookup-entity entity attrs true)] + (when-let [f (:HBEntity/get (meta this))] + (f [this attrs v])) + v))) +(defn q-entity-array [query conn & args] + (->> (apply d/q query conn args) + (map (fn id->entity [[id]] (HBEntity. (d/entity conn id) nil))) + to-array)) + +(declare humanize-transact-error humanize-entity-error humanize-q-error) + +(defn transact! [conn txs] + (try + (d/transact! conn (mapcat (comp nil->retract js->tx) txs)) + (catch js/Error e + (throw (js/Error. (humanize-transact-error e)))))) + +(defn entity [conn lookup] + (try + (HBEntity. (d/entity @conn (js->entity-lookup lookup)) nil) + (catch js/Error e + (throw (js/Error. (humanize-entity-error e)))))) + +(defn q [query conn & args] + (try + (apply q-entity-array (js->query query) @conn (keywordize args)) + (catch js/Error e + (throw (js/Error. (humanize-q-error e)))))) (defn humanize-transact-error [error] (condp re-find (goog.object/get error "message") - #"\[object Object\] is not ISeqable" + #"\[object Object\] is not ISeqable" "Expected an array of transactions. \nFor example: transact([ {todo: {name: 1}}, {todo: {name: 2}} ]) " - + #"Unknown operation at \[nil nil nil nil\], expected" "Expected 'retractEntity'. \nFor example: transact([['retractEntity', id]]) " - + #"Can't use tempid in '\[:db\.fn/retractEntity" "Expected a numerical id. \nFor example: transact([['retractEntity', 123]]) " - + #"Expected number or lookup ref for entity id, got nil" "Expected a numerical id. \nFor example: transact([['retractEntity', 123]]) " (goog.object/get error "message"))) -(defn transact! [conn txs] - (try - (d/transact! conn (mapcat (comp nil->retract js->tx) txs)) - (catch js/Error e - (throw (js/Error. (humanize-transact-error e)))))) - - (defn humanize-entity-error [error] (condp re-find (goog.object/get error "message") #"Lookup ref attribute should be marked as :db/unique: \[:([\w-]+)/([\w-]+) ((?!\]).+)\]" @@ -209,13 +259,6 @@ "\n\nAdd this to your config: { schema: { " nmspc ": { " attr ": { unique: 'identity' }}}\n")) (goog.object/get error "message"))) -(defn entity [conn lookup] - (try - (d/entity @conn (js->entity-lookup lookup)) - (catch js/Error e - (throw (js/Error. (humanize-entity-error e)))))) - - (defn example-js-query ([] (example-js-query "item")) ([nmsp] (str "\n @@ -230,25 +273,19 @@ For example: query({ #"Query should be a vector or a map" (str "Expected query to be in the form of an object or datalog string." (example-js-query)) - + #"Query for unknown vars: \[\?\]" (str "Expected query to have a $find and a $where clause." (example-js-query)) - + ; TODO: revist when datalog strings are better supported since this error is directed at JS object queries only. #"Query for unknown vars: \[\?((?!\]).+)\]" :>> (fn [[_ var]] (str "Expected to see '" var "' in both the $find and $where clauses." (example-js-query var))) - + #"((?! is not ISeqable).+) is not ISeqable" :>> (fn [[_ v]] (str "Expected $where clause to be a nested object, not " v "." (example-js-query))) - (goog.object/get error "message"))) - -(defn q [query conn & args] - (try - (apply q-entity-array (js->query query) @conn (keywordize args)) - (catch js/Error e - (throw (js/Error. (humanize-q-error e)))))) \ No newline at end of file + (goog.object/get error "message"))) \ No newline at end of file diff --git a/src/homebase/js_test.cljs b/src/homebase/js_test.cljs index d189cbc5..d2cf9a17 100644 --- a/src/homebase/js_test.cljs +++ b/src/homebase/js_test.cljs @@ -4,32 +4,51 @@ [datascript.core :as d] [homebase.js :as hbjs])) -(deftest test-transact - (testing "should succeed" - (is (map? (hbjs/transact! (d/create-conn) - (clj->js [{"wat" {"thing" 1}} - ["retractEntity" 1]]))))) - (testing "should fail with humanized errors" - (is (thrown-with-msg? - js/Error - #"(?s)Expected an array of transactions.*For example:" - (hbjs/transact! (d/create-conn) (clj->js {})))) - (is (thrown-with-msg? - js/Error - #"(?s)Expected 'retractEntity'.*For example:" - (hbjs/transact! (d/create-conn) (clj->js [[]])))) - (is (thrown-with-msg? - js/Error - #"(?s)Expected 'retractEntity'.*For example:" - (hbjs/transact! (d/create-conn) (clj->js [["notAThing"]])))) - (is (thrown-with-msg? - js/Error - #"(?s)Expected a numerical id.*For example:" - (hbjs/transact! (d/create-conn) (clj->js [["retractEntity" "wat"]])))) - (is (thrown-with-msg? - js/Error - #"(?s)Expected a numerical id.*For example:" - (hbjs/transact! (d/create-conn) (clj->js [["retractEntity"]])))))) +(def test-conn + (d/conn-from-db + (d/init-db + #{(d/datom 3 :todo/project 2) + (d/datom 2 :project/name "abc")} + {:todo/project {:db/valueType :db.type/ref + :db/cardinality :db.cardinality/one}}))) + +(deftest test-entity-get + (testing "datascript entity get" + (is (thrown-with-msg? + js/Error + #"Cannot read property 'get' of null" + (.get (d/entity @(d/create-conn) nil) :db/id))) + (is (= 3 (:db/id (d/entity @(d/create-conn) 3)))) + (is (= 3 (.get (d/entity @(d/create-conn) 3) :db/id))) + (is (nil? (.get (d/entity @(d/create-conn) 3) :todo/name))) + (is (nil? (get-in (d/entity @(d/create-conn) 3) [:todo/project :db/id]))) + (is (= 2 (get-in (d/entity @test-conn 3) [:todo/project :db/id]))) + (is (some? (get-in (d/entity @test-conn 2) [:todo/_project]))) + (is (= 2 (.get (d/entity @test-conn 3) :todo/project :db/id))) + (is (= 3 (get (d/entity @test-conn 3) :db/id))) + (is (= 3 (.get (d/entity @test-conn 3) "id"))) + (is (= 2 (.get (d/entity @test-conn 3) "project" "id"))) + (is (thrown? js/Error (get (d/entity @test-conn 3) "id"))) + (is (thrown? js/Error (get-in (d/entity @test-conn 3) ["project" "id"]))) + (is (= "abc" (.get (d/entity @test-conn 3) "project" "name")))) + (testing "homebase entity get" + (is (some? (hbjs/entity (d/create-conn) 3))) + (is (= 3 (:db/id (hbjs/entity test-conn 3)))) + (is (= 3 (get (hbjs/entity test-conn 3) "id"))) + (is (= 3 (.get (hbjs/entity test-conn 3) "id"))) + (is (nil? (.get (hbjs/entity (d/create-conn) 3) "name"))) + (is (= "abc" (.get (hbjs/entity test-conn 2) "name"))) + (is (nil? (get-in (hbjs/entity (d/create-conn) 3) ["project" "id"]))) + (is (some? (.get (hbjs/entity test-conn 2) ":todo/_project"))) + (is (= "abc" (.get (hbjs/entity test-conn 3) "project" "name"))) + (is (nil? (:db/id (hbjs/entity (d/create-conn) 3)))) + (is (nil? (.get (hbjs/entity (d/create-conn) 3) "id"))) + (is (nil? (get (hbjs/entity (d/create-conn) 3) "id"))) + (is (nil? (get-in (hbjs/entity (d/create-conn) 3) ["id"]))) + (is (nil? (.get (hbjs/entity (d/create-conn) 3) "project" "id"))) + (is (= 2 (get-in (hbjs/entity test-conn 3) ["project" "id"]))) + (is (= "abc" (get-in (hbjs/entity test-conn 3) ["project" "name"]))))) + (deftest test-transact (testing "should succeed" @@ -60,7 +79,7 @@ (deftest test-entity (testing "should succeed" - (is (= 1 (:db/id (hbjs/entity (d/create-conn) (clj->js 1)))))) + (is (nil? (:db/id (hbjs/entity (d/create-conn) (clj->js 1)))))) (testing "should fail with humanized errors" (is (thrown-with-msg? js/Error diff --git a/src/homebase/react.cljs b/src/homebase/react.cljs index 15d6ca40..2cc51b7c 100644 --- a/src/homebase/react.cljs +++ b/src/homebase/react.cljs @@ -16,6 +16,20 @@ (second) (clojure.string/trim)))))))) +(defn changed? [entities cached-entities] + (if (not= (count entities) (count cached-entities)) + true + (reduce (fn [_ e] + (when (let [cached-e (get cached-entities (get e "id"))] + (if (nil? cached-e) + (reduced true) + (reduce (fn [_ [ks v]] + (when (not= v (get-in e ks)) + (reduced true))) + nil cached-e))) + (reduced true))) + nil entities))) + (defonce ^:export homebase-context (react/createContext)) (def base-schema @@ -34,25 +48,47 @@ (defn ^:export useEntity [lookup] (let [conn (react/useContext homebase-context) - run-lookup (fn [] (try-hook "useEntity" #(hbjs/entity conn lookup))) - [result setResult] (react/useState (run-lookup))] + cached-entities (react/useMemo #(atom {}) #js []) + run-lookup (react/useCallback + (fn run-lookup [] + (vary-meta (try-hook "useEntity" #(hbjs/entity conn lookup)) + merge {:HBEntity/get (fn [[e ks v]] (swap! cached-entities assoc-in [(get e "id") ks] v))})) + #js [lookup]) + [result setResult] (react/useState (run-lookup)) + listener (react/useCallback + (fn entity-listener [] + (let [result (run-lookup)] + (when (changed? #js [result] @cached-entities) + (setResult result)))) + #js [run-lookup])] (react/useEffect (fn use-entity-effect [] (let [key (rand)] - (d/listen! conn key #(setResult (run-lookup))) - (fn unmount-use-entity-effect [] (d/unlisten! conn key)))) + (d/listen! conn key listener) + #(d/unlisten! conn key))) #js [lookup]) [result])) (defn ^:export useQuery [query & args] (let [conn (react/useContext homebase-context) - run-query (fn [] (try-hook "useQuery" #(apply hbjs/q query conn args))) - [result setResult] (react/useState (run-query))] + cached-entities (react/useMemo #(atom {}) #js []) + run-query (react/useCallback + (fn run-query [] + (.map (try-hook "useQuery" #(apply hbjs/q query conn args)) + (fn [e] (vary-meta e merge {:HBEntity/get (fn [[e ks v]] (swap! cached-entities assoc-in [(get e "id") ks] v))})))) + #js [query args]) + [result setResult] (react/useState (run-query)) + listener (react/useCallback + (fn query-listener [] + (let [result (run-query)] + (when (changed? result @cached-entities) + (setResult result)))) + #js [run-query])] (react/useEffect (fn use-query-effect [] (let [key (rand)] - (d/listen! conn key #(setResult (run-query))) - (fn unmount-use-query-effect [] (d/unlisten! conn key)))) + (d/listen! conn key listener) + #(d/unlisten! conn key))) #js [query args]) [result])) diff --git a/src/js_gen/todo-example.js b/src/js_gen/todo-example.js index 69150f00..5b7620b1 100644 --- a/src/js_gen/todo-example.js +++ b/src/js_gen/todo-example.js @@ -50,8 +50,7 @@ const config = { // identity is a special unique attribute for user generated ids // E.g. todoFilters are settings that should be easy to lookup by their identity identity: 'todoFilters', - showCompleted: true, - project: 0 + showCompleted: true } }, { user: { @@ -122,58 +121,6 @@ const NewTodo = () => { }, "Create Todo")); }; -const TodoFilters = () => { - const [filters] = useEntity({ - identity: 'todoFilters' - }); - const [transact] = useTransact(); - return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("label", { - htmlFor: "show-completed" - }, "Show Completed?"), /*#__PURE__*/_react.default.createElement("input", { - type: "checkbox", - id: "show-completed", - checked: filters.get('showCompleted'), - onChange: e => transact([{ - todoFilter: { - id: filters.get('id'), - showCompleted: e.target.checked - } - }]) - }), "\xA0\xB7\xA0", /*#__PURE__*/_react.default.createElement(ProjectSelect, { - value: filters.get('project'), - onChange: project => transact([{ - todoFilter: { - id: filters.get('id'), - project - } - }]) - })); -}; - -const ProjectSelect = ({ - value, - onChange -}) => { - const [projects] = useQuery({ - $find: 'project', - $where: { - project: { - name: '$any' - } - } - }); - return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("label", null, "Project:"), "\xA0", /*#__PURE__*/_react.default.createElement("select", { - name: "projects", - value: value, - onChange: e => onChange && onChange(Number(e.target.value)) - }, /*#__PURE__*/_react.default.createElement("option", { - value: "0" - }), projects.map(project => /*#__PURE__*/_react.default.createElement("option", { - key: project.get('id'), - value: project.get('id') - }, project.get('name'))))); -}; - const TodoList = () => { const [filters] = useEntity({ identity: 'todoFilters' @@ -189,37 +136,45 @@ const TodoList = () => { return /*#__PURE__*/_react.default.createElement("div", null, todos.filter(todo => { if (!filters.get('showCompleted') && todo.get('isCompleted')) return false; if (filters.get('project') && todo.get('project', 'id') !== filters.get('project')) return false; + if (filters.get('owner') && todo.get('owner', 'id') !== filters.get('owner')) return false; return true; }).sort((a, b) => a.get('createdAt') > b.get('createdAt') ? -1 : 1).map(todo => /*#__PURE__*/_react.default.createElement(Todo, { key: todo.get('id'), - todo: todo + id: todo.get('id') }))); -}; +}; // PERFORMANCE: By accepting an `id` prop instead of a whole `todo` entity +// this component stays disconnected from the useQuery in the parent TodoList. +// useEntity creates a separate scope for every Todo so changes to TodoList +// or sibling Todos don't trigger unnecessary re-renders. -const Todo = ({ - todo -}) => /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", { - style: { - display: 'flex', - flexDirection: 'row', - alignItems: 'flex-end', - paddingTop: 20 - } -}, /*#__PURE__*/_react.default.createElement(TodoCheck, { - todo: todo -}), /*#__PURE__*/_react.default.createElement(TodoName, { - todo: todo -})), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(TodoProject, { - todo: todo -}), "\xA0\xB7\xA0", /*#__PURE__*/_react.default.createElement(TodoOwner, { - todo: todo -}), "\xA0\xB7\xA0", /*#__PURE__*/_react.default.createElement(TodoDelete, { - todo: todo -})), /*#__PURE__*/_react.default.createElement("small", { - style: { - color: 'grey' - } -}, todo.get('createdAt').toLocaleString())); + +const Todo = _react.default.memo(({ + id +}) => { + const [todo] = useEntity(id); + return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", { + style: { + display: 'flex', + flexDirection: 'row', + alignItems: 'flex-end', + paddingTop: 20 + } + }, /*#__PURE__*/_react.default.createElement(TodoCheck, { + todo: todo + }), /*#__PURE__*/_react.default.createElement(TodoName, { + todo: todo + })), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(TodoProject, { + todo: todo + }), "\xA0\xB7\xA0", /*#__PURE__*/_react.default.createElement(TodoOwner, { + todo: todo + }), "\xA0\xB7\xA0", /*#__PURE__*/_react.default.createElement(TodoDelete, { + todo: todo + })), /*#__PURE__*/_react.default.createElement("small", { + style: { + color: 'grey' + } + }, todo.get('createdAt').toLocaleString())); +}); const TodoCheck = ({ todo @@ -256,7 +211,7 @@ const TodoName = ({ textDecoration: 'line-through ' }) }, - value: todo.get('name'), + defaultValue: todo.get('name'), onChange: e => transact([{ todo: { id: todo.get('id'), @@ -270,12 +225,14 @@ const TodoProject = ({ todo }) => { const [transact] = useTransact(); - return /*#__PURE__*/_react.default.createElement(ProjectSelect, { - value: todo.get('project', 'id') || '', - onChange: projectId => transact([{ + return /*#__PURE__*/_react.default.createElement(EntitySelect, { + label: "Project", + entityType: "project", + value: todo.get('project', 'id'), + onChange: project => transact([{ todo: { id: todo.get('id'), - 'project': projectId || null + project } }]) }); @@ -285,29 +242,17 @@ const TodoOwner = ({ todo }) => { const [transact] = useTransact(); - const [users] = useQuery({ - $find: 'user', - $where: { - user: { - name: '$any' - } - } - }); - return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("label", null, "Owner:"), "\xA0", /*#__PURE__*/_react.default.createElement("select", { - name: "users", - value: todo.get('owner', 'id') || '', - onChange: e => transact([{ + return /*#__PURE__*/_react.default.createElement(EntitySelect, { + label: "Owner", + entityType: "user", + value: todo.get('owner', 'id'), + onChange: owner => transact([{ todo: { id: todo.get('id'), - owner: Number(e.target.value) || null + owner } }]) - }, /*#__PURE__*/_react.default.createElement("option", { - value: "" - }), users.map(user => /*#__PURE__*/_react.default.createElement("option", { - key: user.get('id'), - value: user.get('id') - }, user.get('name'))))); + }); }; const TodoDelete = ({ @@ -317,4 +262,68 @@ const TodoDelete = ({ return /*#__PURE__*/_react.default.createElement("button", { onClick: () => transact([['retractEntity', todo.get('id')]]) }, "Delete"); -}; \ No newline at end of file +}; + +const TodoFilters = () => { + const [filters] = useEntity({ + identity: 'todoFilters' + }); + const [transact] = useTransact(); + return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("label", null, "Show Completed?", /*#__PURE__*/_react.default.createElement("input", { + type: "checkbox", + checked: filters.get('showCompleted'), + onChange: e => transact([{ + todoFilter: { + id: filters.get('id'), + showCompleted: e.target.checked + } + }]) + })), "\xA0\xB7\xA0", /*#__PURE__*/_react.default.createElement(EntitySelect, { + label: "Project", + entityType: "project", + value: filters.get('project'), + onChange: project => transact([{ + todoFilter: { + id: filters.get('id'), + project + } + }]) + }), "\xA0\xB7\xA0", /*#__PURE__*/_react.default.createElement(EntitySelect, { + label: "Owner", + entityType: "user", + value: filters.get('owner'), + onChange: owner => transact([{ + todoFilter: { + id: filters.get('id'), + owner + } + }]) + })); +}; + +const EntitySelect = _react.default.memo(({ + label, + entityType, + value, + onChange +}) => { + const [entities] = useQuery({ + $find: entityType, + $where: { + [entityType]: { + name: '$any' + } + } + }); + return /*#__PURE__*/_react.default.createElement("label", null, label, ":\xA0", /*#__PURE__*/_react.default.createElement("select", { + name: entityType, + value: value || '', + onChange: e => onChange && onChange(Number(e.target.value) || null) + }, /*#__PURE__*/_react.default.createElement("option", { + key: "-", + value: "" + }), entities.map(entity => /*#__PURE__*/_react.default.createElement("option", { + key: entity.get('id'), + value: entity.get('id') + }, entity.get('name'))))); +}); \ No newline at end of file