diff --git a/.gitignore b/.gitignore index f8ed09bc..f46aecab 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ yarn.lock **/*.log test/repo-tests* **/bundle.js +package-lock.json # Logs logs diff --git a/.travis.yml b/.travis.yml index b19254bb..67f1dd1a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,9 @@ branches: - master - /^release\/.*$/ +services: + - xvfb + stages: - check - test @@ -13,8 +16,8 @@ stages: - release node_js: - - '12' - - '13' + - 'node' + - 'lts/*' os: - linux @@ -25,40 +28,55 @@ before_install: # prevents windows error: npm ERR! ... git-sh-setup: file not found - if [ "$TRAVIS_OS_NAME" = "windows" ]; then export PATH=/c/PROGRA~1/Git/usr/bin:/c/PROGRA~1/Git/mingw64/libexec/git-core:$PATH ; fi -script: npx nyc -s npm run test:node -- --bail +script: npx nyc -s npm run test -- -- -- -t node --bail after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov jobs: include: - stage: check + name: linting script: - - npx aegir commitlint --travis - - npm run depcheck - npm run lint + - stage: check + name: dep-check (production deps) + script: + - npm run depcheck -- $RUN_SINCE -- -- -p + + - stage: check + name: dep-check (unused deps) + script: + - npm run depcheck -- $RUN_SINCE -- -- -- --unused + - stage: test name: chrome addons: chrome: stable - script: npm run test:browser + script: npm run test -- -- -- -t browser - stage: test name: chrome webworker addons: chrome: stable - script: npm run test:webworker + script: npm run test -- -- -- -t webworker - stage: test name: firefox addons: firefox: latest - script: npm run test:browser -- -- -- --browsers FirefoxHeadless + script: npm run test -- -- -- -t browser --browsers FirefoxHeadless - stage: test name: firefox webworker addons: firefox: latest - script: npm run test:webworker -- -- -- --browsers FirefoxHeadless + script: npm run test -- -- -- -t webworker --browsers FirefoxHeadless + + - stage: test + name: electron main + addons: + firefox: latest + script: npm run test -- -- -- -t electron-main - stage: release # only run on changes to master diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index ae4fa273..00000000 --- a/package-lock.json +++ /dev/null @@ -1,6918 +0,0 @@ -{ - "name": "js-ipfs-unixfs", - "version": "1.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@evocateur/libnpmaccess": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz", - "integrity": "sha512-KSCAHwNWro0CF2ukxufCitT9K5LjL/KuMmNzSu8wuwN2rjyKHD8+cmOsiybK+W5hdnwc5M1SmRlVCaMHQo+3rg==", - "dev": true, - "requires": { - "@evocateur/npm-registry-fetch": "^4.0.0", - "aproba": "^2.0.0", - "figgy-pudding": "^3.5.1", - "get-stream": "^4.0.0", - "npm-package-arg": "^6.1.0" - }, - "dependencies": { - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - } - } - }, - "@evocateur/libnpmpublish": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@evocateur/libnpmpublish/-/libnpmpublish-1.2.2.tgz", - "integrity": "sha512-MJrrk9ct1FeY9zRlyeoyMieBjGDG9ihyyD9/Ft6MMrTxql9NyoEx2hw9casTIP4CdqEVu+3nQ2nXxoJ8RCXyFg==", - "dev": true, - "requires": { - "@evocateur/npm-registry-fetch": "^4.0.0", - "aproba": "^2.0.0", - "figgy-pudding": "^3.5.1", - "get-stream": "^4.0.0", - "lodash.clonedeep": "^4.5.0", - "normalize-package-data": "^2.4.0", - "npm-package-arg": "^6.1.0", - "semver": "^5.5.1", - "ssri": "^6.0.1" - }, - "dependencies": { - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "@evocateur/npm-registry-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@evocateur/npm-registry-fetch/-/npm-registry-fetch-4.0.0.tgz", - "integrity": "sha512-k1WGfKRQyhJpIr+P17O5vLIo2ko1PFLKwoetatdduUSt/aQ4J2sJrJwwatdI5Z3SiYk/mRH9S3JpdmMFd/IK4g==", - "dev": true, - "requires": { - "JSONStream": "^1.3.4", - "bluebird": "^3.5.1", - "figgy-pudding": "^3.4.1", - "lru-cache": "^5.1.1", - "make-fetch-happen": "^5.0.0", - "npm-package-arg": "^6.1.0", - "safe-buffer": "^5.1.2" - } - }, - "@evocateur/pacote": { - "version": "9.6.5", - "resolved": "https://registry.npmjs.org/@evocateur/pacote/-/pacote-9.6.5.tgz", - "integrity": "sha512-EI552lf0aG2nOV8NnZpTxNo2PcXKPmDbF9K8eCBFQdIZwHNGN/mi815fxtmUMa2wTa1yndotICIDt/V0vpEx2w==", - "dev": true, - "requires": { - "@evocateur/npm-registry-fetch": "^4.0.0", - "bluebird": "^3.5.3", - "cacache": "^12.0.3", - "chownr": "^1.1.2", - "figgy-pudding": "^3.5.1", - "get-stream": "^4.1.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^5.1.1", - "make-fetch-happen": "^5.0.0", - "minimatch": "^3.0.4", - "minipass": "^2.3.5", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "normalize-package-data": "^2.5.0", - "npm-package-arg": "^6.1.0", - "npm-packlist": "^1.4.4", - "npm-pick-manifest": "^3.0.0", - "osenv": "^0.1.5", - "promise-inflight": "^1.0.1", - "promise-retry": "^1.1.1", - "protoduck": "^5.0.1", - "rimraf": "^2.6.3", - "safe-buffer": "^5.2.0", - "semver": "^5.7.0", - "ssri": "^6.0.1", - "tar": "^4.4.10", - "unique-filename": "^1.1.1", - "which": "^1.3.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "@lerna/add": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/add/-/add-3.21.0.tgz", - "integrity": "sha512-vhUXXF6SpufBE1EkNEXwz1VLW03f177G9uMOFMQkp6OJ30/PWg4Ekifuz9/3YfgB2/GH8Tu4Lk3O51P2Hskg/A==", - "dev": true, - "requires": { - "@evocateur/pacote": "^9.6.3", - "@lerna/bootstrap": "3.21.0", - "@lerna/command": "3.21.0", - "@lerna/filter-options": "3.20.0", - "@lerna/npm-conf": "3.16.0", - "@lerna/validation-error": "3.13.0", - "dedent": "^0.7.0", - "npm-package-arg": "^6.1.0", - "p-map": "^2.1.0", - "semver": "^6.2.0" - } - }, - "@lerna/bootstrap": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/bootstrap/-/bootstrap-3.21.0.tgz", - "integrity": "sha512-mtNHlXpmvJn6JTu0KcuTTPl2jLsDNud0QacV/h++qsaKbhAaJr/FElNZ5s7MwZFUM3XaDmvWzHKaszeBMHIbBw==", - "dev": true, - "requires": { - "@lerna/command": "3.21.0", - "@lerna/filter-options": "3.20.0", - "@lerna/has-npm-version": "3.16.5", - "@lerna/npm-install": "3.16.5", - "@lerna/package-graph": "3.18.5", - "@lerna/pulse-till-done": "3.13.0", - "@lerna/rimraf-dir": "3.16.5", - "@lerna/run-lifecycle": "3.16.2", - "@lerna/run-topologically": "3.18.5", - "@lerna/symlink-binary": "3.17.0", - "@lerna/symlink-dependencies": "3.17.0", - "@lerna/validation-error": "3.13.0", - "dedent": "^0.7.0", - "get-port": "^4.2.0", - "multimatch": "^3.0.0", - "npm-package-arg": "^6.1.0", - "npmlog": "^4.1.2", - "p-finally": "^1.0.0", - "p-map": "^2.1.0", - "p-map-series": "^1.0.0", - "p-waterfall": "^1.0.0", - "read-package-tree": "^5.1.6", - "semver": "^6.2.0" - } - }, - "@lerna/changed": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/changed/-/changed-3.21.0.tgz", - "integrity": "sha512-hzqoyf8MSHVjZp0gfJ7G8jaz+++mgXYiNs9iViQGA8JlN/dnWLI5sWDptEH3/B30Izo+fdVz0S0s7ydVE3pWIw==", - "dev": true, - "requires": { - "@lerna/collect-updates": "3.20.0", - "@lerna/command": "3.21.0", - "@lerna/listable": "3.18.5", - "@lerna/output": "3.13.0" - } - }, - "@lerna/check-working-tree": { - "version": "3.16.5", - "resolved": "https://registry.npmjs.org/@lerna/check-working-tree/-/check-working-tree-3.16.5.tgz", - "integrity": "sha512-xWjVBcuhvB8+UmCSb5tKVLB5OuzSpw96WEhS2uz6hkWVa/Euh1A0/HJwn2cemyK47wUrCQXtczBUiqnq9yX5VQ==", - "dev": true, - "requires": { - "@lerna/collect-uncommitted": "3.16.5", - "@lerna/describe-ref": "3.16.5", - "@lerna/validation-error": "3.13.0" - } - }, - "@lerna/child-process": { - "version": "3.16.5", - "resolved": "https://registry.npmjs.org/@lerna/child-process/-/child-process-3.16.5.tgz", - "integrity": "sha512-vdcI7mzei9ERRV4oO8Y1LHBZ3A5+ampRKg1wq5nutLsUA4mEBN6H7JqjWOMY9xZemv6+kATm2ofjJ3lW5TszQg==", - "dev": true, - "requires": { - "chalk": "^2.3.1", - "execa": "^1.0.0", - "strong-log-transformer": "^2.0.0" - } - }, - "@lerna/clean": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/clean/-/clean-3.21.0.tgz", - "integrity": "sha512-b/L9l+MDgE/7oGbrav6rG8RTQvRiZLO1zTcG17zgJAAuhlsPxJExMlh2DFwJEVi2les70vMhHfST3Ue1IMMjpg==", - "dev": true, - "requires": { - "@lerna/command": "3.21.0", - "@lerna/filter-options": "3.20.0", - "@lerna/prompt": "3.18.5", - "@lerna/pulse-till-done": "3.13.0", - "@lerna/rimraf-dir": "3.16.5", - "p-map": "^2.1.0", - "p-map-series": "^1.0.0", - "p-waterfall": "^1.0.0" - } - }, - "@lerna/cli": { - "version": "3.18.5", - "resolved": "https://registry.npmjs.org/@lerna/cli/-/cli-3.18.5.tgz", - "integrity": "sha512-erkbxkj9jfc89vVs/jBLY/fM0I80oLmJkFUV3Q3wk9J3miYhP14zgVEBsPZY68IZlEjT6T3Xlq2xO1AVaatHsA==", - "dev": true, - "requires": { - "@lerna/global-options": "3.13.0", - "dedent": "^0.7.0", - "npmlog": "^4.1.2", - "yargs": "^14.2.2" - } - }, - "@lerna/collect-uncommitted": { - "version": "3.16.5", - "resolved": "https://registry.npmjs.org/@lerna/collect-uncommitted/-/collect-uncommitted-3.16.5.tgz", - "integrity": "sha512-ZgqnGwpDZiWyzIQVZtQaj9tRizsL4dUOhuOStWgTAw1EMe47cvAY2kL709DzxFhjr6JpJSjXV5rZEAeU3VE0Hg==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "chalk": "^2.3.1", - "figgy-pudding": "^3.5.1", - "npmlog": "^4.1.2" - } - }, - "@lerna/collect-updates": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@lerna/collect-updates/-/collect-updates-3.20.0.tgz", - "integrity": "sha512-qBTVT5g4fupVhBFuY4nI/3FSJtQVcDh7/gEPOpRxoXB/yCSnT38MFHXWl+y4einLciCjt/+0x6/4AG80fjay2Q==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "@lerna/describe-ref": "3.16.5", - "minimatch": "^3.0.4", - "npmlog": "^4.1.2", - "slash": "^2.0.0" - } - }, - "@lerna/command": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/command/-/command-3.21.0.tgz", - "integrity": "sha512-T2bu6R8R3KkH5YoCKdutKv123iUgUbW8efVjdGCDnCMthAQzoentOJfDeodBwn0P2OqCl3ohsiNVtSn9h78fyQ==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "@lerna/package-graph": "3.18.5", - "@lerna/project": "3.21.0", - "@lerna/validation-error": "3.13.0", - "@lerna/write-log-file": "3.13.0", - "clone-deep": "^4.0.1", - "dedent": "^0.7.0", - "execa": "^1.0.0", - "is-ci": "^2.0.0", - "npmlog": "^4.1.2" - } - }, - "@lerna/conventional-commits": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@lerna/conventional-commits/-/conventional-commits-3.22.0.tgz", - "integrity": "sha512-z4ZZk1e8Mhz7+IS8NxHr64wyklHctCJyWpJKEZZPJiLFJ8yKto/x38O80R10pIzC0rr8Sy/OsjSH4bl0TbbgqA==", - "dev": true, - "requires": { - "@lerna/validation-error": "3.13.0", - "conventional-changelog-angular": "^5.0.3", - "conventional-changelog-core": "^3.1.6", - "conventional-recommended-bump": "^5.0.0", - "fs-extra": "^8.1.0", - "get-stream": "^4.0.0", - "lodash.template": "^4.5.0", - "npm-package-arg": "^6.1.0", - "npmlog": "^4.1.2", - "pify": "^4.0.1", - "semver": "^6.2.0" - } - }, - "@lerna/create": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@lerna/create/-/create-3.22.0.tgz", - "integrity": "sha512-MdiQQzCcB4E9fBF1TyMOaAEz9lUjIHp1Ju9H7f3lXze5JK6Fl5NYkouAvsLgY6YSIhXMY8AHW2zzXeBDY4yWkw==", - "dev": true, - "requires": { - "@evocateur/pacote": "^9.6.3", - "@lerna/child-process": "3.16.5", - "@lerna/command": "3.21.0", - "@lerna/npm-conf": "3.16.0", - "@lerna/validation-error": "3.13.0", - "camelcase": "^5.0.0", - "dedent": "^0.7.0", - "fs-extra": "^8.1.0", - "globby": "^9.2.0", - "init-package-json": "^1.10.3", - "npm-package-arg": "^6.1.0", - "p-reduce": "^1.0.0", - "pify": "^4.0.1", - "semver": "^6.2.0", - "slash": "^2.0.0", - "validate-npm-package-license": "^3.0.3", - "validate-npm-package-name": "^3.0.0", - "whatwg-url": "^7.0.0" - } - }, - "@lerna/create-symlink": { - "version": "3.16.2", - "resolved": "https://registry.npmjs.org/@lerna/create-symlink/-/create-symlink-3.16.2.tgz", - "integrity": "sha512-pzXIJp6av15P325sgiIRpsPXLFmkisLhMBCy4764d+7yjf2bzrJ4gkWVMhsv4AdF0NN3OyZ5jjzzTtLNqfR+Jw==", - "dev": true, - "requires": { - "@zkochan/cmd-shim": "^3.1.0", - "fs-extra": "^8.1.0", - "npmlog": "^4.1.2" - } - }, - "@lerna/describe-ref": { - "version": "3.16.5", - "resolved": "https://registry.npmjs.org/@lerna/describe-ref/-/describe-ref-3.16.5.tgz", - "integrity": "sha512-c01+4gUF0saOOtDBzbLMFOTJDHTKbDFNErEY6q6i9QaXuzy9LNN62z+Hw4acAAZuJQhrVWncVathcmkkjvSVGw==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "npmlog": "^4.1.2" - } - }, - "@lerna/diff": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/diff/-/diff-3.21.0.tgz", - "integrity": "sha512-5viTR33QV3S7O+bjruo1SaR40m7F2aUHJaDAC7fL9Ca6xji+aw1KFkpCtVlISS0G8vikUREGMJh+c/VMSc8Usw==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "@lerna/command": "3.21.0", - "@lerna/validation-error": "3.13.0", - "npmlog": "^4.1.2" - } - }, - "@lerna/exec": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/exec/-/exec-3.21.0.tgz", - "integrity": "sha512-iLvDBrIE6rpdd4GIKTY9mkXyhwsJ2RvQdB9ZU+/NhR3okXfqKc6py/24tV111jqpXTtZUW6HNydT4dMao2hi1Q==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "@lerna/command": "3.21.0", - "@lerna/filter-options": "3.20.0", - "@lerna/profiler": "3.20.0", - "@lerna/run-topologically": "3.18.5", - "@lerna/validation-error": "3.13.0", - "p-map": "^2.1.0" - } - }, - "@lerna/filter-options": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@lerna/filter-options/-/filter-options-3.20.0.tgz", - "integrity": "sha512-bmcHtvxn7SIl/R9gpiNMVG7yjx7WyT0HSGw34YVZ9B+3xF/83N3r5Rgtjh4hheLZ+Q91Or0Jyu5O3Nr+AwZe2g==", - "dev": true, - "requires": { - "@lerna/collect-updates": "3.20.0", - "@lerna/filter-packages": "3.18.0", - "dedent": "^0.7.0", - "figgy-pudding": "^3.5.1", - "npmlog": "^4.1.2" - } - }, - "@lerna/filter-packages": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/@lerna/filter-packages/-/filter-packages-3.18.0.tgz", - "integrity": "sha512-6/0pMM04bCHNATIOkouuYmPg6KH3VkPCIgTfQmdkPJTullERyEQfNUKikrefjxo1vHOoCACDpy65JYyKiAbdwQ==", - "dev": true, - "requires": { - "@lerna/validation-error": "3.13.0", - "multimatch": "^3.0.0", - "npmlog": "^4.1.2" - } - }, - "@lerna/get-npm-exec-opts": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-3.13.0.tgz", - "integrity": "sha512-Y0xWL0rg3boVyJk6An/vurKzubyJKtrxYv2sj4bB8Mc5zZ3tqtv0ccbOkmkXKqbzvNNF7VeUt1OJ3DRgtC/QZw==", - "dev": true, - "requires": { - "npmlog": "^4.1.2" - } - }, - "@lerna/get-packed": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/@lerna/get-packed/-/get-packed-3.16.0.tgz", - "integrity": "sha512-AjsFiaJzo1GCPnJUJZiTW6J1EihrPkc2y3nMu6m3uWFxoleklsSCyImumzVZJssxMi3CPpztj8LmADLedl9kXw==", - "dev": true, - "requires": { - "fs-extra": "^8.1.0", - "ssri": "^6.0.1", - "tar": "^4.4.8" - } - }, - "@lerna/github-client": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@lerna/github-client/-/github-client-3.22.0.tgz", - "integrity": "sha512-O/GwPW+Gzr3Eb5bk+nTzTJ3uv+jh5jGho9BOqKlajXaOkMYGBELEAqV5+uARNGWZFvYAiF4PgqHb6aCUu7XdXg==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "@octokit/plugin-enterprise-rest": "^6.0.1", - "@octokit/rest": "^16.28.4", - "git-url-parse": "^11.1.2", - "npmlog": "^4.1.2" - } - }, - "@lerna/gitlab-client": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/@lerna/gitlab-client/-/gitlab-client-3.15.0.tgz", - "integrity": "sha512-OsBvRSejHXUBMgwWQqNoioB8sgzL/Pf1pOUhHKtkiMl6aAWjklaaq5HPMvTIsZPfS6DJ9L5OK2GGZuooP/5c8Q==", - "dev": true, - "requires": { - "node-fetch": "^2.5.0", - "npmlog": "^4.1.2", - "whatwg-url": "^7.0.0" - } - }, - "@lerna/global-options": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@lerna/global-options/-/global-options-3.13.0.tgz", - "integrity": "sha512-SlZvh1gVRRzYLVluz9fryY1nJpZ0FHDGB66U9tFfvnnxmueckRQxLopn3tXj3NU1kc3QANT2I5BsQkOqZ4TEFQ==", - "dev": true - }, - "@lerna/has-npm-version": { - "version": "3.16.5", - "resolved": "https://registry.npmjs.org/@lerna/has-npm-version/-/has-npm-version-3.16.5.tgz", - "integrity": "sha512-WL7LycR9bkftyqbYop5rEGJ9sRFIV55tSGmbN1HLrF9idwOCD7CLrT64t235t3t4O5gehDnwKI5h2U3oxTrF8Q==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "semver": "^6.2.0" - } - }, - "@lerna/import": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@lerna/import/-/import-3.22.0.tgz", - "integrity": "sha512-uWOlexasM5XR6tXi4YehODtH9Y3OZrFht3mGUFFT3OIl2s+V85xIGFfqFGMTipMPAGb2oF1UBLL48kR43hRsOg==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "@lerna/command": "3.21.0", - "@lerna/prompt": "3.18.5", - "@lerna/pulse-till-done": "3.13.0", - "@lerna/validation-error": "3.13.0", - "dedent": "^0.7.0", - "fs-extra": "^8.1.0", - "p-map-series": "^1.0.0" - } - }, - "@lerna/info": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/info/-/info-3.21.0.tgz", - "integrity": "sha512-0XDqGYVBgWxUquFaIptW2bYSIu6jOs1BtkvRTWDDhw4zyEdp6q4eaMvqdSap1CG+7wM5jeLCi6z94wS0AuiuwA==", - "dev": true, - "requires": { - "@lerna/command": "3.21.0", - "@lerna/output": "3.13.0", - "envinfo": "^7.3.1" - } - }, - "@lerna/init": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/init/-/init-3.21.0.tgz", - "integrity": "sha512-6CM0z+EFUkFfurwdJCR+LQQF6MqHbYDCBPyhu/d086LRf58GtYZYj49J8mKG9ktayp/TOIxL/pKKjgLD8QBPOg==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "@lerna/command": "3.21.0", - "fs-extra": "^8.1.0", - "p-map": "^2.1.0", - "write-json-file": "^3.2.0" - } - }, - "@lerna/link": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/link/-/link-3.21.0.tgz", - "integrity": "sha512-tGu9GxrX7Ivs+Wl3w1+jrLi1nQ36kNI32dcOssij6bg0oZ2M2MDEFI9UF2gmoypTaN9uO5TSsjCFS7aR79HbdQ==", - "dev": true, - "requires": { - "@lerna/command": "3.21.0", - "@lerna/package-graph": "3.18.5", - "@lerna/symlink-dependencies": "3.17.0", - "p-map": "^2.1.0", - "slash": "^2.0.0" - } - }, - "@lerna/list": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/list/-/list-3.21.0.tgz", - "integrity": "sha512-KehRjE83B1VaAbRRkRy6jLX1Cin8ltsrQ7FHf2bhwhRHK0S54YuA6LOoBnY/NtA8bHDX/Z+G5sMY78X30NS9tg==", - "dev": true, - "requires": { - "@lerna/command": "3.21.0", - "@lerna/filter-options": "3.20.0", - "@lerna/listable": "3.18.5", - "@lerna/output": "3.13.0" - } - }, - "@lerna/listable": { - "version": "3.18.5", - "resolved": "https://registry.npmjs.org/@lerna/listable/-/listable-3.18.5.tgz", - "integrity": "sha512-Sdr3pVyaEv5A7ZkGGYR7zN+tTl2iDcinryBPvtuv20VJrXBE8wYcOks1edBTcOWsPjCE/rMP4bo1pseyk3UTsg==", - "dev": true, - "requires": { - "@lerna/query-graph": "3.18.5", - "chalk": "^2.3.1", - "columnify": "^1.5.4" - } - }, - "@lerna/log-packed": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/@lerna/log-packed/-/log-packed-3.16.0.tgz", - "integrity": "sha512-Fp+McSNBV/P2mnLUYTaSlG8GSmpXM7krKWcllqElGxvAqv6chk2K3c2k80MeVB4WvJ9tRjUUf+i7HUTiQ9/ckQ==", - "dev": true, - "requires": { - "byte-size": "^5.0.1", - "columnify": "^1.5.4", - "has-unicode": "^2.0.1", - "npmlog": "^4.1.2" - } - }, - "@lerna/npm-conf": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/@lerna/npm-conf/-/npm-conf-3.16.0.tgz", - "integrity": "sha512-HbO3DUrTkCAn2iQ9+FF/eisDpWY5POQAOF1m7q//CZjdC2HSW3UYbKEGsSisFxSfaF9Z4jtrV+F/wX6qWs3CuA==", - "dev": true, - "requires": { - "config-chain": "^1.1.11", - "pify": "^4.0.1" - } - }, - "@lerna/npm-dist-tag": { - "version": "3.18.5", - "resolved": "https://registry.npmjs.org/@lerna/npm-dist-tag/-/npm-dist-tag-3.18.5.tgz", - "integrity": "sha512-xw0HDoIG6HreVsJND9/dGls1c+lf6vhu7yJoo56Sz5bvncTloYGLUppIfDHQr4ZvmPCK8rsh0euCVh2giPxzKQ==", - "dev": true, - "requires": { - "@evocateur/npm-registry-fetch": "^4.0.0", - "@lerna/otplease": "3.18.5", - "figgy-pudding": "^3.5.1", - "npm-package-arg": "^6.1.0", - "npmlog": "^4.1.2" - } - }, - "@lerna/npm-install": { - "version": "3.16.5", - "resolved": "https://registry.npmjs.org/@lerna/npm-install/-/npm-install-3.16.5.tgz", - "integrity": "sha512-hfiKk8Eku6rB9uApqsalHHTHY+mOrrHeWEs+gtg7+meQZMTS3kzv4oVp5cBZigndQr3knTLjwthT/FX4KvseFg==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "@lerna/get-npm-exec-opts": "3.13.0", - "fs-extra": "^8.1.0", - "npm-package-arg": "^6.1.0", - "npmlog": "^4.1.2", - "signal-exit": "^3.0.2", - "write-pkg": "^3.1.0" - } - }, - "@lerna/npm-publish": { - "version": "3.18.5", - "resolved": "https://registry.npmjs.org/@lerna/npm-publish/-/npm-publish-3.18.5.tgz", - "integrity": "sha512-3etLT9+2L8JAx5F8uf7qp6iAtOLSMj+ZYWY6oUgozPi/uLqU0/gsMsEXh3F0+YVW33q0M61RpduBoAlOOZnaTg==", - "dev": true, - "requires": { - "@evocateur/libnpmpublish": "^1.2.2", - "@lerna/otplease": "3.18.5", - "@lerna/run-lifecycle": "3.16.2", - "figgy-pudding": "^3.5.1", - "fs-extra": "^8.1.0", - "npm-package-arg": "^6.1.0", - "npmlog": "^4.1.2", - "pify": "^4.0.1", - "read-package-json": "^2.0.13" - } - }, - "@lerna/npm-run-script": { - "version": "3.16.5", - "resolved": "https://registry.npmjs.org/@lerna/npm-run-script/-/npm-run-script-3.16.5.tgz", - "integrity": "sha512-1asRi+LjmVn3pMjEdpqKJZFT/3ZNpb+VVeJMwrJaV/3DivdNg7XlPK9LTrORuKU4PSvhdEZvJmSlxCKyDpiXsQ==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "@lerna/get-npm-exec-opts": "3.13.0", - "npmlog": "^4.1.2" - } - }, - "@lerna/otplease": { - "version": "3.18.5", - "resolved": "https://registry.npmjs.org/@lerna/otplease/-/otplease-3.18.5.tgz", - "integrity": "sha512-S+SldXAbcXTEDhzdxYLU0ZBKuYyURP/ND2/dK6IpKgLxQYh/z4ScljPDMyKymmEvgiEJmBsPZAAPfmNPEzxjog==", - "dev": true, - "requires": { - "@lerna/prompt": "3.18.5", - "figgy-pudding": "^3.5.1" - } - }, - "@lerna/output": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@lerna/output/-/output-3.13.0.tgz", - "integrity": "sha512-7ZnQ9nvUDu/WD+bNsypmPG5MwZBwu86iRoiW6C1WBuXXDxM5cnIAC1m2WxHeFnjyMrYlRXM9PzOQ9VDD+C15Rg==", - "dev": true, - "requires": { - "npmlog": "^4.1.2" - } - }, - "@lerna/pack-directory": { - "version": "3.16.4", - "resolved": "https://registry.npmjs.org/@lerna/pack-directory/-/pack-directory-3.16.4.tgz", - "integrity": "sha512-uxSF0HZeGyKaaVHz5FroDY9A5NDDiCibrbYR6+khmrhZtY0Bgn6hWq8Gswl9iIlymA+VzCbshWIMX4o2O8C8ng==", - "dev": true, - "requires": { - "@lerna/get-packed": "3.16.0", - "@lerna/package": "3.16.0", - "@lerna/run-lifecycle": "3.16.2", - "figgy-pudding": "^3.5.1", - "npm-packlist": "^1.4.4", - "npmlog": "^4.1.2", - "tar": "^4.4.10", - "temp-write": "^3.4.0" - } - }, - "@lerna/package": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/@lerna/package/-/package-3.16.0.tgz", - "integrity": "sha512-2lHBWpaxcBoiNVbtyLtPUuTYEaB/Z+eEqRS9duxpZs6D+mTTZMNy6/5vpEVSCBmzvdYpyqhqaYjjSLvjjr5Riw==", - "dev": true, - "requires": { - "load-json-file": "^5.3.0", - "npm-package-arg": "^6.1.0", - "write-pkg": "^3.1.0" - } - }, - "@lerna/package-graph": { - "version": "3.18.5", - "resolved": "https://registry.npmjs.org/@lerna/package-graph/-/package-graph-3.18.5.tgz", - "integrity": "sha512-8QDrR9T+dBegjeLr+n9WZTVxUYUhIUjUgZ0gvNxUBN8S1WB9r6H5Yk56/MVaB64tA3oGAN9IIxX6w0WvTfFudA==", - "dev": true, - "requires": { - "@lerna/prerelease-id-from-version": "3.16.0", - "@lerna/validation-error": "3.13.0", - "npm-package-arg": "^6.1.0", - "npmlog": "^4.1.2", - "semver": "^6.2.0" - } - }, - "@lerna/prerelease-id-from-version": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-3.16.0.tgz", - "integrity": "sha512-qZyeUyrE59uOK8rKdGn7jQz+9uOpAaF/3hbslJVFL1NqF9ELDTqjCPXivuejMX/lN4OgD6BugTO4cR7UTq/sZA==", - "dev": true, - "requires": { - "semver": "^6.2.0" - } - }, - "@lerna/profiler": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@lerna/profiler/-/profiler-3.20.0.tgz", - "integrity": "sha512-bh8hKxAlm6yu8WEOvbLENm42i2v9SsR4WbrCWSbsmOElx3foRnMlYk7NkGECa+U5c3K4C6GeBbwgqs54PP7Ljg==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1", - "fs-extra": "^8.1.0", - "npmlog": "^4.1.2", - "upath": "^1.2.0" - } - }, - "@lerna/project": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/project/-/project-3.21.0.tgz", - "integrity": "sha512-xT1mrpET2BF11CY32uypV2GPtPVm6Hgtha7D81GQP9iAitk9EccrdNjYGt5UBYASl4CIDXBRxwmTTVGfrCx82A==", - "dev": true, - "requires": { - "@lerna/package": "3.16.0", - "@lerna/validation-error": "3.13.0", - "cosmiconfig": "^5.1.0", - "dedent": "^0.7.0", - "dot-prop": "^4.2.0", - "glob-parent": "^5.0.0", - "globby": "^9.2.0", - "load-json-file": "^5.3.0", - "npmlog": "^4.1.2", - "p-map": "^2.1.0", - "resolve-from": "^4.0.0", - "write-json-file": "^3.2.0" - } - }, - "@lerna/prompt": { - "version": "3.18.5", - "resolved": "https://registry.npmjs.org/@lerna/prompt/-/prompt-3.18.5.tgz", - "integrity": "sha512-rkKj4nm1twSbBEb69+Em/2jAERK8htUuV8/xSjN0NPC+6UjzAwY52/x9n5cfmpa9lyKf/uItp7chCI7eDmNTKQ==", - "dev": true, - "requires": { - "inquirer": "^6.2.0", - "npmlog": "^4.1.2" - } - }, - "@lerna/publish": { - "version": "3.22.1", - "resolved": "https://registry.npmjs.org/@lerna/publish/-/publish-3.22.1.tgz", - "integrity": "sha512-PG9CM9HUYDreb1FbJwFg90TCBQooGjj+n/pb3gw/eH5mEDq0p8wKdLFe0qkiqUkm/Ub5C8DbVFertIo0Vd0zcw==", - "dev": true, - "requires": { - "@evocateur/libnpmaccess": "^3.1.2", - "@evocateur/npm-registry-fetch": "^4.0.0", - "@evocateur/pacote": "^9.6.3", - "@lerna/check-working-tree": "3.16.5", - "@lerna/child-process": "3.16.5", - "@lerna/collect-updates": "3.20.0", - "@lerna/command": "3.21.0", - "@lerna/describe-ref": "3.16.5", - "@lerna/log-packed": "3.16.0", - "@lerna/npm-conf": "3.16.0", - "@lerna/npm-dist-tag": "3.18.5", - "@lerna/npm-publish": "3.18.5", - "@lerna/otplease": "3.18.5", - "@lerna/output": "3.13.0", - "@lerna/pack-directory": "3.16.4", - "@lerna/prerelease-id-from-version": "3.16.0", - "@lerna/prompt": "3.18.5", - "@lerna/pulse-till-done": "3.13.0", - "@lerna/run-lifecycle": "3.16.2", - "@lerna/run-topologically": "3.18.5", - "@lerna/validation-error": "3.13.0", - "@lerna/version": "3.22.1", - "figgy-pudding": "^3.5.1", - "fs-extra": "^8.1.0", - "npm-package-arg": "^6.1.0", - "npmlog": "^4.1.2", - "p-finally": "^1.0.0", - "p-map": "^2.1.0", - "p-pipe": "^1.2.0", - "semver": "^6.2.0" - } - }, - "@lerna/pulse-till-done": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@lerna/pulse-till-done/-/pulse-till-done-3.13.0.tgz", - "integrity": "sha512-1SOHpy7ZNTPulzIbargrgaJX387csN7cF1cLOGZiJQA6VqnS5eWs2CIrG8i8wmaUavj2QlQ5oEbRMVVXSsGrzA==", - "dev": true, - "requires": { - "npmlog": "^4.1.2" - } - }, - "@lerna/query-graph": { - "version": "3.18.5", - "resolved": "https://registry.npmjs.org/@lerna/query-graph/-/query-graph-3.18.5.tgz", - "integrity": "sha512-50Lf4uuMpMWvJ306be3oQDHrWV42nai9gbIVByPBYJuVW8dT8O8pA3EzitNYBUdLL9/qEVbrR0ry1HD7EXwtRA==", - "dev": true, - "requires": { - "@lerna/package-graph": "3.18.5", - "figgy-pudding": "^3.5.1" - } - }, - "@lerna/resolve-symlink": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/@lerna/resolve-symlink/-/resolve-symlink-3.16.0.tgz", - "integrity": "sha512-Ibj5e7njVHNJ/NOqT4HlEgPFPtPLWsO7iu59AM5bJDcAJcR96mLZ7KGVIsS2tvaO7akMEJvt2P+ErwCdloG3jQ==", - "dev": true, - "requires": { - "fs-extra": "^8.1.0", - "npmlog": "^4.1.2", - "read-cmd-shim": "^1.0.1" - } - }, - "@lerna/rimraf-dir": { - "version": "3.16.5", - "resolved": "https://registry.npmjs.org/@lerna/rimraf-dir/-/rimraf-dir-3.16.5.tgz", - "integrity": "sha512-bQlKmO0pXUsXoF8lOLknhyQjOZsCc0bosQDoX4lujBXSWxHVTg1VxURtWf2lUjz/ACsJVDfvHZbDm8kyBk5okA==", - "dev": true, - "requires": { - "@lerna/child-process": "3.16.5", - "npmlog": "^4.1.2", - "path-exists": "^3.0.0", - "rimraf": "^2.6.2" - } - }, - "@lerna/run": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@lerna/run/-/run-3.21.0.tgz", - "integrity": "sha512-fJF68rT3veh+hkToFsBmUJ9MHc9yGXA7LSDvhziAojzOb0AI/jBDp6cEcDQyJ7dbnplba2Lj02IH61QUf9oW0Q==", - "dev": true, - "requires": { - "@lerna/command": "3.21.0", - "@lerna/filter-options": "3.20.0", - "@lerna/npm-run-script": "3.16.5", - "@lerna/output": "3.13.0", - "@lerna/profiler": "3.20.0", - "@lerna/run-topologically": "3.18.5", - "@lerna/timer": "3.13.0", - "@lerna/validation-error": "3.13.0", - "p-map": "^2.1.0" - } - }, - "@lerna/run-lifecycle": { - "version": "3.16.2", - "resolved": "https://registry.npmjs.org/@lerna/run-lifecycle/-/run-lifecycle-3.16.2.tgz", - "integrity": "sha512-RqFoznE8rDpyyF0rOJy3+KjZCeTkO8y/OB9orPauR7G2xQ7PTdCpgo7EO6ZNdz3Al+k1BydClZz/j78gNCmL2A==", - "dev": true, - "requires": { - "@lerna/npm-conf": "3.16.0", - "figgy-pudding": "^3.5.1", - "npm-lifecycle": "^3.1.2", - "npmlog": "^4.1.2" - } - }, - "@lerna/run-topologically": { - "version": "3.18.5", - "resolved": "https://registry.npmjs.org/@lerna/run-topologically/-/run-topologically-3.18.5.tgz", - "integrity": "sha512-6N1I+6wf4hLOnPW+XDZqwufyIQ6gqoPfHZFkfWlvTQ+Ue7CuF8qIVQ1Eddw5HKQMkxqN10thKOFfq/9NQZ4NUg==", - "dev": true, - "requires": { - "@lerna/query-graph": "3.18.5", - "figgy-pudding": "^3.5.1", - "p-queue": "^4.0.0" - } - }, - "@lerna/symlink-binary": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/@lerna/symlink-binary/-/symlink-binary-3.17.0.tgz", - "integrity": "sha512-RLpy9UY6+3nT5J+5jkM5MZyMmjNHxZIZvXLV+Q3MXrf7Eaa1hNqyynyj4RO95fxbS+EZc4XVSk25DGFQbcRNSQ==", - "dev": true, - "requires": { - "@lerna/create-symlink": "3.16.2", - "@lerna/package": "3.16.0", - "fs-extra": "^8.1.0", - "p-map": "^2.1.0" - } - }, - "@lerna/symlink-dependencies": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/@lerna/symlink-dependencies/-/symlink-dependencies-3.17.0.tgz", - "integrity": "sha512-KmjU5YT1bpt6coOmdFueTJ7DFJL4H1w5eF8yAQ2zsGNTtZ+i5SGFBWpb9AQaw168dydc3s4eu0W0Sirda+F59Q==", - "dev": true, - "requires": { - "@lerna/create-symlink": "3.16.2", - "@lerna/resolve-symlink": "3.16.0", - "@lerna/symlink-binary": "3.17.0", - "fs-extra": "^8.1.0", - "p-finally": "^1.0.0", - "p-map": "^2.1.0", - "p-map-series": "^1.0.0" - } - }, - "@lerna/timer": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@lerna/timer/-/timer-3.13.0.tgz", - "integrity": "sha512-RHWrDl8U4XNPqY5MQHkToWS9jHPnkLZEt5VD+uunCKTfzlxGnRCr3/zVr8VGy/uENMYpVP3wJa4RKGY6M0vkRw==", - "dev": true - }, - "@lerna/validation-error": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@lerna/validation-error/-/validation-error-3.13.0.tgz", - "integrity": "sha512-SiJP75nwB8GhgwLKQfdkSnDufAaCbkZWJqEDlKOUPUvVOplRGnfL+BPQZH5nvq2BYSRXsksXWZ4UHVnQZI/HYA==", - "dev": true, - "requires": { - "npmlog": "^4.1.2" - } - }, - "@lerna/version": { - "version": "3.22.1", - "resolved": "https://registry.npmjs.org/@lerna/version/-/version-3.22.1.tgz", - "integrity": "sha512-PSGt/K1hVqreAFoi3zjD0VEDupQ2WZVlVIwesrE5GbrL2BjXowjCsTDPqblahDUPy0hp6h7E2kG855yLTp62+g==", - "dev": true, - "requires": { - "@lerna/check-working-tree": "3.16.5", - "@lerna/child-process": "3.16.5", - "@lerna/collect-updates": "3.20.0", - "@lerna/command": "3.21.0", - "@lerna/conventional-commits": "3.22.0", - "@lerna/github-client": "3.22.0", - "@lerna/gitlab-client": "3.15.0", - "@lerna/output": "3.13.0", - "@lerna/prerelease-id-from-version": "3.16.0", - "@lerna/prompt": "3.18.5", - "@lerna/run-lifecycle": "3.16.2", - "@lerna/run-topologically": "3.18.5", - "@lerna/validation-error": "3.13.0", - "chalk": "^2.3.1", - "dedent": "^0.7.0", - "load-json-file": "^5.3.0", - "minimatch": "^3.0.4", - "npmlog": "^4.1.2", - "p-map": "^2.1.0", - "p-pipe": "^1.2.0", - "p-reduce": "^1.0.0", - "p-waterfall": "^1.0.0", - "semver": "^6.2.0", - "slash": "^2.0.0", - "temp-write": "^3.4.0", - "write-json-file": "^3.2.0" - } - }, - "@lerna/write-log-file": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@lerna/write-log-file/-/write-log-file-3.13.0.tgz", - "integrity": "sha512-RibeMnDPvlL8bFYW5C8cs4mbI3AHfQef73tnJCQ/SgrXZHehmHnsyWUiE7qDQCAo+B1RfTapvSyFF69iPj326A==", - "dev": true, - "requires": { - "npmlog": "^4.1.2", - "write-file-atomic": "^2.3.0" - } - }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - } - }, - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true - }, - "@octokit/auth-token": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.4.2.tgz", - "integrity": "sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ==", - "dev": true, - "requires": { - "@octokit/types": "^5.0.0" - } - }, - "@octokit/endpoint": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.5.tgz", - "integrity": "sha512-70K5u6zd45ItOny6aHQAsea8HHQjlQq85yqOMe+Aj8dkhN2qSJ9T+Q3YjUjEYfPRBcuUWNgMn62DQnP/4LAIiQ==", - "dev": true, - "requires": { - "@octokit/types": "^5.0.0", - "is-plain-object": "^4.0.0", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "is-plain-object": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-4.1.1.tgz", - "integrity": "sha512-5Aw8LLVsDlZsETVMhoMXzqsXwQqr/0vlnBYzIXJbYo2F4yYlhLHs+Ez7Bod7IIQKWkJbJfxrWD7pA1Dw1TKrwA==", - "dev": true - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true - } - } - }, - "@octokit/plugin-enterprise-rest": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz", - "integrity": "sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw==", - "dev": true - }, - "@octokit/plugin-paginate-rest": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz", - "integrity": "sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q==", - "dev": true, - "requires": { - "@octokit/types": "^2.0.1" - }, - "dependencies": { - "@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", - "dev": true, - "requires": { - "@types/node": ">= 8" - } - } - } - }, - "@octokit/plugin-request-log": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz", - "integrity": "sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw==", - "dev": true - }, - "@octokit/plugin-rest-endpoint-methods": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz", - "integrity": "sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ==", - "dev": true, - "requires": { - "@octokit/types": "^2.0.1", - "deprecation": "^2.3.1" - }, - "dependencies": { - "@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", - "dev": true, - "requires": { - "@types/node": ">= 8" - } - } - } - }, - "@octokit/request": { - "version": "5.4.7", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.4.7.tgz", - "integrity": "sha512-FN22xUDP0i0uF38YMbOfx6TotpcENP5W8yJM1e/LieGXn6IoRxDMnBf7tx5RKSW4xuUZ/1P04NFZy5iY3Rax1A==", - "dev": true, - "requires": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.0.0", - "@octokit/types": "^5.0.0", - "deprecation": "^2.0.0", - "is-plain-object": "^4.0.0", - "node-fetch": "^2.3.0", - "once": "^1.4.0", - "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/request-error": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.0.2.tgz", - "integrity": "sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw==", - "dev": true, - "requires": { - "@octokit/types": "^5.0.1", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "is-plain-object": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-4.1.1.tgz", - "integrity": "sha512-5Aw8LLVsDlZsETVMhoMXzqsXwQqr/0vlnBYzIXJbYo2F4yYlhLHs+Ez7Bod7IIQKWkJbJfxrWD7pA1Dw1TKrwA==", - "dev": true - }, - "universal-user-agent": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", - "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==", - "dev": true - } - } - }, - "@octokit/request-error": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-1.2.1.tgz", - "integrity": "sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA==", - "dev": true, - "requires": { - "@octokit/types": "^2.0.0", - "deprecation": "^2.0.0", - "once": "^1.4.0" - }, - "dependencies": { - "@octokit/types": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-2.16.2.tgz", - "integrity": "sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q==", - "dev": true, - "requires": { - "@types/node": ">= 8" - } - } - } - }, - "@octokit/rest": { - "version": "16.43.2", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.43.2.tgz", - "integrity": "sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ==", - "dev": true, - "requires": { - "@octokit/auth-token": "^2.4.0", - "@octokit/plugin-paginate-rest": "^1.1.1", - "@octokit/plugin-request-log": "^1.0.0", - "@octokit/plugin-rest-endpoint-methods": "2.4.0", - "@octokit/request": "^5.2.0", - "@octokit/request-error": "^1.0.2", - "atob-lite": "^2.0.0", - "before-after-hook": "^2.0.0", - "btoa-lite": "^1.0.0", - "deprecation": "^2.0.0", - "lodash.get": "^4.4.2", - "lodash.set": "^4.3.2", - "lodash.uniq": "^4.5.0", - "octokit-pagination-methods": "^1.1.0", - "once": "^1.4.0", - "universal-user-agent": "^4.0.0" - } - }, - "@octokit/types": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.2.1.tgz", - "integrity": "sha512-PugtgEw8u++zAyBpDpSkR8K1OsT2l8QWp3ECL6bZHFoq9PfHDoKeGFWSuX2Z+Ghy93k1fkKf8tsmqNBv+8dEfQ==", - "dev": true, - "requires": { - "@types/node": ">= 8" - } - }, - "@types/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", - "dev": true - }, - "@types/node": { - "version": "14.0.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz", - "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==", - "dev": true - }, - "@types/normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", - "dev": true - }, - "@zkochan/cmd-shim": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz", - "integrity": "sha512-o8l0+x7C7sMZU3v9GuJIAU10qQLtwR1dtRQIOmlNMtyaqhmpXOzx1HWiYoWfmmf9HHZoAkXpc9TM9PQYF9d4Jg==", - "dev": true, - "requires": { - "is-windows": "^1.0.0", - "mkdirp-promise": "^5.0.1", - "mz": "^2.5.0" - } - }, - "JSONStream": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", - "dev": true, - "requires": { - "jsonparse": "^1.2.0", - "through": ">=2.2.7 <3" - } - }, - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - }, - "agentkeepalive": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-3.5.2.tgz", - "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", - "dev": true, - "requires": { - "humanize-ms": "^1.2.1" - } - }, - "ajv": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", - "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", - "dev": true - }, - "aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", - "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-differ": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-2.1.0.tgz", - "integrity": "sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w==", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-ify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", - "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", - "dev": true - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", - "dev": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "atob-lite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/atob-lite/-/atob-lite-2.0.0.tgz", - "integrity": "sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY=", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", - "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "before-after-hook": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.1.0.tgz", - "integrity": "sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A==", - "dev": true - }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "btoa-lite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/btoa-lite/-/btoa-lite-1.0.0.tgz", - "integrity": "sha1-M3dm2hWAEhD92VbCLpxokaudAzc=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "builtins": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/builtins/-/builtins-1.0.3.tgz", - "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=", - "dev": true - }, - "byline": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", - "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=", - "dev": true - }, - "byte-size": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/byte-size/-/byte-size-5.0.1.tgz", - "integrity": "sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw==", - "dev": true - }, - "cacache": { - "version": "12.0.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", - "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", - "dev": true, - "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", - "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", - "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true - }, - "caller-callsite": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", - "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", - "dev": true, - "requires": { - "callsites": "^2.0.0" - } - }, - "caller-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", - "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", - "dev": true, - "requires": { - "caller-callsite": "^2.0.0" - } - }, - "callsites": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", - "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", - "dev": true - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - } - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true - }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", - "dev": true - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "columnify": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/columnify/-/columnify-1.5.4.tgz", - "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", - "dev": true, - "requires": { - "strip-ansi": "^3.0.0", - "wcwidth": "^1.0.0" - } - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "compare-func": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.4.tgz", - "integrity": "sha512-sq2sWtrqKPkEXAC8tEJA1+BqAH9GbFkGBtUOqrUX57VSfwp8xyktctk+uLoRy5eccTdxzDcVIztlYDpKs3Jv1Q==", - "dev": true, - "requires": { - "array-ify": "^1.0.0", - "dot-prop": "^3.0.0" - }, - "dependencies": { - "dot-prop": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-3.0.0.tgz", - "integrity": "sha1-G3CK8JSknJoOfbyteQq6U52sEXc=", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - } - } - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", - "dev": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "conventional-changelog-angular": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.10.tgz", - "integrity": "sha512-k7RPPRs0vp8+BtPsM9uDxRl6KcgqtCJmzRD1wRtgqmhQ96g8ifBGo9O/TZBG23jqlXS/rg8BKRDELxfnQQGiaA==", - "dev": true, - "requires": { - "compare-func": "^1.3.1", - "q": "^1.5.1" - } - }, - "conventional-changelog-core": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-3.2.3.tgz", - "integrity": "sha512-LMMX1JlxPIq/Ez5aYAYS5CpuwbOk6QFp8O4HLAcZxe3vxoCtABkhfjetk8IYdRB9CDQGwJFLR3Dr55Za6XKgUQ==", - "dev": true, - "requires": { - "conventional-changelog-writer": "^4.0.6", - "conventional-commits-parser": "^3.0.3", - "dateformat": "^3.0.0", - "get-pkg-repo": "^1.0.0", - "git-raw-commits": "2.0.0", - "git-remote-origin-url": "^2.0.0", - "git-semver-tags": "^2.0.3", - "lodash": "^4.2.1", - "normalize-package-data": "^2.3.5", - "q": "^1.5.1", - "read-pkg": "^3.0.0", - "read-pkg-up": "^3.0.0", - "through2": "^3.0.0" - }, - "dependencies": { - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - } - } - }, - "conventional-changelog-preset-loader": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", - "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", - "dev": true - }, - "conventional-changelog-writer": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-4.0.16.tgz", - "integrity": "sha512-jmU1sDJDZpm/dkuFxBeRXvyNcJQeKhGtVcFFkwTphUAzyYWcwz2j36Wcv+Mv2hU3tpvLMkysOPXJTLO55AUrYQ==", - "dev": true, - "requires": { - "compare-func": "^1.3.1", - "conventional-commits-filter": "^2.0.6", - "dateformat": "^3.0.0", - "handlebars": "^4.7.6", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.15", - "meow": "^7.0.0", - "semver": "^6.0.0", - "split": "^1.0.0", - "through2": "^3.0.0" - }, - "dependencies": { - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - } - } - }, - "conventional-commits-filter": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.6.tgz", - "integrity": "sha512-4g+sw8+KA50/Qwzfr0hL5k5NWxqtrOVw4DDk3/h6L85a9Gz0/Eqp3oP+CWCNfesBvZZZEFHF7OTEbRe+yYSyKw==", - "dev": true, - "requires": { - "lodash.ismatch": "^4.4.0", - "modify-values": "^1.0.0" - } - }, - "conventional-commits-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.1.0.tgz", - "integrity": "sha512-RSo5S0WIwXZiRxUGTPuYFbqvrR4vpJ1BDdTlthFgvHt5kEdnd1+pdvwWphWn57/oIl4V72NMmOocFqqJ8mFFhA==", - "dev": true, - "requires": { - "JSONStream": "^1.0.4", - "is-text-path": "^1.0.1", - "lodash": "^4.17.15", - "meow": "^7.0.0", - "split2": "^2.0.0", - "through2": "^3.0.0", - "trim-off-newlines": "^1.0.0" - }, - "dependencies": { - "through2": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", - "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", - "dev": true, - "requires": { - "inherits": "^2.0.4", - "readable-stream": "2 || 3" - } - } - } - }, - "conventional-recommended-bump": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-5.0.1.tgz", - "integrity": "sha512-RVdt0elRcCxL90IrNP0fYCpq1uGt2MALko0eyeQ+zQuDVWtMGAy9ng6yYn3kax42lCj9+XBxQ8ZN6S9bdKxDhQ==", - "dev": true, - "requires": { - "concat-stream": "^2.0.0", - "conventional-changelog-preset-loader": "^2.1.1", - "conventional-commits-filter": "^2.0.2", - "conventional-commits-parser": "^3.0.3", - "git-raw-commits": "2.0.0", - "git-semver-tags": "^2.0.3", - "meow": "^4.0.0", - "q": "^1.5.1" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "camelcase-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", - "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", - "dev": true, - "requires": { - "camelcase": "^4.1.0", - "map-obj": "^2.0.0", - "quick-lru": "^1.0.0" - } - }, - "concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "map-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", - "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", - "dev": true - }, - "meow": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", - "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", - "dev": true, - "requires": { - "camelcase-keys": "^4.0.0", - "decamelize-keys": "^1.0.0", - "loud-rejection": "^1.0.0", - "minimist": "^1.1.3", - "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" - } - }, - "minimist-options": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" - } - }, - "quick-lru": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", - "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "redent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", - "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", - "dev": true, - "requires": { - "indent-string": "^3.0.0", - "strip-indent": "^2.0.0" - } - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true - }, - "trim-newlines": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", - "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", - "dev": true - } - } - }, - "copy-concurrently": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "fs-write-stream-atomic": "^1.0.8", - "iferr": "^0.1.5", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.0" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cosmiconfig": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", - "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", - "dev": true, - "requires": { - "import-fresh": "^2.0.0", - "is-directory": "^0.3.1", - "js-yaml": "^3.13.1", - "parse-json": "^4.0.0" - } - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "cyclist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", - "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", - "dev": true - }, - "dargs": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-4.1.0.tgz", - "integrity": "sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "debuglog": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz", - "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=", - "dev": true - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, - "requires": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "dependencies": { - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - } - } - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true - }, - "detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=", - "dev": true - }, - "dezalgo": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz", - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", - "dev": true, - "requires": { - "asap": "^2.0.0", - "wrappy": "1" - } - }, - "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", - "dev": true, - "requires": { - "path-type": "^3.0.0" - } - }, - "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", - "dev": true - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "requires": { - "iconv-lite": "^0.6.2" - } - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "env-paths": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.0.tgz", - "integrity": "sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==", - "dev": true - }, - "envinfo": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.7.2.tgz", - "integrity": "sha512-k3Eh5bKuQnZjm49/L7H4cHzs2FlL5QjbTB3JrPxoTI8aJG7hVMe4uKyJxSYH4ahseby2waUwk5OaKX/nAsaYgg==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.17.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", - "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.0", - "is-regex": "^1.1.0", - "object-inspect": "^1.7.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.0", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true - }, - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "requires": { - "es6-promise": "^4.0.3" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", - "dev": true - }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "requires": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "dependencies": { - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", - "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", - "dev": true, - "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - }, - "dependencies": { - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "figgy-pudding": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", - "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "flush-write-stream": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", - "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.3.6" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" - } - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", - "dev": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs-write-stream-atomic": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "iferr": "^0.1.5", - "imurmurhash": "^0.1.4", - "readable-stream": "1 || 2" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "genfun": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/genfun/-/genfun-5.0.0.tgz", - "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-pkg-repo": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz", - "integrity": "sha1-xztInAbYDMVTbCyFP54FIyBWly0=", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "meow": "^3.3.0", - "normalize-package-data": "^2.3.0", - "parse-github-repo-url": "^1.3.0", - "through2": "^2.0.0" - }, - "dependencies": { - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - } - } - }, - "get-port": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-4.2.0.tgz", - "integrity": "sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw==", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "git-raw-commits": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.0.tgz", - "integrity": "sha512-w4jFEJFgKXMQJ0H0ikBk2S+4KP2VEjhCvLCNqbNRQC8BgGWgLKNCO7a9K9LI+TVT7Gfoloje502sEnctibffgg==", - "dev": true, - "requires": { - "dargs": "^4.0.1", - "lodash.template": "^4.0.2", - "meow": "^4.0.0", - "split2": "^2.0.0", - "through2": "^2.0.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "camelcase-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", - "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", - "dev": true, - "requires": { - "camelcase": "^4.1.0", - "map-obj": "^2.0.0", - "quick-lru": "^1.0.0" - } - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "map-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", - "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", - "dev": true - }, - "meow": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", - "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", - "dev": true, - "requires": { - "camelcase-keys": "^4.0.0", - "decamelize-keys": "^1.0.0", - "loud-rejection": "^1.0.0", - "minimist": "^1.1.3", - "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" - } - }, - "minimist-options": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" - } - }, - "quick-lru": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", - "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", - "dev": true - }, - "redent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", - "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", - "dev": true, - "requires": { - "indent-string": "^3.0.0", - "strip-indent": "^2.0.0" - } - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true - }, - "trim-newlines": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", - "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", - "dev": true - } - } - }, - "git-remote-origin-url": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", - "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", - "dev": true, - "requires": { - "gitconfiglocal": "^1.0.0", - "pify": "^2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, - "git-semver-tags": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-2.0.3.tgz", - "integrity": "sha512-tj4FD4ww2RX2ae//jSrXZzrocla9db5h0V7ikPl1P/WwoZar9epdUhwR7XHXSgc+ZkNq72BEEerqQuicoEQfzA==", - "dev": true, - "requires": { - "meow": "^4.0.0", - "semver": "^6.0.0" - }, - "dependencies": { - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "camelcase-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", - "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", - "dev": true, - "requires": { - "camelcase": "^4.1.0", - "map-obj": "^2.0.0", - "quick-lru": "^1.0.0" - } - }, - "indent-string": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", - "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", - "dev": true - }, - "map-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", - "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", - "dev": true - }, - "meow": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-4.0.1.tgz", - "integrity": "sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A==", - "dev": true, - "requires": { - "camelcase-keys": "^4.0.0", - "decamelize-keys": "^1.0.0", - "loud-rejection": "^1.0.0", - "minimist": "^1.1.3", - "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" - } - }, - "minimist-options": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", - "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0" - } - }, - "quick-lru": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", - "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", - "dev": true - }, - "redent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", - "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", - "dev": true, - "requires": { - "indent-string": "^3.0.0", - "strip-indent": "^2.0.0" - } - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true - }, - "trim-newlines": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", - "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", - "dev": true - } - } - }, - "git-up": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/git-up/-/git-up-4.0.1.tgz", - "integrity": "sha512-LFTZZrBlrCrGCG07/dm1aCjjpL1z9L3+5aEeI9SBhAqSc+kiA9Or1bgZhQFNppJX6h/f5McrvJt1mQXTFm6Qrw==", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "parse-url": "^5.0.0" - } - }, - "git-url-parse": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/git-url-parse/-/git-url-parse-11.1.2.tgz", - "integrity": "sha512-gZeLVGY8QVKMIkckncX+iCq2/L8PlwncvDFKiWkBn9EtCfYDbliRTTp6qzyQ1VMdITUfq7293zDzfpjdiGASSQ==", - "dev": true, - "requires": { - "git-up": "^4.0.0" - } - }, - "gitconfiglocal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", - "dev": true, - "requires": { - "ini": "^1.3.2" - } - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "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-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", - "dev": true - }, - "globby": { - "version": "9.2.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", - "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^1.0.2", - "dir-glob": "^2.2.2", - "fast-glob": "^2.2.6", - "glob": "^7.1.3", - "ignore": "^4.0.3", - "pify": "^4.0.1", - "slash": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "handlebars": { - "version": "4.7.6", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz", - "integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==", - "dev": true, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.0", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "dev": true, - "requires": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - } - }, - "hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", - "dev": true - }, - "http-cache-semantics": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", - "dev": true - }, - "http-proxy-agent": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz", - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", - "dev": true, - "requires": { - "agent-base": "4", - "debug": "3.1.0" - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", - "dev": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - } - }, - "humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", - "dev": true, - "requires": { - "ms": "^2.0.0" - } - }, - "iconv-lite": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", - "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - } - }, - "iferr": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", - "dev": true - }, - "ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true - }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "import-fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", - "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", - "dev": true, - "requires": { - "caller-path": "^2.0.0", - "resolve-from": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "init-package-json": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-1.10.3.tgz", - "integrity": "sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==", - "dev": true, - "requires": { - "glob": "^7.1.1", - "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", - "promzard": "^0.3.0", - "read": "~1.0.1", - "read-package-json": "1 || 2", - "semver": "2.x || 3.x || 4 || 5", - "validate-npm-package-license": "^3.0.1", - "validate-npm-package-name": "^3.0.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "inquirer": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", - "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", - "dev": true, - "requires": { - "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" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } - } - } - } - }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", - "dev": true - }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "dev": true, - "requires": { - "ci-info": "^2.0.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-directory": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", - "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", - "dev": true - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", - "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-ssh": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz", - "integrity": "sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg==", - "dev": true, - "requires": { - "protocols": "^1.1.0" - } - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-text-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", - "dev": true, - "requires": { - "text-extensions": "^1.0.0" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "json-parse-better-errors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "lerna": { - "version": "3.22.1", - "resolved": "https://registry.npmjs.org/lerna/-/lerna-3.22.1.tgz", - "integrity": "sha512-vk1lfVRFm+UuEFA7wkLKeSF7Iz13W+N/vFd48aW2yuS7Kv0RbNm2/qcDPV863056LMfkRlsEe+QYOw3palj5Lg==", - "dev": true, - "requires": { - "@lerna/add": "3.21.0", - "@lerna/bootstrap": "3.21.0", - "@lerna/changed": "3.21.0", - "@lerna/clean": "3.21.0", - "@lerna/cli": "3.18.5", - "@lerna/create": "3.22.0", - "@lerna/diff": "3.21.0", - "@lerna/exec": "3.21.0", - "@lerna/import": "3.22.0", - "@lerna/info": "3.21.0", - "@lerna/init": "3.21.0", - "@lerna/link": "3.21.0", - "@lerna/list": "3.21.0", - "@lerna/publish": "3.22.1", - "@lerna/run": "3.21.0", - "@lerna/version": "3.22.1", - "import-local": "^2.0.0", - "npmlog": "^4.1.2" - } - }, - "lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", - "dev": true - }, - "load-json-file": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", - "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "parse-json": "^4.0.0", - "pify": "^4.0.1", - "strip-bom": "^3.0.0", - "type-fest": "^0.3.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "lodash.ismatch": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", - "dev": true - }, - "lodash.set": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", - "dev": true - }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, - "lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0" - } - }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", - "dev": true - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } - }, - "macos-release": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.4.1.tgz", - "integrity": "sha512-H/QHeBIN1fIGJX517pvK8IEK53yQOW7YcEI55oYtgjDdoCQQz7eJS94qt5kNrscReEyuD/JcdFCm2XBEcGOITg==", - "dev": true - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "make-fetch-happen": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz", - "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", - "dev": true, - "requires": { - "agentkeepalive": "^3.4.1", - "cacache": "^12.0.0", - "http-cache-semantics": "^3.8.1", - "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.3", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "node-fetch-npm": "^2.0.2", - "promise-retry": "^1.1.1", - "socks-proxy-agent": "^4.0.0", - "ssri": "^6.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", - "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "meow": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-7.0.1.tgz", - "integrity": "sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==", - "dev": true, - "requires": { - "@types/minimist": "^1.2.0", - "arrify": "^2.0.1", - "camelcase": "^6.0.0", - "camelcase-keys": "^6.2.2", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "^4.0.2", - "normalize-package-data": "^2.5.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.13.1", - "yargs-parser": "^18.1.3" - }, - "dependencies": { - "arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", - "dev": true - }, - "camelcase": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz", - "integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "parse-json": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.1.tgz", - "integrity": "sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", - "lines-and-columns": "^1.1.6" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - } - } - } - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", - "dev": true - }, - "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", - "dev": true, - "requires": { - "mime-db": "1.44.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "requires": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - } - }, - "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", - "dev": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", - "dev": true, - "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mkdirp-promise": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", - "integrity": "sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE=", - "dev": true, - "requires": { - "mkdirp": "*" - } - }, - "modify-values": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", - "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", - "dev": true - }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", - "dev": true, - "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "multimatch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-3.0.0.tgz", - "integrity": "sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA==", - "dev": true, - "requires": { - "array-differ": "^2.0.3", - "array-union": "^1.0.2", - "arrify": "^1.0.1", - "minimatch": "^3.0.4" - } - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, - "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "dev": true - }, - "node-fetch-npm": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz", - "integrity": "sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==", - "dev": true, - "requires": { - "encoding": "^0.1.11", - "json-parse-better-errors": "^1.0.0", - "safe-buffer": "^5.1.1" - } - }, - "node-gyp": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-5.1.1.tgz", - "integrity": "sha512-WH0WKGi+a4i4DUt2mHnvocex/xPLp9pYt5R6M2JdFB7pJ7Z34hveZ4nDTGTiLXCkitA9T8HFZjhinBCiVHYcWw==", - "dev": true, - "requires": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.2", - "mkdirp": "^0.5.1", - "nopt": "^4.0.1", - "npmlog": "^4.1.2", - "request": "^2.88.0", - "rimraf": "^2.6.3", - "semver": "^5.7.1", - "tar": "^4.4.12", - "which": "^1.3.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "nopt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", - "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", - "dev": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "normalize-url": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", - "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", - "dev": true - }, - "npm-bundled": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", - "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", - "dev": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-lifecycle": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz", - "integrity": "sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g==", - "dev": true, - "requires": { - "byline": "^5.0.0", - "graceful-fs": "^4.1.15", - "node-gyp": "^5.0.2", - "resolve-from": "^4.0.0", - "slide": "^1.1.6", - "uid-number": "0.0.6", - "umask": "^1.1.0", - "which": "^1.3.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", - "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", - "dev": true - }, - "npm-package-arg": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", - "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", - "dev": true, - "requires": { - "hosted-git-info": "^2.7.1", - "osenv": "^0.1.5", - "semver": "^5.6.0", - "validate-npm-package-name": "^3.0.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "npm-packlist": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", - "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", - "dev": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1", - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-pick-manifest": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", - "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1", - "npm-package-arg": "^6.0.0", - "semver": "^5.4.1" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "octokit-pagination-methods": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz", - "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-name": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-name/-/os-name-3.1.0.tgz", - "integrity": "sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg==", - "dev": true, - "requires": { - "macos-release": "^2.2.0", - "windows-release": "^3.1.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true - }, - "p-map-series": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-1.0.0.tgz", - "integrity": "sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco=", - "dev": true, - "requires": { - "p-reduce": "^1.0.0" - } - }, - "p-pipe": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", - "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", - "dev": true - }, - "p-queue": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-4.0.0.tgz", - "integrity": "sha512-3cRXXn3/O0o3+eVmUroJPSj/esxoEFIm0ZOno/T+NzG/VZgPOqQ8WKmlNqubSEpZmCIngEy34unkHGg83ZIBmg==", - "dev": true, - "requires": { - "eventemitter3": "^3.1.0" - } - }, - "p-reduce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", - "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", - "dev": true - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "p-waterfall": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-waterfall/-/p-waterfall-1.0.0.tgz", - "integrity": "sha1-ftlLPOszMngjU69qrhGqn8I1uwA=", - "dev": true, - "requires": { - "p-reduce": "^1.0.0" - } - }, - "parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", - "dev": true, - "requires": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" - } - }, - "parse-github-repo-url": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz", - "integrity": "sha1-nn2LslKmy2ukJZUGC3v23z28H1A=", - "dev": true - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parse-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/parse-path/-/parse-path-4.0.1.tgz", - "integrity": "sha512-d7yhga0Oc+PwNXDvQ0Jv1BuWkLVPXcAoQ/WREgd6vNNoKYaW52KI+RdOFjI63wjkmps9yUE8VS4veP+AgpQ/hA==", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "protocols": "^1.4.0" - } - }, - "parse-url": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/parse-url/-/parse-url-5.0.1.tgz", - "integrity": "sha512-flNUPP27r3vJpROi0/R3/2efgKkyXqnXwyP1KQ2U0SfFRgdizOdWfvrrvJg1LuOoxs7GQhmxJlq23IpQ/BkByg==", - "dev": true, - "requires": { - "is-ssh": "^1.3.0", - "normalize-url": "^3.3.0", - "parse-path": "^4.0.0", - "protocols": "^1.4.0" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", - "dev": true - }, - "promise-retry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-1.1.1.tgz", - "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", - "dev": true, - "requires": { - "err-code": "^1.0.0", - "retry": "^0.10.0" - }, - "dependencies": { - "err-code": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", - "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=", - "dev": true - } - } - }, - "promzard": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/promzard/-/promzard-0.3.0.tgz", - "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", - "dev": true, - "requires": { - "read": "1" - } - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true - }, - "protocols": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/protocols/-/protocols-1.4.7.tgz", - "integrity": "sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg==", - "dev": true - }, - "protoduck": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/protoduck/-/protoduck-5.0.1.tgz", - "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", - "dev": true, - "requires": { - "genfun": "^5.0.0" - } - }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true - }, - "read": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", - "dev": true, - "requires": { - "mute-stream": "~0.0.4" - } - }, - "read-cmd-shim": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz", - "integrity": "sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2" - } - }, - "read-package-json": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.1.tgz", - "integrity": "sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A==", - "dev": true, - "requires": { - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "json-parse-better-errors": "^1.0.1", - "normalize-package-data": "^2.0.0", - "npm-normalize-package-bin": "^1.0.0" - } - }, - "read-package-tree": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/read-package-tree/-/read-package-tree-5.3.1.tgz", - "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", - "dev": true, - "requires": { - "read-package-json": "^2.0.0", - "readdir-scoped-modules": "^1.0.0", - "util-promisify": "^2.1.0" - } - }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, - "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" - }, - "dependencies": { - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - } - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - } - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "readdir-scoped-modules": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz", - "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", - "dev": true, - "requires": { - "debuglog": "^1.0.1", - "dezalgo": "^1.0.0", - "graceful-fs": "^4.1.2", - "once": "^1.3.0" - } - }, - "redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "requires": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", - "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", - "dev": true - } - } - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "retry": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", - "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-async": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", - "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", - "dev": true - }, - "run-queue": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", - "dev": true, - "requires": { - "aproba": "^1.1.1" - } - }, - "rxjs": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz", - "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==", - "dev": true, - "requires": { - "tslib": "^1.9.0" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "slide": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz", - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=", - "dev": true - }, - "smart-buffer": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", - "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "socks": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.3.3.tgz", - "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", - "dev": true, - "requires": { - "ip": "1.1.5", - "smart-buffer": "^4.1.0" - } - }, - "socks-proxy-agent": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz", - "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", - "dev": true, - "requires": { - "agent-base": "~4.2.1", - "socks": "~2.3.2" - }, - "dependencies": { - "agent-base": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.1.tgz", - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", - "dev": true, - "requires": { - "es6-promisify": "^5.0.0" - } - } - } - }, - "sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "split2": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", - "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", - "dev": true, - "requires": { - "through2": "^2.0.2" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", - "dev": true, - "requires": { - "figgy-pudding": "^3.5.1" - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-each": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", - "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" - } - }, - "stream-shift": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", - "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - } - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } - }, - "strong-log-transformer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz", - "integrity": "sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA==", - "dev": true, - "requires": { - "duplexer": "^0.1.1", - "minimist": "^1.2.0", - "through": "^2.3.4" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", - "dev": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "temp-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", - "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", - "dev": true - }, - "temp-write": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/temp-write/-/temp-write-3.4.0.tgz", - "integrity": "sha1-jP9jD7fp2gXwR8dM5M5NaFRX1JI=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "is-stream": "^1.1.0", - "make-dir": "^1.0.0", - "pify": "^3.0.0", - "temp-dir": "^1.0.0", - "uuid": "^3.0.1" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "text-extensions": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", - "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", - "dev": true - }, - "thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "dev": true, - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "trim-newlines": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", - "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==", - "dev": true - }, - "trim-off-newlines": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", - "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", - "dev": true - }, - "tslib": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "type-fest": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", - "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", - "dev": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uglify-js": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.1.tgz", - "integrity": "sha512-RjxApKkrPJB6kjJxQS3iZlf///REXWYxYJxO/MpmlQzVkDWVI3PSnCBWezMecmTU/TRkNxrl8bmsfFQCp+LO+Q==", - "dev": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz", - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=", - "dev": true - }, - "umask": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/umask/-/umask-1.1.0.tgz", - "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-filename": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", - "dev": true, - "requires": { - "unique-slug": "^2.0.0" - } - }, - "unique-slug": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", - "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4" - } - }, - "universal-user-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-4.0.1.tgz", - "integrity": "sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg==", - "dev": true, - "requires": { - "os-name": "^3.1.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "util-promisify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/util-promisify/-/util-promisify-2.1.0.tgz", - "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3" - } - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "validate-npm-package-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz", - "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", - "dev": true, - "requires": { - "builtins": "^1.0.3" - } - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", - "dev": true, - "requires": { - "defaults": "^1.0.3" - } - }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true - }, - "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "windows-release": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-3.3.1.tgz", - "integrity": "sha512-Pngk/RDCaI/DkuHPlGTdIkDiTAnAkyMjoQMZqRsxydNl1qGXNIoZrB7RK8g53F2tEgQBMqQJHQdYZuQEEAu54A==", - "dev": true, - "requires": { - "execa": "^1.0.0" - } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "write-json-file": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", - "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", - "dev": true, - "requires": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.15", - "make-dir": "^2.1.0", - "pify": "^4.0.1", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.4.2" - }, - "dependencies": { - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "write-pkg": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-3.2.0.tgz", - "integrity": "sha512-tX2ifZ0YqEFOF1wjRW2Pk93NLsj02+n1UP5RvO6rCs0K6R2g1padvf006cY74PQJKMGS2r42NK7FD0dG6Y6paw==", - "dev": true, - "requires": { - "sort-keys": "^2.0.0", - "write-json-file": "^2.2.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - }, - "write-json-file": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-2.3.0.tgz", - "integrity": "sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8=", - "dev": true, - "requires": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "pify": "^3.0.0", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.0.0" - } - } - } - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "y18n": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", - "dev": true - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "yargs": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", - "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^15.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "yargs-parser": { - "version": "15.0.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", - "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } -} diff --git a/package.json b/package.json index 91d7578d..12cbaffa 100644 --- a/package.json +++ b/package.json @@ -4,16 +4,14 @@ "description": "JS implementation of the IPFS UnixFS", "scripts": { "postinstall": "lerna bootstrap", - "reset": "lerna run --parallel clean && rm -rf packages/*/node_modules node_modules", - "test": "lerna run --parallel test", - "test:node": "lerna run --parallel test:node", - "test:browser": "lerna run --parallel test:browser", - "test:webworker": "lerna run --parallel test:webworker", - "coverage": "lerna run --parallel coverage", - "build": "lerna run --parallel build", - "clean": "lerna run --parallel clean", - "lint": "lerna run --parallel lint", - "depcheck": "lerna run --parallel depcheck", + "reset": "lerna run clean && rm -rf packages/*/node_modules node_modules", + "test": "lerna run test", + "coverage": "lerna run coverage", + "prepare": "lerna run prepare", + "build": "lerna run build", + "clean": "lerna run clean", + "lint": "lerna run lint", + "depcheck": "lerna run depcheck", "release": "npm run update-contributors && lerna publish", "release:rc": "lerna publish --canary --preid rc --dist-tag next", "update-contributors": "aegir release --lint=false --test=false --bump=false --build=false --changelog=false --commit=false --tag=false --push=false --ghrelease=false --docs=false --publish=false" diff --git a/packages/ipfs-unixfs-exporter/README.md b/packages/ipfs-unixfs-exporter/README.md index e39b86e6..73654083 100644 --- a/packages/ipfs-unixfs-exporter/README.md +++ b/packages/ipfs-unixfs-exporter/README.md @@ -22,7 +22,7 @@ - [Example](#example) - [API](#api) - [`exporter(cid, ipld, options)`](#exportercid-ipld-options) - - [UnixFS V1 entries](#unixfs-v1-entries) + - [UnixFSEntry](#unixfsentry) - [Raw entries](#raw-entries) - [CBOR entries](#cbor-entries) - [`entry.content({ offset, length })`](#entrycontent-offset-length-) @@ -87,41 +87,39 @@ const exporter = require('ipfs-unixfs-exporter') Uses the given [ipld](https://github.com/ipld/js-ipld) instance to fetch an IPFS node by it's CID. -Returns a Promise which resolves to an `entry`. +Returns a Promise which resolves to a `UnixFSEntry`. `options` is an optional object argument that might include the following keys: - `signal` ([AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal)): Used to cancel any network requests that are initiated as a result of this export -#### UnixFS V1 entries - -Entries with a `dag-pb` codec `CID` return UnixFS V1 entries: +#### UnixFSEntry ```javascript { + type: 'file' // or 'directory' name: 'foo.txt', path: 'Qmbar/foo.txt', cid: CID, // see https://github.com/multiformats/js-cid - node: DAGNode, // see https://github.com/ipld/js-ipld-dag-pb content: function, // returns an async iterator unixfs: UnixFS // see https://github.com/ipfs/js-ipfs-unixfs } ``` -If the entry is a file, `entry.content()` returns an async iterator that yields one or more buffers containing the file content: +If the entry is a file, `entry.content()` returns an async iterator that yields one or more Uint8Arrays containing the file content: ```javascript -if (entry.unixfs.type === 'file') { +if (entry.type === 'file') { for await (const chunk of entry.content()) { // chunk is a Buffer } } ``` -If the entry is a directory or hamt shard, `entry.content()` returns further `entry` objects: +If the entry is a directory, `entry.content()` returns further `entry` objects: ```javascript -if (entry.unixfs.type.includes('directory')) { // can be 'directory' or 'hamt-sharded-directory' +if (entry.type === 'directory') { for await (const entry of dir.content()) { console.info(entry.name) } @@ -167,7 +165,6 @@ Entries with a `dag-cbor` codec `CID` return JavaScript object entries: There is no `content` function for a `CBOR` node. - #### `entry.content({ offset, length })` When `entry` is a file or a `raw` node, `offset` and/or `length` arguments can be passed to `entry.content()` to return slices of data: @@ -189,7 +186,7 @@ for await (const chunk of entry.content({ return data ``` -If `entry` is a directory or hamt shard, passing `offset` and/or `length` to `entry.content()` will limit the number of files returned from the directory. +If `entry` is a directory, passing `offset` and/or `length` to `entry.content()` will limit the number of files returned from the directory. ```javascript const entries = [] diff --git a/packages/ipfs-unixfs-exporter/package.json b/packages/ipfs-unixfs-exporter/package.json index 3f15f688..81c4312f 100644 --- a/packages/ipfs-unixfs-exporter/package.json +++ b/packages/ipfs-unixfs-exporter/package.json @@ -8,15 +8,12 @@ "fs": false }, "scripts": { + "prepare": "aegir build --no-bundle", "test": "aegir test", - "test:node": "aegir test -t node", - "test:browser": "aegir test -t browser", - "test:webworker": "aegir test -t webworker", - "build": "aegir build", "clean": "rm -rf ./dist", "lint": "aegir lint", - "coverage": "nyc -s npm run test:node && nyc report --reporter=html", - "depcheck": "aegir dep-check" + "coverage": "nyc -s npm run test -t node && nyc report --reporter=html", + "depcheck": "aegir dep-check -i @types/mocha -i @types/sinon -i nyc -i abort-controller" }, "repository": { "type": "git", @@ -35,29 +32,39 @@ }, "homepage": "https://github.com/ipfs/js-ipfs-unixfs#readme", "devDependencies": { + "@types/mocha": "^8.2.0", + "@types/sinon": "^9.0.10", "abort-controller": "^3.0.0", - "aegir": "^29.2.2", + "aegir": "^30.3.0", "detect-node": "^2.0.4", - "ipfs-unixfs-importer": "^5.0.0", "ipld": "^0.28.0", - "ipld-dag-pb": "^0.20.0", + "ipld-dag-pb": "^0.21.0", "ipld-in-memory": "^7.0.0", + "ipfs-unixfs-importer": "^5.0.0", "it-all": "^1.0.1", - "it-buffer-stream": "^1.0.2", + "it-buffer-stream": "^2.0.0", "it-first": "^1.0.1", - "merge-options": "^3.0.3", + "merge-options": "^3.0.4", "multicodec": "^2.0.0", + "native-abort-controller": "^1.0.3", "nyc": "^15.0.0", - "sinon": "^9.0.1", - "uint8arrays": "^1.1.0" + "sinon": "^9.0.10", + "uint8arrays": "^2.0.5" }, "dependencies": { - "cids": "^1.0.0", - "err-code": "^2.0.0", - "hamt-sharding": "^1.0.0", + "cids": "^1.1.5", + "err-code": "^3.0.0", + "hamt-sharding": "^2.0.0", "ipfs-unixfs": "^2.0.4", - "ipfs-utils": "^5.0.0", "it-last": "^1.0.1", "multihashing-async": "^2.0.0" + }, + "types": "dist/src/index.d.ts", + "files": [ + "src", + "dist" + ], + "eslintConfig": { + "extends": "ipfs" } } diff --git a/packages/ipfs-unixfs-exporter/src/index.js b/packages/ipfs-unixfs-exporter/src/index.js index 8a30a456..257af8f1 100644 --- a/packages/ipfs-unixfs-exporter/src/index.js +++ b/packages/ipfs-unixfs-exporter/src/index.js @@ -5,6 +5,69 @@ const CID = require('cids') const resolve = require('./resolvers') const last = require('it-last') +/** + * @typedef {import('ipfs-unixfs')} UnixFS + * @typedef {import('ipld-dag-pb').DAGNode} DAGNode + * + * @typedef {object} UnixFSFile + * @property {'file'} type + * @property {string} name + * @property {string} path + * @property {CID} cid + * @property {number} depth + * @property {UnixFS} unixfs + * @property {DAGNode} node + * @property {(options?: ExporterOptions) => AsyncIterable} content + * + * @typedef {object} UnixFSDirectory + * @property {'directory'} type + * @property {string} name + * @property {string} path + * @property {CID} cid + * @property {number} depth + * @property {UnixFS} unixfs + * @property {DAGNode} node + * @property {(options?: ExporterOptions) => AsyncIterable} content + * + * @typedef {object} ObjectNode + * @property {'object'} type + * @property {string} name + * @property {string} path + * @property {CID} cid + * @property {number} depth + * @property {any} node + * + * @typedef {object} RawNode + * @property {'raw'} type + * @property {string} name + * @property {string} path + * @property {CID} cid + * @property {number} depth + * @property {Uint8Array} node + * @property {(options?: ExporterOptions) => AsyncIterable} content + * + * @typedef {object} IdentityNode + * @property {'identity'} type + * @property {string} name + * @property {string} path + * @property {CID} cid + * @property {number} depth + * @property {Uint8Array} node + * @property {(options?: ExporterOptions) => AsyncIterable} content + * + * @typedef {UnixFSFile | UnixFSDirectory | ObjectNode | RawNode | IdentityNode} UnixFSEntry + */ + +/** + * @typedef {object} IPLDResolver + * @property {(cid: CID, options?: any) => Promise} get + * @property {(node: any, codec: number, options?: any) => Promise} put + * + * @typedef {object} ExporterOptions + * @property {number} [offset=0] + * @property {number} [length] + */ + const toPathComponents = (path = '') => { // split on / unless escaped with \ return (path @@ -13,6 +76,9 @@ const toPathComponents = (path = '') => { .filter(Boolean) } +/** + * @param {string|Uint8Array|CID} path + */ const cidAndRest = (path) => { if (path instanceof Uint8Array) { return { @@ -44,7 +110,12 @@ const cidAndRest = (path) => { throw errCode(new Error(`Unknown path type ${path}`), 'ERR_BAD_PATH') } -const walkPath = async function * (path, ipld, options) { +/** + * @param {string | CID} path + * @param {IPLDResolver} ipld + * @param {ExporterOptions} [options] + */ +const walkPath = async function * (path, ipld, options = {}) { let { cid, toResolve @@ -76,34 +147,62 @@ const walkPath = async function * (path, ipld, options) { } } -const exporter = (path, ipld, options) => { - return last(walkPath(path, ipld, options)) +/** + * @param {string | CID} path + * @param {IPLDResolver} ipld + * @param {ExporterOptions} [options] + */ +const exporter = async (path, ipld, options = {}) => { + const result = await last(walkPath(path, ipld, options)) + + if (!result) { + throw errCode(new Error(`Could not resolve ${path}`), 'ERR_NOT_FOUND') + } + + return result } -const recursive = async function * (path, ipld, options) { +/** + * @param {string | CID} path + * @param {IPLDResolver} ipld + * @param {ExporterOptions} [options] + */ +const recursive = async function * (path, ipld, options = {}) { const node = await exporter(path, ipld, options) + if (!node) { + return + } + yield node - if (node.unixfs && node.unixfs.type.includes('dir')) { + if (node.type === 'directory') { for await (const child of recurse(node, options)) { yield child } } + /** + * @param {UnixFSDirectory} node + * @param {ExporterOptions} options + * @returns {AsyncGenerator} + */ async function * recurse (node, options) { for await (const file of node.content(options)) { yield file - if (file.unixfs.type.includes('dir')) { - for await (const subFile of recurse(file, options)) { - yield subFile - } + if (file instanceof Uint8Array) { + continue + } + + if (file.type === 'directory') { + yield * recurse(file, options) } } } } +exporter.path = walkPath +exporter.recursive = recursive + module.exports = exporter -module.exports.path = walkPath -module.exports.recursive = recursive diff --git a/packages/ipfs-unixfs-exporter/src/resolvers/dag-cbor.js b/packages/ipfs-unixfs-exporter/src/resolvers/dag-cbor.js index 0c88360b..027fae45 100644 --- a/packages/ipfs-unixfs-exporter/src/resolvers/dag-cbor.js +++ b/packages/ipfs-unixfs-exporter/src/resolvers/dag-cbor.js @@ -3,6 +3,9 @@ const CID = require('cids') const errCode = require('err-code') +/** + * @type {import('./').Resolver} + */ const resolve = async (cid, name, path, toResolve, resolve, depth, ipld, options) => { const node = await ipld.get(cid, options) let subObject = node @@ -19,6 +22,7 @@ const resolve = async (cid, name, path, toResolve, resolve, depth, ipld, options if (CID.isCID(subObject[prop])) { return { entry: { + type: 'object', name, path, cid, @@ -43,6 +47,7 @@ const resolve = async (cid, name, path, toResolve, resolve, depth, ipld, options return { entry: { + type: 'object', name, path, cid, diff --git a/packages/ipfs-unixfs-exporter/src/resolvers/identity.js b/packages/ipfs-unixfs-exporter/src/resolvers/identity.js index 8a54051e..83f57db5 100644 --- a/packages/ipfs-unixfs-exporter/src/resolvers/identity.js +++ b/packages/ipfs-unixfs-exporter/src/resolvers/identity.js @@ -5,8 +5,18 @@ const extractDataFromBlock = require('../utils/extract-data-from-block') const validateOffsetAndLength = require('../utils/validate-offset-and-length') const mh = require('multihashing-async').multihash +/** + * @typedef {import('../').ExporterOptions} ExporterOptions + */ + +/** + * @param {Uint8Array} node + */ const rawContent = (node) => { - return function * (options = {}) { + /** + * @param {ExporterOptions} options + */ + async function * contentGenerator (options = {}) { const { offset, length @@ -14,8 +24,13 @@ const rawContent = (node) => { yield extractDataFromBlock(node, 0, offset, offset + length) } + + return contentGenerator } +/** + * @type {import('./').Resolver} + */ const resolve = async (cid, name, path, toResolve, resolve, depth, ipld, options) => { if (toResolve.length) { throw errCode(new Error(`No link named ${path} found in raw node ${cid.toBaseEncodedString()}`), 'ERR_NOT_FOUND') @@ -25,12 +40,13 @@ const resolve = async (cid, name, path, toResolve, resolve, depth, ipld, options return { entry: { + type: 'identity', name, path, cid, - node: buf, content: rawContent(buf.digest), - depth + depth, + node: buf.digest } } } diff --git a/packages/ipfs-unixfs-exporter/src/resolvers/index.js b/packages/ipfs-unixfs-exporter/src/resolvers/index.js index 68163c99..8e3316b5 100644 --- a/packages/ipfs-unixfs-exporter/src/resolvers/index.js +++ b/packages/ipfs-unixfs-exporter/src/resolvers/index.js @@ -2,6 +2,33 @@ const errCode = require('err-code') +/** + * @typedef {import('../').IPLDResolver} IPLDResolver + * @typedef {import('../').ExporterOptions} ExporterOptions + * @typedef {import('../').UnixFSEntry} UnixFSEntry + * @typedef {import('cids')} CID + */ + +/** + * @typedef {object} NextResult + * @property {CID} cid + * @property {string} name + * @property {string} path + * @property {string[]} toResolve + * + * @typedef {object} ResolveResult + * @property {UnixFSEntry} entry + * @property {NextResult} [next] + */ + +/** + * + * @typedef {(cid: CID, name: string, path: string, toResolve: string[], depth: number, ipld: IPLDResolver, options: ExporterOptions) => Promise} Resolve + * + * @typedef {(cid: CID, name: string, path: string, toResolve: string[], resolve: Resolve, depth: number, ipld: IPLDResolver, options: ExporterOptions) => Promise} Resolver + * + * @type {{ [ key: string ]: Resolver }} + */ const resolvers = { 'dag-pb': require('./unixfs-v1'), raw: require('./raw'), @@ -9,7 +36,10 @@ const resolvers = { identity: require('./identity') } -const resolve = (cid, name, path, toResolve, depth, ipld, options) => { +/** + * @type {Resolve} + */ +function resolve (cid, name, path, toResolve, depth, ipld, options) { const resolver = resolvers[cid.codec] if (!resolver) { diff --git a/packages/ipfs-unixfs-exporter/src/resolvers/raw.js b/packages/ipfs-unixfs-exporter/src/resolvers/raw.js index 6dd96185..d85573e5 100644 --- a/packages/ipfs-unixfs-exporter/src/resolvers/raw.js +++ b/packages/ipfs-unixfs-exporter/src/resolvers/raw.js @@ -4,8 +4,18 @@ const errCode = require('err-code') const extractDataFromBlock = require('../utils/extract-data-from-block') const validateOffsetAndLength = require('../utils/validate-offset-and-length') +/** + * @typedef {import('../').ExporterOptions} ExporterOptions + */ + +/** + * @param {Uint8Array} node + */ const rawContent = (node) => { - return function * (options = {}) { + /** + * @param {ExporterOptions} options + */ + async function * contentGenerator (options = {}) { const { offset, length @@ -13,8 +23,13 @@ const rawContent = (node) => { yield extractDataFromBlock(node, 0, offset, offset + length) } + + return contentGenerator } +/** + * @type {import('./').Resolver} + */ const resolve = async (cid, name, path, toResolve, resolve, depth, ipld, options) => { if (toResolve.length) { throw errCode(new Error(`No link named ${path} found in raw node ${cid.toBaseEncodedString()}`), 'ERR_NOT_FOUND') @@ -24,12 +39,13 @@ const resolve = async (cid, name, path, toResolve, resolve, depth, ipld, options return { entry: { + type: 'raw', name, path, cid, - node: buf, content: rawContent(buf), - depth + depth, + node: buf } } } diff --git a/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/directory.js b/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/directory.js index caadbec5..0a7feb10 100644 --- a/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/directory.js +++ b/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/directory.js @@ -1,7 +1,17 @@ 'use strict' -const directoryContent = (cid, node, unixfs, path, resolve, depth, ipld, options) => { - return async function * (options = {}) { +/** + * @typedef {import('../../../').ExporterOptions} ExporterOptions + * @typedef {import('../').UnixfsV1DirectoryContent} UnixfsV1DirectoryContent + * + * @type {import('../').UnixfsV1Resolver} + */ +const directoryContent = (cid, node, unixfs, path, resolve, depth, ipld) => { + /** + * @param {ExporterOptions} [options] + * @returns {UnixfsV1DirectoryContent} + */ + async function * yieldDirectoryContent (options = {}) { const offset = options.offset || 0 const length = options.length || node.Links.length const links = node.Links.slice(offset, length) @@ -9,9 +19,13 @@ const directoryContent = (cid, node, unixfs, path, resolve, depth, ipld, options for (const link of links) { const result = await resolve(link.Hash, link.Name, `${path}/${link.Name}`, [], depth + 1, ipld, options) - yield result.entry + if (result.entry) { + yield result.entry + } } } + + return yieldDirectoryContent } module.exports = directoryContent diff --git a/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/file.js b/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/file.js index 7da322b3..31806295 100644 --- a/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/file.js +++ b/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/file.js @@ -5,6 +5,19 @@ const validateOffsetAndLength = require('../../../utils/validate-offset-and-leng const UnixFS = require('ipfs-unixfs') const errCode = require('err-code') +/** + * @typedef {import('../../../').ExporterOptions} ExporterOptions + * @typedef {import('../../../').IPLDResolver} IPLDResolver + * @typedef {import('ipld-dag-pb').DAGNode} DAGNode + * + * @param {IPLDResolver} ipld + * @param {DAGNode} node + * @param {number} start + * @param {number} end + * @param {number} streamPosition + * @param {ExporterOptions} options + * @returns {AsyncIterable} + */ async function * emitBytes (ipld, node, start, end, streamPosition = 0, options) { // a `raw` node if (node instanceof Uint8Array) { @@ -28,9 +41,7 @@ async function * emitBytes (ipld, node, start, end, streamPosition = 0, options) } // might be a unixfs `raw` node or have data on intermediate nodes - const nodeHasData = Boolean(file.data && file.data.length) - - if (nodeHasData) { + if (file.data && file.data.length) { const buf = extractDataFromBlock(file.data, streamPosition, start, end) if (buf.length) { @@ -64,10 +75,20 @@ async function * emitBytes (ipld, node, start, end, streamPosition = 0, options) } } +/** + * @type {import('../').UnixfsV1Resolver} + */ const fileContent = (cid, node, unixfs, path, resolve, depth, ipld) => { - return (options = {}) => { + /** + * @param {ExporterOptions} options + */ + function yieldFileContent (options = {}) { const fileSize = unixfs.fileSize() + if (fileSize === undefined) { + throw new Error('File was a directory') + } + const { offset, length @@ -78,6 +99,8 @@ const fileContent = (cid, node, unixfs, path, resolve, depth, ipld) => { return emitBytes(ipld, node, start, end, 0, options) } + + return yieldFileContent } module.exports = fileContent diff --git a/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/hamt-sharded-directory.js b/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/hamt-sharded-directory.js index 965e1b47..f8a4f97d 100644 --- a/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/hamt-sharded-directory.js +++ b/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/hamt-sharded-directory.js @@ -1,11 +1,36 @@ 'use strict' +/** + * @typedef {import('../../../').ExporterOptions} ExporterOptions + * @typedef {import('ipld-dag-pb').DAGNode} DAGNode + * @typedef {import('../../').Resolve} Resolve + * @typedef {import('../../../').IPLDResolver} IPLDResolver + * @typedef {import('../').UnixfsV1DirectoryContent} UnixfsV1DirectoryContent + * + * @type {import('../').UnixfsV1Resolver} + */ const hamtShardedDirectoryContent = (cid, node, unixfs, path, resolve, depth, ipld) => { - return (options = {}) => { + /** + * @param {ExporterOptions} options + * + */ + function yieldHamtDirectoryContent (options = {}) { return listDirectory(node, path, resolve, depth, ipld, options) } + + return yieldHamtDirectoryContent } +/** + * @param {DAGNode} node + * @param {string} path + * @param {Resolve} resolve + * @param {number} depth + * @param {IPLDResolver} ipld + * @param {ExporterOptions} options + * + * @returns {UnixfsV1DirectoryContent} + */ async function * listDirectory (node, path, resolve, depth, ipld, options) { const links = node.Links @@ -13,7 +38,7 @@ async function * listDirectory (node, path, resolve, depth, ipld, options) { const name = link.Name.substring(2) if (name) { - const result = await resolve(link.Hash, name, `${path}/${name}`, [], depth + 1, ipld) + const result = await resolve(link.Hash, name, `${path}/${name}`, [], depth + 1, ipld, options) yield result.entry } else { diff --git a/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/raw.js b/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/raw.js index cbef4af6..b385877b 100644 --- a/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/raw.js +++ b/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/content/raw.js @@ -3,9 +3,21 @@ const extractDataFromBlock = require('../../../utils/extract-data-from-block') const validateOffsetAndLength = require('../../../utils/validate-offset-and-length') +/** + * @typedef {import('../../../').ExporterOptions} ExporterOptions + * + * @type {import('../').UnixfsV1Resolver} + */ const rawContent = (cid, node, unixfs, path, resolve, depth, ipld) => { - return function * (options = {}) { - const size = node.length + /** + * @param {ExporterOptions} options + */ + function * yieldRawContent (options = {}) { + if (!unixfs.data) { + throw new Error('Raw block had no data') + } + + const size = unixfs.data.length const { offset, @@ -14,6 +26,8 @@ const rawContent = (cid, node, unixfs, path, resolve, depth, ipld) => { yield extractDataFromBlock(unixfs.data, 0, offset, offset + length) } + + return yieldRawContent } module.exports = rawContent diff --git a/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/index.js b/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/index.js index 99fca6af..7fe4cfa1 100644 --- a/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/index.js +++ b/packages/ipfs-unixfs-exporter/src/resolvers/unixfs-v1/index.js @@ -4,21 +4,50 @@ const errCode = require('err-code') const UnixFS = require('ipfs-unixfs') const findShardCid = require('../../utils/find-cid-in-shard') +/** + * @typedef {import('../../').ExporterOptions} ExporterOptions + * @typedef {import('../../').IPLDResolver} IPLDResolver + * @typedef {import('../').UnixFSEntry} UnixFSEntry + * @typedef {import('cids')} CID + * @typedef {import('ipld-dag-pb').DAGNode} DAGNode + * @typedef {import('../').Resolve} Resolve + */ + +/** + * @param {import('ipld-dag-pb').DAGNode} node + * @param {string} name + */ const findLinkCid = (node, name) => { const link = node.Links.find(link => link.Name === name) return link && link.Hash } +/** + * @typedef {AsyncIterable | Iterable} UnixfsV1FileContent + * @typedef {AsyncIterable | Iterable} UnixfsV1DirectoryContent + * + * @typedef {UnixfsV1FileContent | UnixfsV1DirectoryContent} UnixfsV1Content + * @typedef {(cid: CID, node: DAGNode, unixfs: UnixFS, path: string, resolve: Resolve, depth: number, ipld: IPLDResolver) => (options: ExporterOptions) => UnixfsV1Content } UnixfsV1Resolver + * + * @type {{ [key: string]: UnixfsV1Resolver }} + */ const contentExporters = { raw: require('./content/file'), file: require('./content/file'), directory: require('./content/directory'), 'hamt-sharded-directory': require('./content/hamt-sharded-directory'), - metadata: (cid, node, unixfs, path, resolve, depth, ipld) => {}, - symlink: (cid, node, unixfs, path, resolve, depth, ipld) => {} + metadata: (cid, node, unixfs, path, resolve, depth, ipld) => { + return () => [] + }, + symlink: (cid, node, unixfs, path, resolve, depth, ipld) => { + return () => [] + } } +/** + * @type {import('../').Resolver} + */ const unixFsResolver = async (cid, name, path, toResolve, resolve, depth, ipld, options) => { const node = await ipld.get(cid, options) let unixfs @@ -60,20 +89,22 @@ const unixFsResolver = async (cid, name, path, toResolve, resolve, depth, ipld, next = { cid: linkCid, toResolve, - name: nextName, + name: nextName || '', path: nextPath } } return { entry: { + type: unixfs.isDirectory() ? 'directory' : 'file', name, path, cid, - node, - content: contentExporters[unixfs.type](cid, node, unixfs, path, resolve, depth, ipld, options), + // @ts-ignore + content: contentExporters[unixfs.type](cid, node, unixfs, path, resolve, depth, ipld), unixfs, - depth + depth, + node }, next } diff --git a/packages/ipfs-unixfs-exporter/src/utils/extract-data-from-block.js b/packages/ipfs-unixfs-exporter/src/utils/extract-data-from-block.js index ba15bc0a..4de42822 100644 --- a/packages/ipfs-unixfs-exporter/src/utils/extract-data-from-block.js +++ b/packages/ipfs-unixfs-exporter/src/utils/extract-data-from-block.js @@ -1,5 +1,11 @@ 'use strict' +/** + * @param {Uint8Array} block + * @param {number} blockStart + * @param {number} requestedStart + * @param {number} requestedEnd + */ module.exports = function extractDataFromBlock (block, blockStart, requestedStart, requestedEnd) { const blockLength = block.length const blockEnd = blockStart + blockLength diff --git a/packages/ipfs-unixfs-exporter/src/utils/find-cid-in-shard.js b/packages/ipfs-unixfs-exporter/src/utils/find-cid-in-shard.js index 51067151..5d4def9c 100644 --- a/packages/ipfs-unixfs-exporter/src/utils/find-cid-in-shard.js +++ b/packages/ipfs-unixfs-exporter/src/utils/find-cid-in-shard.js @@ -1,16 +1,23 @@ 'use strict' -const Bucket = require('hamt-sharding/src/bucket') +const { Bucket, createHAMT } = require('hamt-sharding') const multihashing = require('multihashing-async') -const uint8ArrayFromString = require('uint8arrays/from-string') + +/** + * @typedef {import('../').ExporterOptions} ExporterOptions + * @typedef {import('../').IPLDResolver} IPLDResolver + * @typedef {import('cids')} CID + */ // FIXME: this is copy/pasted from ipfs-unixfs-importer/src/dir-sharded.js -const hashFn = async function (value) { - const buf = uint8ArrayFromString(value) +/** + * @param {Uint8Array} buf + */ +const hashFn = async function (buf) { const hash = await multihashing(buf, 'murmur3-128') // Multihashing inserts preamble of 2 bytes. Remove it. - // Also, murmur3 outputs 128 bit but, accidently, IPFS Go's + // Also, murmur3 outputs 128 bit but, accidentally, IPFS Go's // implementation only uses the first 64, so we must do the same // for parity.. const justHash = hash.slice(2, 10) @@ -23,8 +30,12 @@ const hashFn = async function (value) { return result } -hashFn.code = 0x22 // TODO: get this from multihashing-async? +/** + * @param {import('ipld-dag-pb').DAGLink[]} links + * @param {Bucket} bucket + * @param {Bucket} rootBucket + */ const addLinksToHamtBucket = (links, bucket, rootBucket) => { return Promise.all( links.map(link => { @@ -32,7 +43,8 @@ const addLinksToHamtBucket = (links, bucket, rootBucket) => { const pos = parseInt(link.Name, 16) return bucket._putObjectAt(pos, new Bucket({ - hashFn + hash: rootBucket._options.hash, + bits: rootBucket._options.bits }, bucket, pos)) } @@ -41,14 +53,20 @@ const addLinksToHamtBucket = (links, bucket, rootBucket) => { ) } +/** + * @param {number} position + */ const toPrefix = (position) => { return position - .toString('16') + .toString(16) .toUpperCase() .padStart(2, '0') .substring(0, 2) } +/** + * @param {import('hamt-sharding').Bucket.BucketPosition} position + */ const toBucketPath = (position) => { let bucket = position.bucket const path = [] @@ -64,16 +82,30 @@ const toBucketPath = (position) => { return path.reverse() } +/** + * @typedef {object} ShardTraversalContext + * @property {number} hamtDepth + * @property {Bucket} rootBucket + * @property {Bucket} lastBucket + * + * @param {import('ipld-dag-pb').DAGNode} node + * @param {string} name + * @param {IPLDResolver} ipld + * @param {ShardTraversalContext} [context] + * @param {ExporterOptions} [options] + * @returns {Promise} + */ const findShardCid = async (node, name, ipld, context, options) => { if (!context) { + const rootBucket = createHAMT({ + hashFn + }) + context = { - rootBucket: new Bucket({ - hashFn - }), - hamtDepth: 1 + rootBucket, + hamtDepth: 1, + lastBucket: rootBucket } - - context.lastBucket = context.rootBucket } await addLinksToHamtBucket(node.Links, context.lastBucket, context.rootBucket) @@ -82,7 +114,7 @@ const findShardCid = async (node, name, ipld, context, options) => { let prefix = toPrefix(position.pos) const bucketPath = toBucketPath(position) - if (bucketPath.length > (context.hamtDepth)) { + if (bucketPath.length > context.hamtDepth) { context.lastBucket = bucketPath[context.hamtDepth] prefix = toPrefix(context.lastBucket._posAtParent) @@ -94,12 +126,12 @@ const findShardCid = async (node, name, ipld, context, options) => { if (entryPrefix !== prefix) { // not the entry or subshard we're looking for - return + return false } if (entryName && entryName !== name) { // not the entry we're looking for - return + return false } return true diff --git a/packages/ipfs-unixfs-exporter/src/utils/validate-offset-and-length.js b/packages/ipfs-unixfs-exporter/src/utils/validate-offset-and-length.js index d1eb4185..1786302f 100644 --- a/packages/ipfs-unixfs-exporter/src/utils/validate-offset-and-length.js +++ b/packages/ipfs-unixfs-exporter/src/utils/validate-offset-and-length.js @@ -2,6 +2,11 @@ const errCode = require('err-code') +/** + * @param {number} size + * @param {number} [offset] + * @param {number} [length] + */ const validateOffsetAndLength = (size, offset, length) => { if (!offset) { offset = 0 diff --git a/packages/ipfs-unixfs-exporter/test/exporter-sharded.spec.js b/packages/ipfs-unixfs-exporter/test/exporter-sharded.spec.js index 626beee0..ac48618b 100644 --- a/packages/ipfs-unixfs-exporter/test/exporter-sharded.spec.js +++ b/packages/ipfs-unixfs-exporter/test/exporter-sharded.spec.js @@ -2,7 +2,9 @@ 'use strict' const { expect } = require('aegir/utils/chai') +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') const UnixFS = require('ipfs-unixfs') const mh = require('multihashing-async').multihash @@ -19,18 +21,31 @@ const { const blockApi = require('./helpers/block') const uint8ArrayConcat = require('uint8arrays/concat') +/** + * @typedef {import('cids')} CID + */ + const SHARD_SPLIT_THRESHOLD = 10 describe('exporter sharded', function () { this.timeout(30000) + /** @type {import('../src').IPLDResolver} */ let ipld + /** @type {import('ipfs-unixfs-importer').BlockAPI} */ let block + /** + * @param {number} numFiles + */ const createShard = (numFiles) => { return createShardWithFileNames(numFiles, (index) => `file-${index}`) } + /** + * @param {number} numFiles + * @param {(index: number) => string} fileName + */ const createShardWithFileNames = (numFiles, fileName) => { const files = new Array(numFiles).fill(0).map((_, index) => ({ path: fileName(index), @@ -40,11 +55,20 @@ describe('exporter sharded', function () { return createShardWithFiles(files) } + /** + * @param {{ path: string, content: Uint8Array }[] } files + */ const createShardWithFiles = async (files) => { - return (await last(importer(files, block, { + const result = await last(importer(files, block, { shardSplitThreshold: SHARD_SPLIT_THRESHOLD, wrapWithDirectory: true - }))).cid + })) + + if (!result) { + throw new Error('Failed to make shard') + } + + return result.cid } before(async () => { @@ -53,6 +77,7 @@ describe('exporter sharded', function () { }) it('exports a sharded directory', async () => { + /** @type {{ [key: string]: { content: Uint8Array, cid?: CID }}} */ const files = {} for (let i = 0; i < (SHARD_SPLIT_THRESHOLD + 1); i++) { @@ -69,10 +94,18 @@ describe('exporter sharded', function () { shardSplitThreshold: SHARD_SPLIT_THRESHOLD })) - const dirCid = imported.pop().cid + const dirCid = imported.pop()?.cid + + if (!dirCid) { + throw new Error('No directory CID found') + } // store the CIDs, we will validate them later imported.forEach(imported => { + if (!imported.path) { + throw new Error('Imported file did not have a path') + } + files[imported.path].cid = imported.cid }) @@ -85,15 +118,28 @@ describe('exporter sharded', function () { expect(exported.cid.equals(dirCid)).to.be.true() + if (exported.type !== 'directory') { + throw new Error('Expected directory') + } + + if (!exported.content) { + throw new Error('No content found on exported entry') + } + const dirFiles = await all(exported.content()) expect(dirFiles.length).to.equal(Object.keys(files).length) for (let i = 0; i < dirFiles.length; i++) { const dirFile = dirFiles[i] + + if (dirFile.type !== 'file') { + throw new Error('Expected file') + } + const data = uint8ArrayConcat(await all(dirFile.content())) // validate the CID - expect(files[dirFile.name].cid.equals(dirFile.cid)).to.be.true() + expect(files[dirFile.name]).to.have.property('cid').that.deep.equals(dirFile.cid) // validate the exported file content expect(files[dirFile.name].content).to.deep.equal(data) @@ -104,19 +150,30 @@ describe('exporter sharded', function () { const numFiles = 31 const dirCid = await createShard(numFiles) const exported = await exporter(dirCid, ipld) + + if (exported.type !== 'directory') { + throw new Error('Unexpected type') + } + const files = await all(exported.content()) expect(files.length).to.equal(numFiles) expect(exported.unixfs.type).to.equal('hamt-sharded-directory') - files.forEach(file => expect(file.unixfs.type).to.equal('file')) + files.forEach(file => { + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + + expect(file.unixfs.type).to.equal('file') + }) }) it('exports one file from a sharded directory', async () => { const dirCid = await createShard(31) const exported = await exporter(`/ipfs/${dirCid.toBaseEncodedString()}/file-14`, ipld) - expect(exported.name).to.equal('file-14') + expect(exported).to.have.property('name', 'file-14') }) it('exports one file from a sharded directory sub shard', async () => { @@ -174,11 +231,19 @@ describe('exporter sharded', function () { expect(exported[2].name).to.equal('bar') expect(exported[3].name).to.equal('baz') + if (exported[3].type !== 'directory') { + throw new Error('Expected file') + } + const files = await all(exported[3].content()) expect(files.length).to.equal(31) files.forEach(file => { + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + expect(file.unixfs.type).to.equal('file') }) }) diff --git a/packages/ipfs-unixfs-exporter/test/exporter-subtree.spec.js b/packages/ipfs-unixfs-exporter/test/exporter-subtree.spec.js index 9ee4caee..363b95dd 100644 --- a/packages/ipfs-unixfs-exporter/test/exporter-subtree.spec.js +++ b/packages/ipfs-unixfs-exporter/test/exporter-subtree.spec.js @@ -2,10 +2,11 @@ 'use strict' const { expect } = require('aegir/utils/chai') +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') const importer = require('ipfs-unixfs-importer') -const mc = require('multicodec') const all = require('it-all') const last = require('it-last') const blockApi = require('./helpers/block') @@ -17,7 +18,9 @@ const ONE_MEG = Math.pow(1024, 2) const exporter = require('./../src') describe('exporter subtree', () => { + /** @type {import('../src').IPLDResolver} */ let ipld + /** @type {import('ipfs-unixfs-importer').BlockAPI} */ let block before(async () => { @@ -36,12 +39,20 @@ describe('exporter subtree', () => { content }], block)) + if (!imported) { + throw new Error('Nothing imported') + } + const exported = await exporter(`${imported.cid.toBaseEncodedString()}/level-1/200Bytes.txt`, ipld) expect(exported).to.have.property('cid') expect(exported.name).to.equal('200Bytes.txt') expect(exported.path).to.equal(`${imported.cid.toBaseEncodedString()}/level-1/200Bytes.txt`) + if (exported.type !== 'file') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(exported.content())) expect(data).to.deep.equal(content) }) @@ -58,7 +69,16 @@ describe('exporter subtree', () => { path: './level-1/level-2' }], block)) + if (!imported) { + throw new Error('Nothing imported') + } + const exported = await exporter(`${imported.cid.toBaseEncodedString()}/level-1`, ipld) + + if (exported.type !== 'directory') { + throw new Error('Unexpected type') + } + const files = await all(exported.content()) expect(files.length).to.equal(2) @@ -68,6 +88,10 @@ describe('exporter subtree', () => { expect(files[1].name).to.equal('level-2') expect(files[1].path).to.equal(`${imported.cid.toBaseEncodedString()}/level-1/level-2`) + if (files[0].type !== 'file') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(files[0].content())) expect(data).to.deep.equal(content) }) @@ -78,6 +102,10 @@ describe('exporter subtree', () => { content: randomBytes(ONE_MEG) }], block)) + if (!imported) { + throw new Error('Nothing imported') + } + try { await exporter(`${imported.cid.toBaseEncodedString()}/doesnotexist`, ipld) } catch (err) { @@ -85,31 +113,6 @@ describe('exporter subtree', () => { } }) - it('exports starting from non-protobuf node', async () => { - const content = uint8ArrayConcat(await all(randomBytes(ONE_MEG))) - - const imported = await last(importer([{ - path: './level-1/200Bytes.txt', - content - }], block, { - wrapWithDirectory: true - })) - - const cborNodeCid = await ipld.put({ - a: { - file: imported.cid - } - }, mc.DAG_CBOR) - - const exported = await exporter(`${cborNodeCid.toBaseEncodedString()}/a/file/level-1/200Bytes.txt`, ipld) - - expect(exported.name).to.equal('200Bytes.txt') - expect(exported.path).to.equal(`${cborNodeCid.toBaseEncodedString()}/a/file/level-1/200Bytes.txt`) - - const data = uint8ArrayConcat(await all(exported.content())) - expect(data).to.deep.equal(content) - }) - it('uses .path to export all components of a path', async () => { const content = uint8ArrayConcat(await all(randomBytes(ONE_MEG))) @@ -126,6 +129,10 @@ describe('exporter subtree', () => { content }], block)) + if (!imported) { + throw new Error('Nothing imported') + } + const exported = await all(exporter.path(`${imported.cid.toBaseEncodedString()}/level-1/level-2/200Bytes.txt`, ipld)) expect(exported.length).to.equal(4) diff --git a/packages/ipfs-unixfs-exporter/test/exporter.spec.js b/packages/ipfs-unixfs-exporter/test/exporter.spec.js index 7630d19c..da56c7fb 100644 --- a/packages/ipfs-unixfs-exporter/test/exporter.spec.js +++ b/packages/ipfs-unixfs-exporter/test/exporter.spec.js @@ -2,7 +2,9 @@ 'use strict' const { expect } = require('aegir/utils/chai') +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') const UnixFS = require('ipfs-unixfs') const CID = require('cids') @@ -18,7 +20,7 @@ const all = require('it-all') const last = require('it-last') const first = require('it-first') const randomBytes = require('it-buffer-stream') -const AbortController = require('abort-controller') +const { AbortController } = require('native-abort-controller') const blockApi = require('./helpers/block') const uint8ArrayFromString = require('uint8arrays/from-string') const uint8ArrayToString = require('uint8arrays/to-string') @@ -27,9 +29,13 @@ const uint8ArrayConcat = require('uint8arrays/concat') const ONE_MEG = Math.pow(1024, 2) describe('exporter', () => { + /** @type {import('../src').IPLDResolver} */ let ipld + /** @type {import('ipfs-unixfs-importer').BlockAPI} */ let block + /** @type {Uint8Array} */ let bigFile + /** @type {Uint8Array} */ let smallFile before(async () => { @@ -37,6 +43,12 @@ describe('exporter', () => { smallFile = uint8ArrayConcat(await all(randomBytes(200))) }) + /** + * @param {object} [options] + * @param {string} [options.type='file'] + * @param {Uint8Array} [options.content] + * @param {DAGLink[]} [options.links=[]] + */ async function dagPut (options = {}) { options.type = options.type || 'file' options.content = options.content || Uint8Array.from([0x01, 0x02, 0x03]) @@ -56,6 +68,14 @@ describe('exporter', () => { return { file: file, node: node, cid: cid } } + /** + * @param {object} options + * @param {Uint8Array} options.file + * @param {'balanced' | 'flat' | 'trickle'} [options.strategy='balanced'] + * @param {string} [options.path='/foo'] + * @param {number} [options.maxChunkSize] + * @param {boolean} [options.rawLeaves] + */ async function addTestFile ({ file, strategy = 'balanced', path = '/foo', maxChunkSize, rawLeaves }) { const result = await all(importer([{ path, @@ -63,23 +83,38 @@ describe('exporter', () => { }], block, { strategy, rawLeaves, - chunkerOptions: { - maxChunkSize - } + maxChunkSize })) return result[0].cid } + /** + * @param {object} options + * @param {Uint8Array} options.file + * @param {number} [options.offset] + * @param {number} [options.length] + * @param {'balanced' | 'flat' | 'trickle'} [options.strategy='balanced'] + * @param {string} [options.path='/foo'] + * @param {number} [options.maxChunkSize] + * @param {boolean} [options.rawLeaves] + */ async function addAndReadTestFile ({ file, offset, length, strategy = 'balanced', path = '/foo', maxChunkSize, rawLeaves }) { const cid = await addTestFile({ file, strategy, path, maxChunkSize, rawLeaves }) const entry = await exporter(cid, ipld) + if (entry.type !== 'file' && entry.type !== 'raw') { + throw new Error('Unexpected type') + } + return uint8ArrayConcat(await all(entry.content({ offset, length }))) } + /** + * @param {'balanced' | 'flat' | 'trickle'} strategy + */ async function checkBytesThatSpanBlocks (strategy) { const bytesInABlock = 262144 const bytes = new Uint8Array(bytesInABlock + 100) @@ -98,8 +133,14 @@ describe('exporter', () => { expect(data).to.deep.equal(Uint8Array.from([1, 2, 3])) } + /** + * @param {import('../src').IPLDResolver} ipld + * @param {'file' | 'directory' | 'raw'} type + * @param {Uint8Array | ArrayLike | undefined} data + * @param {{ node: DAGNode, cid: CID }[]} children + */ async function createAndPersistNode (ipld, type, data, children) { - const file = new UnixFS(type, data ? Uint8Array.from(data) : undefined) + const file = new UnixFS({ type, data: data ? Uint8Array.from(data) : undefined }) const links = [] for (let i = 0; i < children.length; i++) { @@ -140,6 +181,10 @@ describe('exporter', () => { expect(file).to.have.property('cid') expect(file).to.have.property('path', result.cid.toBaseEncodedString()) + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(file.content())) expect(data).to.deep.equal(unmarsh.data) }) @@ -187,7 +232,16 @@ describe('exporter', () => { const node = await ipld.get(result.cid) const unmarsh = UnixFS.unmarshal(node.Data) + if (!unmarsh.data) { + throw new Error('Unexpected data') + } + const file = await exporter(result.cid, ipld) + + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(file.content({ offset, length @@ -208,7 +262,7 @@ describe('exporter', () => { hashAlg: mh.names['sha2-256'] }) - const chunk2 = new UnixFS('raw', content.slice(5)) + const chunk2 = new UnixFS({ type: 'raw', data: content.slice(5) }) const chunkNode2 = new DAGNode(chunk2.marshal()) const chunkCid2 = await ipld.put(chunkNode2, mc.DAG_PB, { cidVersion: 0, @@ -231,6 +285,11 @@ describe('exporter', () => { }) const exported = await exporter(fileCid, ipld) + + if (exported.type !== 'file') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(exported.content())) expect(data).to.deep.equal(content) }) @@ -239,7 +298,7 @@ describe('exporter', () => { const offset = 0 const length = 5 - const chunk = await dagPut({ content: randomBytes(100) }) + const chunk = await dagPut({ content: uint8ArrayConcat(await all(randomBytes(100))) }) const result = await dagPut({ content: uint8ArrayConcat(await all(randomBytes(100))), links: [ @@ -247,7 +306,16 @@ describe('exporter', () => { ] }) + if (!result.file.data) { + throw new Error('Expected data') + } + const file = await exporter(result.cid, ipld) + + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(file.content({ offset, length @@ -260,11 +328,15 @@ describe('exporter', () => { this.timeout(30 * 1000) const cid = await addTestFile({ - file: randomBytes(ONE_MEG * 6) + file: uint8ArrayConcat(await all(randomBytes(ONE_MEG * 6))) }) const file = await exporter(cid, ipld) + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + expect(file).to.have.property('path', cid.toBaseEncodedString()) expect(file.unixfs.fileSize()).to.equal(ONE_MEG * 6) }) @@ -283,6 +355,10 @@ describe('exporter', () => { const file = await exporter(cid, ipld) expect(file).to.have.property('path', cid.toBaseEncodedString()) + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(file.content({ offset, length @@ -337,7 +413,17 @@ describe('exporter', () => { }, { path: './level-1/level-2' }], block)) + + if (!importedDir) { + throw new Error('Nothing imported') + } + const dir = await exporter(importedDir.cid, ipld) + + if (dir.type !== 'directory') { + throw new Error('Unexpected type') + } + const files = await all(dir.content()) files.forEach(file => expect(file).to.have.property('cid')) @@ -351,14 +437,14 @@ describe('exporter', () => { ]) files - .filter(file => file.unixfs.type === 'dir') + .filter(file => file.type === 'directory' && file.unixfs.type === 'dir') .forEach(dir => { expect(dir).to.has.property('size', 0) }) expect( files - .map(file => file.unixfs.type === 'file') + .map(file => file.type === 'file' && file.unixfs.type === 'file') ).to.deep.equal([ true, false, @@ -376,7 +462,16 @@ describe('exporter', () => { path: './level-1' }], block)) + if (!importedDir) { + throw new Error('Nothing imported') + } + const dir = await exporter(importedDir.cid, ipld) + + if (dir.type !== 'directory') { + throw new Error('Unexpected type') + } + const files = await all(dir.content()) files.forEach(file => expect(file).to.have.property('cid')) @@ -391,7 +486,7 @@ describe('exporter', () => { expect( files - .map(file => file.unixfs.type === 'file') + .map(file => file.type === 'file' && file.unixfs.type === 'file') ).to.deep.equal([ true, false, @@ -523,7 +618,16 @@ describe('exporter', () => { rawLeaves: true })) + if (!imported) { + throw new Error('Nothing imported') + } + const file = await exporter(imported.cid, ipld) + + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(file.content())) expect(data).to.deep.equal(bigFile) @@ -533,7 +637,17 @@ describe('exporter', () => { const imported = await first(importer([{ path: 'empty' }], block)) + + if (!imported) { + throw new Error('Nothing imported') + } + const dir = await exporter(imported.cid, ipld) + + if (dir.type !== 'directory') { + throw new Error('Unexpected type') + } + const files = await all(dir.content()) expect(files.length).to.equal(0) }) @@ -649,6 +763,10 @@ describe('exporter', () => { }) const file = await exporter(cid, ipld) + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + while (offset < bigFile.length) { const result = uint8ArrayConcat(await all(file.content({ offset, @@ -694,6 +812,11 @@ describe('exporter', () => { ]) const file = await exporter(node.cid, ipld) + + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(file.content())) expect(data).to.deep.equal(Uint8Array.from([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07])) @@ -718,16 +841,21 @@ describe('exporter', () => { const internalNodes = await Promise.all([ createAndPersistNode(ipld, 'raw', [0x04, 0x05, 0x06, 0x07], [leaves[1]]), - createAndPersistNode(ipld, 'raw', null, [leaves[2]]) + createAndPersistNode(ipld, 'raw', undefined, [leaves[2]]) ]) - const node = await createAndPersistNode(ipld, 'file', null, [ + const node = await createAndPersistNode(ipld, 'file', undefined, [ leaves[0], internalNodes[0], internalNodes[1] ]) const file = await exporter(node.cid, ipld) + + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(file.content())) expect(data).to.deep.equal( @@ -745,6 +873,11 @@ describe('exporter', () => { ]) const file = await exporter(node.cid, ipld) + + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(file.content({ offset: 4 }))) @@ -762,7 +895,16 @@ describe('exporter', () => { rawLeaves: true })) + if (!imported) { + throw new Error('Nothing imported') + } + const file = await exporter(imported.cid, ipld) + + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + const buffers = await all(file.content()) buffers.forEach(buffer => { @@ -778,9 +920,17 @@ describe('exporter', () => { rawLeaves: true })) + if (!imported) { + throw new Error('Nothing imported') + } + const file = await exporter(imported.cid, ipld) expect(CID.isCID(file.cid)).to.be.true() + if (file.type !== 'raw') { + throw new Error('Unexpected type') + } + const data = uint8ArrayConcat(await all(file.content())) expect(data).to.deep.equal(smallFile) }) @@ -805,6 +955,10 @@ describe('exporter', () => { const cborNodeCid = await ipld.put(node, mc.DAG_CBOR) const exported = await exporter(`${cborNodeCid.toBaseEncodedString()}`, ipld) + if (exported.type !== 'object') { + throw new Error('Unexpected type') + } + expect(exported.node).to.deep.equal(node) }) @@ -854,6 +1008,10 @@ describe('exporter', () => { const exported = await exporter(cid, ipld) + if (exported.type !== 'file') { + throw new Error('Unexpected type') + } + try { await all(exported.content()) } catch (err) { @@ -884,6 +1042,10 @@ describe('exporter', () => { content: uint8ArrayFromString('hello world') }], block)) + if (!dir) { + throw new Error('Nothing imported') + } + const exported = await all(exporter.recursive(dir.cid, ipld)) const dirCid = dir.cid.toBaseEncodedString() @@ -913,6 +1075,11 @@ describe('exporter', () => { const cid = new CID(1, 'identity', hash) const exported = await exporter(cid, ipld) + + if (exported.type !== 'identity') { + throw new Error('Unexpected type') + } + const result = uint8ArrayConcat(await all(exported.content())) expect(result).to.deep.equal(data) @@ -925,6 +1092,11 @@ describe('exporter', () => { const cid = new CID(1, 'identity', hash) const exported = await exporter(cid, ipld) + + if (exported.type !== 'identity') { + throw new Error('Unexpected type') + } + const result = uint8ArrayConcat(await all(exported.content({ offset: 1 }))) @@ -938,6 +1110,11 @@ describe('exporter', () => { const cid = new CID(1, 'identity', hash) const exported = await exporter(cid, ipld) + + if (exported.type !== 'identity') { + throw new Error('Unexpected type') + } + const result = uint8ArrayConcat(await all(exported.content({ length: 1 }))) @@ -951,6 +1128,11 @@ describe('exporter', () => { const cid = new CID(1, 'identity', hash) const exported = await exporter(cid, ipld) + + if (exported.type !== 'identity') { + throw new Error('Unexpected type') + } + const result = uint8ArrayConcat(await all(exported.content({ offset: 3, length: 1 @@ -975,6 +1157,11 @@ describe('exporter', () => { // regular test IPLD is offline-only, we need to mimic what happens when // we try to get a block from the network const ipld = { + /** + * + * @param {CID} cid + * @param {{ signal: AbortSignal }} options + */ get: (cid, options) => { // promise will never resolve, so reject it when the abort signal is sent return new Promise((resolve, reject) => { @@ -985,6 +1172,7 @@ describe('exporter', () => { } } + // @ts-ignore ipld implementation incomplete await expect(exporter(cid, ipld, { signal: abortController.signal })).to.eventually.be.rejectedWith(message) diff --git a/packages/ipfs-unixfs-exporter/test/helpers/block.js b/packages/ipfs-unixfs-exporter/test/helpers/block.js index 74728a15..473f420d 100644 --- a/packages/ipfs-unixfs-exporter/test/helpers/block.js +++ b/packages/ipfs-unixfs-exporter/test/helpers/block.js @@ -1,21 +1,31 @@ 'use strict' -const DAG_PB = require('ipld-dag-pb') +const { + DAGNode, + util +} = require('ipld-dag-pb') const multicodec = require('multicodec') const mh = require('multihashing-async').multihash -module.exports = (ipld) => { +/** + * @param {import('../../src/').IPLDResolver} ipld + */ +function createBlockApi (ipld) { // make ipld behave like the block api, some tests need to pull // data from ipld so can't use a simple in-memory cid->block map - return { + /** @type {import('ipfs-unixfs-importer').BlockAPI} */ + const BlockApi = { put: async (buf, { cid }) => { const multihash = mh.decode(cid.multihash) + /** @type {any} */ + let obj = buf + if (cid.codec === 'dag-pb') { - buf = DAG_PB.util.deserialize(buf) + obj = util.deserialize(buf) } - await ipld.put(buf, cid.codec === 'dag-pb' ? multicodec.DAG_PB : multicodec.RAW, { + await ipld.put(obj, cid.codec === 'dag-pb' ? multicodec.DAG_PB : multicodec.RAW, { cidVersion: cid.version, hashAlg: multihash.code }) @@ -23,13 +33,18 @@ module.exports = (ipld) => { return { cid, data: buf } }, get: async (cid, options) => { - const node = await ipld.get(cid, options) + /** @type {Uint8Array} */ + let buf = await ipld.get(cid, options) - if (cid.codec === 'dag-pb') { - return node.serialize() + if (buf instanceof DAGNode) { + buf = buf.serialize() } - return { cid, data: node } + return { cid, data: buf } } } + + return BlockApi } + +module.exports = createBlockApi diff --git a/packages/ipfs-unixfs-exporter/test/helpers/collect-leaf-cids.js b/packages/ipfs-unixfs-exporter/test/helpers/collect-leaf-cids.js index 26354e69..e82ae581 100644 --- a/packages/ipfs-unixfs-exporter/test/helpers/collect-leaf-cids.js +++ b/packages/ipfs-unixfs-exporter/test/helpers/collect-leaf-cids.js @@ -1,6 +1,13 @@ 'use strict' +/** + * @param {import('cids')} cid + * @param {import('../../src').IPLDResolver} ipld + */ module.exports = function (cid, ipld) { + /** + * @param {import('cids')} cid + */ async function * traverse (cid) { const node = await ipld.get(cid) @@ -13,7 +20,12 @@ module.exports = function (cid, ipld) { return } - node.Links.forEach(link => traverse(link.Hash)) + node.Links.forEach( + /** + * @param {import('ipld-dag-pb').DAGLink} link + */ + link => traverse(link.Hash) + ) } return traverse(cid) diff --git a/packages/ipfs-unixfs-exporter/test/import-export-dir-sharding.spec.js b/packages/ipfs-unixfs-exporter/test/import-export-dir-sharding.spec.js index bc5af3b9..9b63ca73 100644 --- a/packages/ipfs-unixfs-exporter/test/import-export-dir-sharding.spec.js +++ b/packages/ipfs-unixfs-exporter/test/import-export-dir-sharding.spec.js @@ -5,7 +5,9 @@ const importer = require('ipfs-unixfs-importer') const exporter = require('../src') const { expect } = require('aegir/utils/chai') +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') const all = require('it-all') const last = require('it-last') @@ -14,8 +16,15 @@ const uint8ArrayFromString = require('uint8arrays/from-string') const uint8ArrayToString = require('uint8arrays/to-string') const uint8ArrayConcat = require('uint8arrays/concat') +/** + * @typedef {import('../src').UnixFSEntry} UnixFSEntry + * @typedef {import('../src').UnixFSDirectory} UnixFSDirectory + */ + describe('builder: directory sharding', () => { + /** @type {import('../src').IPLDResolver} */ let ipld + /** @type {import('ipfs-unixfs-importer').BlockAPI} */ let block before(async () => { @@ -39,10 +48,25 @@ describe('builder: directory sharding', () => { expect(nodes[1].path).to.equal('a') const dirNode = await exporter(nodes[1].cid, ipld) + + if (dirNode.type !== 'directory') { + throw new Error('Unexpected type') + } + expect(dirNode.unixfs.type).to.equal('directory') const fileNode = await exporter(nodes[0].cid, ipld) + + if (fileNode.type !== 'file') { + throw new Error('Unexpected type') + } + expect(fileNode.unixfs.type).to.equal('file') + + if (fileNode.type !== 'file') { + throw new Error('Unexpected type') + } + expect(uint8ArrayConcat(await all(fileNode.content()))).to.deep.equal(content) }) @@ -60,6 +84,10 @@ describe('builder: directory sharding', () => { const node = await exporter(nodes[1].cid, ipld) + if (node.type !== 'directory') { + throw new Error('Unexpected type') + } + expect(node.unixfs.type).to.equal('hamt-sharded-directory') }) @@ -75,10 +103,19 @@ describe('builder: directory sharding', () => { const nonShardedHash = nodes[1].cid const dir = await exporter(nonShardedHash, ipld) + + if (dir.type !== 'directory') { + throw new Error('Unexpected type') + } + const files = await all(dir.content()) expect(files.length).to.equal(1) + if (files[0].type !== 'file') { + throw new Error('Unexpected type') + } + const expectedHash = nonShardedHash.toBaseEncodedString() expect(dir.path).to.be.eql(expectedHash) @@ -103,10 +140,19 @@ describe('builder: directory sharding', () => { const shardedHash = nodes[1].cid const dir = await exporter(shardedHash, ipld) + + if (dir.type !== 'directory') { + throw new Error('Unexpected type') + } + const files = await all(dir.content()) expect(files.length).to.equal(1) + if (files[0].type !== 'file') { + throw new Error('Unexpected type') + } + const expectedHash = shardedHash.toBaseEncodedString() expect(dir.path).to.be.eql(expectedHash) @@ -162,7 +208,15 @@ describe('builder: directory sharding', () => { const dir = await exporter(nodes[nodes.length - 1].cid, ipld) + if (dir.type !== 'directory') { + throw new Error('Unexpected type') + } + for await (const entry of dir.content()) { + if (entry.type !== 'file') { + throw new Error('Unexpected type') + } + const content = uint8ArrayConcat(await all(entry.content())) expect(uint8ArrayToString(content)).to.equal(parseInt(entry.name, 10).toString()) } @@ -174,6 +228,7 @@ describe('builder: directory sharding', () => { const maxDirs = 2000 const maxDepth = 3 + /** @type {import('cids')} */ let rootHash before(async () => { @@ -209,6 +264,11 @@ describe('builder: directory sharding', () => { } const node = await last(importer(source, block)) + + if (!node) { + throw new Error('Nothing imported') + } + expect(node.path).to.equal('big') rootHash = node.cid @@ -217,12 +277,15 @@ describe('builder: directory sharding', () => { it('imports a big dir', async () => { const dir = await exporter(rootHash, ipld) + /** + * @param {UnixFSEntry} node + */ const verifyContent = async (node) => { - if (node.unixfs.type === 'file') { + if (node.type === 'file') { const bufs = await all(node.content()) const content = uint8ArrayConcat(bufs) - expect(uint8ArrayToString(content)).to.equal(parseInt(node.name, 10).toString()) - } else { + expect(uint8ArrayToString(content)).to.equal(parseInt(node.name || '', 10).toString()) + } else if (node.type === 'directory') { for await (const entry of node.content()) { await verifyContent(entry) } @@ -233,12 +296,17 @@ describe('builder: directory sharding', () => { }) it('exports a big dir', async () => { + /** + * @param {UnixFSEntry} node + * @param {{ [key: string]: { type: 'file', content: string } | UnixFSDirectory }} entries + */ const collectContent = async (node, entries = {}) => { - if (node.unixfs.type === 'file') { + if (node.type === 'file') { entries[node.path] = { + type: 'file', content: uint8ArrayToString(uint8ArrayConcat(await all(node.content()))) } - } else { + } else if (node.type === 'directory') { entries[node.path] = node for await (const entry of node.content()) { @@ -249,6 +317,9 @@ describe('builder: directory sharding', () => { return entries } + /** + * @param {string} path + */ const eachPath = (path) => { if (!index) { // first dir @@ -257,6 +328,11 @@ describe('builder: directory sharding', () => { } const entry = entries[path] + + if (entry.type === 'file') { + throw new Error('Unexpected type') + } + expect(entry).to.exist() expect(entry.content).to.not.be.a('string') } else { @@ -291,6 +367,10 @@ describe('builder: directory sharding', () => { const node = await exporter(exportHash, ipld) expect(node.path).to.equal(exportHash) + if (node.type !== 'file') { + throw new Error('Unexpected type') + } + const content = uint8ArrayConcat(await all(node.content())) expect(uint8ArrayToString(content)).to.equal('2000') }) diff --git a/packages/ipfs-unixfs-exporter/test/import-export-nested-dir.spec.js b/packages/ipfs-unixfs-exporter/test/import-export-nested-dir.spec.js index 1a5e7831..2f82e226 100644 --- a/packages/ipfs-unixfs-exporter/test/import-export-nested-dir.spec.js +++ b/packages/ipfs-unixfs-exporter/test/import-export-nested-dir.spec.js @@ -2,7 +2,9 @@ 'use strict' const { expect } = require('aegir/utils/chai') +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') const all = require('it-all') const importer = require('ipfs-unixfs-importer') @@ -14,7 +16,9 @@ const uint8ArrayConcat = require('uint8arrays/concat') describe('import and export: directory', () => { const rootHash = 'QmdCrquDwd7RfZ6GCZFEVADwe8uyyw1YmF9mtAB7etDgmK' + /** @type {import('../src').IPLDResolver} */ let ipld + /** @type {import('ipfs-unixfs-importer').BlockAPI} */ let block before(async () => { @@ -90,11 +94,21 @@ describe('import and export: directory', () => { }) }) +/** + * + * @param {import('../src').UnixFSEntry} node + * @param {string} path + * @param {{ path: string, content: string }[]} entries + */ async function recursiveExport (node, path, entries = []) { + if (node.type !== 'directory') { + throw new Error('Can only recursively export directories') + } + for await (const entry of node.content()) { - if (entry.unixfs.type === 'directory') { + if (entry.type === 'directory') { await recursiveExport(entry, `${path}/${entry.name}`, entries) - } else { + } else if (entry.type === 'file') { entries.push({ path: `${path}/${entry.name}`, content: uint8ArrayToString(uint8ArrayConcat(await all(entry.content()))) @@ -105,13 +119,20 @@ async function recursiveExport (node, path, entries = []) { return entries } +/** + * @param {{ path?: string, cid: import('cids') }} node + */ function normalizeNode (node) { return { - path: node.path, + path: node.path || '', multihash: node.cid.toBaseEncodedString() } } +/** + * @param {{ path: string }} a + * @param {{ path: string }} b + */ function byPath (a, b) { if (a.path > b.path) return -1 if (a.path < b.path) return 1 diff --git a/packages/ipfs-unixfs-exporter/test/import-export.spec.js b/packages/ipfs-unixfs-exporter/test/import-export.spec.js index d529b85d..85d8c560 100644 --- a/packages/ipfs-unixfs-exporter/test/import-export.spec.js +++ b/packages/ipfs-unixfs-exporter/test/import-export.spec.js @@ -3,9 +3,13 @@ 'use strict' const { expect } = require('aegir/utils/chai') +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') +// @ts-ignore const loadFixture = require('aegir/fixtures') +// @ts-ignore const isNode = require('detect-node') const bigFile = loadFixture((isNode ? __dirname : 'test') + '/fixtures/1.2MiB.txt') const blockApi = require('./helpers/block') @@ -26,7 +30,9 @@ describe('import and export', function () { const importerOptions = { strategy: strategy } describe('using builder: ' + strategy, () => { + /** @type {import('../src').IPLDResolver} */ let ipld + /** @type {import('ipfs-unixfs-importer').BlockAPI} */ let block before(async () => { @@ -38,11 +44,16 @@ describe('import and export', function () { const path = `${strategy}-big.dat` const values = [{ path: path, content: bigFile }] + // @ts-ignore for await (const file of importer(values, block, importerOptions)) { expect(file.path).to.eql(path) const result = await exporter(file.cid, ipld) + if (result.type !== 'file') { + throw new Error('Unexpected type') + } + expect(result.unixfs.fileSize()).to.eql(bigFile.length) } }) diff --git a/packages/ipfs-unixfs-exporter/test/importer.spec.js b/packages/ipfs-unixfs-exporter/test/importer.spec.js index b67a954b..0368e4b2 100644 --- a/packages/ipfs-unixfs-exporter/test/importer.spec.js +++ b/packages/ipfs-unixfs-exporter/test/importer.spec.js @@ -5,14 +5,20 @@ const importer = require('ipfs-unixfs-importer') const exporter = require('../src') const extend = require('merge-options') const { expect } = require('aegir/utils/chai') -const spy = require('sinon/lib/sinon/spy') +const sinon = require('sinon') +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') const UnixFs = require('ipfs-unixfs') const collectLeafCids = require('./helpers/collect-leaf-cids') +// @ts-ignore const loadFixture = require('aegir/fixtures') +// @ts-ignore const isNode = require('detect-node') +/** @type {Uint8Array} */ const bigFile = loadFixture((isNode ? __dirname : 'test') + '/fixtures/1.2MiB.txt') +/** @type {Uint8Array} */ const smallFile = loadFixture((isNode ? __dirname : 'test') + '/fixtures/200Bytes.txt') const all = require('it-all') const first = require('it-first') @@ -21,7 +27,17 @@ const uint8ArrayConcat = require('uint8arrays/concat') const uint8ArrayFromString = require('uint8arrays/from-string') const uint8ArrayToString = require('uint8arrays/to-string') const last = require('it-last') +const CID = require('cids') +/** + * @typedef {import('../src').IPLDResolver} IPLDResolver + * @typedef {import('ipfs-unixfs-importer').BlockAPI} BlockAPI + * @typedef {import('ipld-dag-pb').DAGNode} DAGNode + */ + +/** + * @param {{ path?: string, cid: CID, unixfs?: UnixFs }[]} files + */ function stringifyMh (files) { return files.map((file) => { return { @@ -31,6 +47,9 @@ function stringifyMh (files) { }) } +/** + * @param {Date} date + */ function dateToTimespec (date) { const ms = date.getTime() const secs = Math.floor(ms / 1000) @@ -179,12 +198,23 @@ const strategyOverrides = { } } +/** + * @param {BlockAPI} block + * @param {IPLDResolver} ipld + * @param {import('ipfs-unixfs-importer').UserImporterOptions} options + * @param {*} expected + */ const checkLeafNodeTypes = async (block, ipld, options, expected) => { const file = await first(importer([{ path: 'foo', content: new Uint8Array(262144 + 5).fill(1) }], block, options)) + if (!file) { + throw new Error('Nothing imported') + } + + /** @type {DAGNode} */ const node = await ipld.get(file.cid) const meta = UnixFs.unmarshal(node.Data) @@ -201,6 +231,12 @@ const checkLeafNodeTypes = async (block, ipld, options, expected) => { }) } +/** + * @param {BlockAPI} block + * @param {IPLDResolver} ipld + * @param {import('ipfs-unixfs-importer').UserImporterOptions} options + * @param {*} expected + */ const checkNodeLinks = async (block, ipld, options, expected) => { for await (const file of importer([{ path: 'foo', @@ -215,6 +251,7 @@ const checkNodeLinks = async (block, ipld, options, expected) => { } strategies.forEach((strategy) => { + // @ts-ignore const baseFiles = strategyBaseFiles[strategy] const defaultResults = extend({}, baseFiles, { 'foo/bar/200Bytes.txt': extend({}, baseFiles['200Bytes.txt'], { @@ -286,10 +323,15 @@ strategies.forEach((strategy) => { cid: 'QmVfHowk2oKuWFyVwSRt8H1dQ3v272jyWSwhfQnTtWNmfw', size: 200 }) + // @ts-ignore }, strategyOverrides[strategy]) const expected = extend({}, defaultResults) + /** + * @param {*} actualFiles + * @param {*} expectedFiles + */ const expectFiles = (actualFiles, expectedFiles) => { expect(actualFiles.length).to.equal(expectedFiles.length) @@ -313,9 +355,13 @@ strategies.forEach((strategy) => { describe('importer: ' + strategy, function () { this.timeout(30 * 1000) + /** @type {IPLDResolver} */ let ipld + /** @type {BlockAPI} */ let block + /** @type {import('ipfs-unixfs-importer').UserImporterOptions} */ const options = { + // @ts-ignore strategy: strategy } @@ -332,6 +378,7 @@ strategies.forEach((strategy) => { it('fails on bad content', async () => { try { + // @ts-expect-error bad content await all(importer([{ path: '200Bytes.txt', content: 7 @@ -344,6 +391,7 @@ strategies.forEach((strategy) => { it('fails on an iterator that yields bad content', async () => { try { + // @ts-expect-error bad content await all(importer([{ path: '200Bytes.txt', content: { @@ -359,7 +407,7 @@ strategies.forEach((strategy) => { }) it('doesn\'t yield anything on empty source', async () => { - const files = await all(importer([], ipld, options)) + const files = await all(importer([], block, options)) expect(files).to.be.empty() }) @@ -396,9 +444,12 @@ strategies.forEach((strategy) => { }], block, options)) const file = await exporter(res[0].cid, ipld) - const fileContent = await first(file.content()) - expect(uint8ArrayToString(fileContent)).to.equal(content) + if (file.type !== 'file') { + throw new Error('Unexpected type') + } + + expect(uint8ArrayToString(uint8ArrayConcat(await all(file.content())))).to.equal(content) }) it('small file with an escaped slash in the title', async () => { @@ -437,7 +488,7 @@ strategies.forEach((strategy) => { it('small file as array (smaller than a chunk)', async () => { const files = await all(importer([{ path: '200Bytes.txt', - content: Array.from(smallFile) + content: Uint8Array.from(smallFile) }], block, options)) expectFiles(files, [ @@ -606,7 +657,14 @@ strategies.forEach((strategy) => { result.forEach(eachFile) + /** + * @param {{ path?: string, cid: string, unixfs?: UnixFs }} file + */ function eachFile (file) { + if (!file.unixfs) { + throw new Error('file was not UnixFS') + } + if (file.path === 'pam/pum/200Bytes.txt') { expect(file.cid).to.equal(expected['200Bytes.txt'].cid) expect(file.unixfs.fileSize()).to.equal(expected['200Bytes.txt'].size) @@ -652,7 +710,7 @@ strategies.forEach((strategy) => { const path = '1.2MiB.txt' const options = { - progress: spy(), + progress: sinon.spy(), maxChunkSize } @@ -666,6 +724,10 @@ strategies.forEach((strategy) => { }) it('will import files with CID version 1', async () => { + /** + * @param {string} path + * @param {number} size + */ const createInputFile = (path, size) => { const name = String(Math.random() + Date.now()) path = path[path.length - 1] === '/' ? path : path + '/' @@ -676,36 +738,45 @@ strategies.forEach((strategy) => { } const inputFiles = [ - createInputFile('/foo', 10), - createInputFile('/foo', 60), - createInputFile('/foo/bar', 78), - createInputFile('/foo/baz', 200), + createInputFile('foo', 10), + createInputFile('foo', 60), + createInputFile('foo/bar', 78), + createInputFile('foo/baz', 200), // Bigger than maxChunkSize - createInputFile('/foo', 262144 + 45), - createInputFile('/foo/bar', 262144 + 134), - createInputFile('/foo/bar', 262144 + 79), - createInputFile('/foo/bar', 262144 + 876), - createInputFile('/foo/bar', 262144 + 21) + createInputFile('foo', 262144 + 45), + createInputFile('foo/bar', 262144 + 134), + createInputFile('foo/bar', 262144 + 79), + createInputFile('foo/bar', 262144 + 876), + createInputFile('foo/bar', 262144 + 21) ] + /** @type {import('ipfs-unixfs-importer').UserImporterOptions} */ const options = { cidVersion: 1, // Ensures we use DirSharded for the data below shardSplitThreshold: 3 } - // Pass a copy of inputFiles, since the importer mutates them - const files = await all(importer(inputFiles.map(f => Object.assign({}, f)), block, options)) + const files = await all(importer(inputFiles, block, options)) const file = files[0] expect(file).to.exist() - for (let i = 0; i < file.length; i++) { + for (let i = 0; i < files.length; i++) { const file = files[i] + if (file.unixfs?.isDirectory()) { + // ignore directories + continue + } + const cid = file.cid.toV1() const inputFile = inputFiles.find(f => f.path === file.path) + if (!inputFile) { + throw new Error('Could not find input file with path ' + file.path) + } + // Just check the intermediate directory can be retrieved if (!inputFile) { await ipld.get(cid) @@ -713,13 +784,12 @@ strategies.forEach((strategy) => { // Check the imported content is correct const node = await exporter(cid, ipld) - const chunks = [] - for await (const chunk of node.content()) { - chunks.push(chunk) + if (node.type !== 'file') { + throw new Error('Unexpected type') } - expect(uint8ArrayConcat(chunks)).to.deep.equal(inputFile.content) + expect(uint8ArrayConcat(await all(node.content()))).to.deep.equal(inputFile.content) } }) @@ -759,8 +829,8 @@ strategies.forEach((strategy) => { content: bigFile }], block, options)) { for await (const { cid } of collectLeafCids(file.cid, ipld)) { - expect(cid.codec).to.be('raw') - expect(cid.version).to.be(1) + expect(cid).to.have.property('codec', 'raw') + expect(cid).to.have.property('version', 1) } } }) @@ -780,7 +850,7 @@ strategies.forEach((strategy) => { }], block, options)) { const node = await exporter(file.cid, ipld) - expect(node).to.have.nested.deep.property('unixfs.mtime', dateToTimespec(now)) + expect(node).to.have.deep.nested.property('unixfs.mtime', dateToTimespec(now)) } }) @@ -795,7 +865,7 @@ strategies.forEach((strategy) => { }], block)) const node = await exporter(entries[0].cid, ipld) - expect(node).to.have.nested.deep.property('unixfs.mtime', dateToTimespec(now)) + expect(node).to.have.deep.nested.property('unixfs.mtime', dateToTimespec(now)) }) it('supports passing metadata for wrapping directories', async () => { @@ -814,13 +884,13 @@ strategies.forEach((strategy) => { }], block)) const nodes = await all(exporter.recursive(entries[entries.length - 1].cid, ipld)) - const node = nodes.filter(node => node.unixfs.type === 'directory').pop() + const node = nodes.filter(node => node.type === 'directory').pop() if (!node) { expect.fail('no directory found') } - expect(node).to.have.nested.deep.property('unixfs.mtime', dateToTimespec(now)) + expect(node).to.have.deep.nested.property('unixfs.mtime', dateToTimespec(now)) expect(node).to.have.nested.property('unixfs.mode', perms) }) @@ -840,13 +910,13 @@ strategies.forEach((strategy) => { }], block)) const nodes = await all(exporter.recursive(entries[entries.length - 1].cid, ipld)) - const node = nodes.filter(node => node.unixfs.type === 'directory').pop() + const node = nodes.filter(node => node.type === 'directory').pop() if (!node) { expect.fail('no directory found') } - expect(node).to.have.nested.deep.property('unixfs.mtime', dateToTimespec(now)) + expect(node).to.have.deep.nested.property('unixfs.mtime', dateToTimespec(now)) expect(node).to.have.nested.property('unixfs.mode', perms) }) @@ -871,13 +941,13 @@ strategies.forEach((strategy) => { }], block)) const nodes = await all(exporter.recursive(entries[entries.length - 1].cid, ipld)) - const node = nodes.filter(node => node.unixfs.type === 'directory' && node.name === 'bar').pop() + const node = nodes.filter(node => node.type === 'directory' && node.name === 'bar').pop() if (!node) { expect.fail('no directory found') } - expect(node).to.have.nested.deep.property('unixfs.mtime', dateToTimespec(now)) + expect(node).to.have.deep.nested.property('unixfs.mtime', dateToTimespec(now)) expect(node).to.have.nested.property('unixfs.mode', perms) }) @@ -902,13 +972,13 @@ strategies.forEach((strategy) => { })) const nodes = await all(exporter.recursive(entries[entries.length - 1].cid, ipld)) - const node = nodes.filter(node => node.unixfs.type === 'hamt-sharded-directory').pop() + const node = nodes.filter(node => node.type === 'directory' && node.unixfs.type === 'hamt-sharded-directory').pop() if (!node) { expect.fail('no hamt-sharded-directory found') } - expect(node).to.have.nested.deep.property('unixfs.mtime', dateToTimespec(now)) + expect(node).to.have.deep.nested.property('unixfs.mtime', dateToTimespec(now)) }) it('supports passing mode', async () => { @@ -1006,9 +1076,21 @@ strategies.forEach((strategy) => { }) describe('configuration', () => { + /** @type {IPLDResolver} */ + let ipld + /** @type {BlockAPI} */ + let block + + before(async () => { + ipld = await inMemory(IPLD) + block = blockApi(ipld) + }) + it('alllows configuring with custom dag and tree builder', async () => { let builtTree = false - const block = 'block' + const cid = new CID('QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn') + const unixfs = new UnixFs({ type: 'directory' }) + const entries = await all(importer([{ path: 'path', content: 'content' @@ -1016,9 +1098,10 @@ describe('configuration', () => { dagBuilder: async function * (source, block, opts) { // eslint-disable-line require-await yield function () { return Promise.resolve({ - cid: 'cid', + cid, path: 'path', - unixfs: 'unixfs' + unixfs, + size: 0 }) } }, @@ -1029,9 +1112,9 @@ describe('configuration', () => { })) expect(entries).to.have.lengthOf(1) - expect(entries).to.have.nested.property('[0].cid', 'cid') + expect(entries).to.have.deep.nested.property('[0].cid', cid) expect(entries).to.have.nested.property('[0].path', 'path') - expect(entries).to.have.nested.property('[0].unixfs', 'unixfs') + expect(entries).to.have.deep.nested.property('[0].unixfs', unixfs) expect(builtTree).to.be.true() }) @@ -1039,16 +1122,20 @@ describe('configuration', () => { it('allows configuring with custom chunker', async () => { let validated = false let chunked = false - const block = { - put: () => {} - } const entries = await all(importer([{ path: 'path', content: uint8ArrayFromString('content') }], block, { chunkValidator: async function * (source, opts) { // eslint-disable-line require-await validated = true - yield * source + + for await (const str of source) { + if (typeof str === 'string') { + yield uint8ArrayFromString(str) + } else { + yield Uint8Array.from(str) + } + } }, chunker: async function * (source, opts) { // eslint-disable-line require-await chunked = true @@ -1065,24 +1152,34 @@ describe('configuration', () => { }) it('imports the same data with different CID versions and gets the same multihash', async () => { - const ipld = await inMemory(IPLD) - const block = blockApi(ipld) const buf = uint8ArrayFromString('content') - const { cid: cidV0 } = await last(importer([{ + const result = await last(importer([{ content: buf }], block, { cidVersion: 0, rawLeaves: false })) - const { cid: cidV1 } = await last(importer([{ + if (!result) { + throw new Error('Nothing imported') + } + + const { cid: cidV0 } = result + + const result2 = await last(importer([{ content: buf }], block, { cidVersion: 1, rawLeaves: false })) + if (!result2) { + throw new Error('Nothing imported') + } + + const { cid: cidV1 } = result2 + expect(cidV0.multihash).to.deep.equal(cidV1.multihash) }) }) diff --git a/packages/ipfs-unixfs-exporter/tsconfig.json b/packages/ipfs-unixfs-exporter/tsconfig.json new file mode 100644 index 00000000..c5c7aae8 --- /dev/null +++ b/packages/ipfs-unixfs-exporter/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ], + "exclude": [ + "dist", + "node_modules" + ], + "references": [ + { + "path": "../ipfs-unixfs" + } + ] +} diff --git a/packages/ipfs-unixfs-importer/README.md b/packages/ipfs-unixfs-importer/README.md index 3ec407e0..076d15de 100644 --- a/packages/ipfs-unixfs-importer/README.md +++ b/packages/ipfs-unixfs-importer/README.md @@ -152,9 +152,9 @@ Several aspects of the importer are overridable by specifying functions as part - It should yield `Buffer` objects constructed from the `source` or throw an `Error` - `chunker` (function): Optional function that supports the signature `async function * (source, options)` where `source` is an async generator and `options` is an options object - It should yield `Buffer` objects. -- `bufferImporter` (function): Optional function that supports the signature `async function * (entry, source, ipld, options)` +- `bufferImporter` (function): Optional function that supports the signature `async function * (entry, ipld, options)` - This function should read `Buffer`s from `source` and persist them using `ipld.put` or similar - - `entry` is the `{ path, content }` entry, `source` is an async generator that yields Buffers + - `entry` is the `{ path, content }` entry, where `entry.content` is an async generator that yields Buffers - It should yield functions that return a Promise that resolves to an object with the properties `{ cid, unixfs, size }` where `cid` is a [CID], `unixfs` is a [UnixFS] entry and `size` is a `Number` that represents the serialized size of the [IPLD] node that holds the buffer data. - Values will be pulled from this generator in parallel - the amount of parallelisation is controlled by the `blockWriteConcurrency` option (default: 10) - `dagBuilder` (function): Optional function that supports the signature `async function * (source, ipld, options)` diff --git a/packages/ipfs-unixfs-importer/package.json b/packages/ipfs-unixfs-importer/package.json index 9af60b44..d9cd0553 100644 --- a/packages/ipfs-unixfs-importer/package.json +++ b/packages/ipfs-unixfs-importer/package.json @@ -8,15 +8,12 @@ "fs": false }, "scripts": { + "prepare": "aegir build --no-bundle", "test": "aegir test", - "test:node": "aegir test -t node", - "test:browser": "aegir test -t browser", - "test:webworker": "aegir test -t webworker", - "build": "aegir build", "clean": "rm -rf ./dist", "lint": "aegir lint", - "coverage": "nyc -s npm run test:node && nyc report --reporter=html", - "depcheck": "aegir dep-check" + "coverage": "nyc -s npm run test -t node && nyc report --reporter=html", + "depcheck": "aegir dep-check -i @types/mocha -i nyc" }, "repository": { "type": "git", @@ -35,25 +32,21 @@ }, "homepage": "https://github.com/ipfs/js-ipfs-unixfs#readme", "devDependencies": { - "aegir": "^29.2.2", - "cids": "^1.0.0", - "detect-node": "^2.0.4", - "ipfs-unixfs-exporter": "^3.0.7", + "@types/mocha": "^8.2.0", + "aegir": "^30.3.0", "ipld": "^0.28.0", "ipld-in-memory": "^7.0.0", - "it-buffer-stream": "^1.0.2", - "it-last": "^1.0.1", + "it-buffer-stream": "^2.0.0", "multicodec": "^2.0.0", - "nyc": "^15.0.0", - "sinon": "^9.0.1" + "nyc": "^15.0.0" }, "dependencies": { "bl": "^4.0.0", - "err-code": "^2.0.0", - "hamt-sharding": "^1.0.0", + "cids": "^1.1.5", + "err-code": "^3.0.0", + "hamt-sharding": "^2.0.0", "ipfs-unixfs": "^2.0.4", - "ipfs-utils": "^5.0.0", - "ipld-dag-pb": "^0.20.0", + "ipld-dag-pb": "^0.21.0", "it-all": "^1.0.1", "it-batch": "^1.0.3", "it-first": "^1.0.1", @@ -61,6 +54,14 @@ "merge-options": "^3.0.3", "multihashing-async": "^2.0.0", "rabin-wasm": "^0.1.1", - "uint8arrays": "^1.1.0" + "uint8arrays": "^2.0.5" + }, + "types": "dist/src/index.d.ts", + "files": [ + "src", + "dist" + ], + "eslintConfig": { + "extends": "ipfs" } } diff --git a/packages/ipfs-unixfs-importer/src/chunker/fixed-size.js b/packages/ipfs-unixfs-importer/src/chunker/fixed-size.js index 6cef6606..ecbb360a 100644 --- a/packages/ipfs-unixfs-importer/src/chunker/fixed-size.js +++ b/packages/ipfs-unixfs-importer/src/chunker/fixed-size.js @@ -1,7 +1,11 @@ 'use strict' +// @ts-ignore const BufferList = require('bl/BufferList') +/** + * @type {import('./').Chunker} + */ module.exports = async function * fixedSizeChunker (source, options) { let bl = new BufferList() let currentLength = 0 diff --git a/packages/ipfs-unixfs-importer/src/chunker/index.js b/packages/ipfs-unixfs-importer/src/chunker/index.js index ec2c494b..fb371fb9 100644 --- a/packages/ipfs-unixfs-importer/src/chunker/index.js +++ b/packages/ipfs-unixfs-importer/src/chunker/index.js @@ -2,11 +2,25 @@ const errCode = require('err-code') +/** + * @typedef {import('../').ImporterOptions} ImporterOptions + * @typedef {(source: AsyncIterable, options: ImporterOptions) => AsyncIterable} Chunker + */ + +/** + * @type {{ [key: string]: Chunker }} + */ const chunkers = { fixed: require('../chunker/fixed-size'), rabin: require('../chunker/rabin') } +/** + * + * @param {import('../').ChunkerType} type + * @param {AsyncIterable} source + * @param {import('../').ImporterOptions} options + */ module.exports = (type, source, options) => { const chunker = chunkers[type] diff --git a/packages/ipfs-unixfs-importer/src/chunker/rabin.js b/packages/ipfs-unixfs-importer/src/chunker/rabin.js index 6f1a0775..7e9f6475 100644 --- a/packages/ipfs-unixfs-importer/src/chunker/rabin.js +++ b/packages/ipfs-unixfs-importer/src/chunker/rabin.js @@ -1,12 +1,24 @@ 'use strict' +// @ts-ignore const BufferList = require('bl/BufferList') +// @ts-ignore const { create } = require('rabin-wasm') const errcode = require('err-code') -module.exports = async function * rabinChunker (source, options) { - const rabin = jsRabin() +/** + * @typedef {object} RabinOptions + * @property {number} min + * @property {number} max + * @property {number} bits + * @property {number} window + * @property {number} polynomial + */ +/** + * @type {import('./').Chunker} + */ +module.exports = async function * rabinChunker (source, options) { let min, max, avg if (options.minChunkSize && options.maxChunkSize && options.avgChunkSize) { @@ -47,27 +59,29 @@ module.exports = async function * rabinChunker (source, options) { } } -const jsRabin = () => { - return async function * (source, options) { - const r = await create(options.bits, options.min, options.max, options.window) - const buffers = new BufferList() +/** + * @param {AsyncIterable} source + * @param {RabinOptions} options + */ +async function * rabin (source, options) { + const r = await create(options.bits, options.min, options.max, options.window) + const buffers = new BufferList() - for await (const chunk of source) { - buffers.append(chunk) + for await (const chunk of source) { + buffers.append(chunk) - const sizes = r.fingerprint(chunk) + const sizes = r.fingerprint(chunk) - for (let i = 0; i < sizes.length; i++) { - var size = sizes[i] - var buf = buffers.slice(0, size) - buffers.consume(size) + for (let i = 0; i < sizes.length; i++) { + const size = sizes[i] + const buf = buffers.slice(0, size) + buffers.consume(size) - yield buf - } + yield buf } + } - if (buffers.length) { - yield buffers.slice(0) - } + if (buffers.length) { + yield buffers.slice(0) } } diff --git a/packages/ipfs-unixfs-importer/src/dag-builder/dir.js b/packages/ipfs-unixfs-importer/src/dag-builder/dir.js index c3c0908a..9541698e 100644 --- a/packages/ipfs-unixfs-importer/src/dag-builder/dir.js +++ b/packages/ipfs-unixfs-importer/src/dag-builder/dir.js @@ -6,6 +6,13 @@ const { DAGNode } = require('ipld-dag-pb') +/** + * @typedef {import('../').Directory} Directory + */ + +/** + * @type {import('./').UnixFSV1DagBuilder} + */ const dirBuilder = async (item, block, options) => { const unixfs = new UnixFS({ type: 'directory', diff --git a/packages/ipfs-unixfs-importer/src/dag-builder/file/balanced.js b/packages/ipfs-unixfs-importer/src/dag-builder/file/balanced.js index 732f7f76..31f65446 100644 --- a/packages/ipfs-unixfs-importer/src/dag-builder/file/balanced.js +++ b/packages/ipfs-unixfs-importer/src/dag-builder/file/balanced.js @@ -2,10 +2,25 @@ const batch = require('it-batch') +/** + * @typedef {import('cids')} CID + * @typedef {import('../..').ImporterOptions} ImporterOptions + * @typedef {import('../..').ImportResult} ImportResult + */ + +/** + * @type {import('.').DAGBuilder} + */ async function * balanced (source, reduce, options) { yield await reduceToParents(source, reduce, options) } +/** + * @param {AsyncIterable | ImportResult[]} source + * @param {import('.').Reducer} reduce + * @param {ImporterOptions} options + * @returns {Promise} + */ async function reduceToParents (source, reduce, options) { const roots = [] diff --git a/packages/ipfs-unixfs-importer/src/dag-builder/file/buffer-importer.js b/packages/ipfs-unixfs-importer/src/dag-builder/file/buffer-importer.js index c627a805..e01df504 100644 --- a/packages/ipfs-unixfs-importer/src/dag-builder/file/buffer-importer.js +++ b/packages/ipfs-unixfs-importer/src/dag-builder/file/buffer-importer.js @@ -6,8 +6,19 @@ const { DAGNode } = require('ipld-dag-pb') -async function * bufferImporter (file, source, block, options) { - for await (let buffer of source) { +/** + * @typedef {import('../../').BlockAPI} BlockAPI + * @typedef {import('../../').ImporterOptions} ImporterOptions + * @typedef {import('../../').File} File + * @typedef {import('../../').PartialImportResult} PartialImportResult + * @typedef {(file: File, block: BlockAPI, options: ImporterOptions) => AsyncIterable<() => Promise>} BufferImporter + */ + +/** + * @type {BufferImporter} + */ +async function * bufferImporter (file, block, options) { + for await (let buffer of file.content) { yield async () => { options.progress(buffer.length, file.path) let unixfs diff --git a/packages/ipfs-unixfs-importer/src/dag-builder/file/flat.js b/packages/ipfs-unixfs-importer/src/dag-builder/file/flat.js index 1ac77ef6..3b3cedda 100644 --- a/packages/ipfs-unixfs-importer/src/dag-builder/file/flat.js +++ b/packages/ipfs-unixfs-importer/src/dag-builder/file/flat.js @@ -2,6 +2,9 @@ const all = require('it-all') +/** + * @type {import('./').DAGBuilder} + */ module.exports = async function * (source, reduce) { yield await reduce(await all(source)) } diff --git a/packages/ipfs-unixfs-importer/src/dag-builder/file/index.js b/packages/ipfs-unixfs-importer/src/dag-builder/file/index.js index 19c2efee..c4ce9892 100644 --- a/packages/ipfs-unixfs-importer/src/dag-builder/file/index.js +++ b/packages/ipfs-unixfs-importer/src/dag-builder/file/index.js @@ -11,13 +11,32 @@ const all = require('it-all') const parallelBatch = require('it-parallel-batch') const mh = require('multihashing-async').multihash +/** + * @typedef {import('cids')} CID + * @typedef {import('../../').File} File + * @typedef {import('../../').BlockAPI} BlockAPI + * @typedef {import('../../').ImporterOptions} ImporterOptions + * @typedef {import('../../').PartialImportResult} PartialImportResult + * + * @typedef {(leaves: PartialImportResult[]) => Promise} Reducer + * @typedef {(source: AsyncIterable, reducer: Reducer, options: ImporterOptions) => AsyncIterable} DAGBuilder + */ + +/** + * @type {{ [key: string]: DAGBuilder}} + */ const dagBuilders = { flat: require('./flat'), balanced: require('./balanced'), trickle: require('./trickle') } -async function * buildFileBatch (file, source, block, options) { +/** + * @param {File} file + * @param {BlockAPI} block + * @param {ImporterOptions} options + */ +async function * buildFileBatch (file, block, options) { let count = -1 let previous let bufferImporter @@ -28,13 +47,13 @@ async function * buildFileBatch (file, source, block, options) { bufferImporter = require('./buffer-importer') } - for await (const entry of parallelBatch(bufferImporter(file, source, block, options), options.blockWriteConcurrency)) { + for await (const entry of parallelBatch(bufferImporter(file, block, options), options.blockWriteConcurrency)) { count++ if (count === 0) { previous = entry continue - } else if (count === 1) { + } else if (count === 1 && previous) { yield previous previous = null } @@ -48,8 +67,16 @@ async function * buildFileBatch (file, source, block, options) { } } +/** + * @param {File} file + * @param {BlockAPI} block + * @param {ImporterOptions} options + */ const reduce = (file, block, options) => { - return async function (leaves) { + /** + * @type {Reducer} + */ + async function reducer (leaves) { if (leaves.length === 1 && leaves[0].single && options.reduceSingleLeafToSelf) { const leaf = leaves[0] @@ -98,29 +125,29 @@ const reduce = (file, block, options) => { return true } - if (!leaf.unixfs.data && leaf.unixfs.fileSize()) { + if (leaf.unixfs && !leaf.unixfs.data && leaf.unixfs.fileSize()) { return true } - return Boolean(leaf.unixfs.data.length) + return Boolean(leaf.unixfs && leaf.unixfs.data && leaf.unixfs.data.length) }) .map((leaf) => { if (leaf.cid.codec === 'raw') { // node is a leaf buffer f.addBlockSize(leaf.size) - return new DAGLink(leaf.name, leaf.size, leaf.cid) + return new DAGLink('', leaf.size, leaf.cid) } - if (!leaf.unixfs.data) { + if (!leaf.unixfs || !leaf.unixfs.data) { // node is an intermediate node - f.addBlockSize(leaf.unixfs.fileSize()) + f.addBlockSize((leaf.unixfs && leaf.unixfs.fileSize()) || 0) } else { // node is a unixfs 'file' leaf node f.addBlockSize(leaf.unixfs.data.length) } - return new DAGLink(leaf.name, leaf.size, leaf.cid) + return new DAGLink('', leaf.size, leaf.cid) }) const node = new DAGNode(f.marshal(), links) @@ -134,16 +161,21 @@ const reduce = (file, block, options) => { size: buffer.length + node.Links.reduce((acc, curr) => acc + curr.Tsize, 0) } } + + return reducer } -const fileBuilder = async (file, source, block, options) => { +/** + * @type {import('../').UnixFSV1DagBuilder} + */ +const fileBuilder = async (file, block, options) => { const dagBuilder = dagBuilders[options.strategy] if (!dagBuilder) { throw errCode(new Error(`Unknown importer build strategy name: ${options.strategy}`), 'ERR_BAD_STRATEGY') } - const roots = await all(dagBuilder(buildFileBatch(file, source, block, options), reduce(file, block, options), options)) + const roots = await all(dagBuilder(buildFileBatch(file, block, options), reduce(file, block, options), options)) if (roots.length > 1) { throw errCode(new Error('expected a maximum of 1 roots and got ' + roots.length), 'ETOOMANYROOTS') diff --git a/packages/ipfs-unixfs-importer/src/dag-builder/file/trickle.js b/packages/ipfs-unixfs-importer/src/dag-builder/file/trickle.js index 5149ff0b..787537a1 100644 --- a/packages/ipfs-unixfs-importer/src/dag-builder/file/trickle.js +++ b/packages/ipfs-unixfs-importer/src/dag-builder/file/trickle.js @@ -2,15 +2,34 @@ const batch = require('it-batch') +/** + * @typedef {import('cids')} CID + * @typedef {import('../..').ImporterOptions} ImporterOptions + * @typedef {import('../..').PartialImportResult} PartialImportResult + * @typedef {import('.').Reducer} Reducer + * @typedef {import('ipfs-unixfs')} UnixFS + */ + +/** + * @type {import('./').DAGBuilder} + */ module.exports = function * trickleReduceToRoot (source, reduce, options) { yield trickleStream(source, reduce, options) } +/** + * @param {AsyncIterable | Iterable} source + * @param {Reducer} reduce + * @param {ImporterOptions} options + * @returns {Promise} + */ async function trickleStream (source, reduce, options) { - let root + const root = new Root(options.layerRepeat) let iteration = 0 let maxDepth = 1 - let subTree = root = new Root(options.layerRepeat) + + /** @type {SubTree} */ + let subTree = root for await (const layer of batch(source, options.maxChildrenPerNode)) { if (subTree.isFull()) { @@ -37,13 +56,32 @@ async function trickleStream (source, reduce, options) { return root.reduce(reduce) } +/** + * @typedef {object} TrickleDagNode + * @property {PartialImportResult[]} children + * @property {number} depth + * @property {number} maxDepth + * @property {number} maxChildren + * @property {PartialImportResult[]} [data] + * @property {TrickleDagNode} [parent] + * @property {CID} [cid] + * @property {number} [size] + * @property {UnixFS} [unixfs] + */ + class SubTree { - constructor (maxDepth, layerRepeat, iteration) { + /** + * @param {number} maxDepth + * @param {number} layerRepeat + * @param {number} [iteration=0] + */ + constructor (maxDepth, layerRepeat, iteration = 0) { this.maxDepth = maxDepth this.layerRepeat = layerRepeat this.currentDepth = 1 this.iteration = iteration + /** @type {TrickleDagNode} */ this.root = this.node = this.parent = { children: [], depth: this.currentDepth, @@ -76,6 +114,9 @@ class SubTree { return true } + /** + * @param {TrickleDagNode} parent + */ _addNextNodeToParent (parent) { this.parent = parent @@ -88,34 +129,55 @@ class SubTree { maxChildren: Math.floor(parent.children.length / this.layerRepeat) * this.layerRepeat } + // @ts-ignore parent.children.push(nextNode) this.currentDepth = nextNode.depth this.node = nextNode } + /** + * + * @param {PartialImportResult[]} layer + */ append (layer) { this.node.data = layer } + /** + * @param {Reducer} reduce + */ reduce (reduce) { return this._reduce(this.root, reduce) } + /** + * @param {TrickleDagNode} node + * @param {Reducer} reduce + * @returns {Promise} + */ async _reduce (node, reduce) { + /** @type {PartialImportResult[]} */ let children = [] if (node.children.length) { children = await Promise.all( node.children + // @ts-ignore .filter(child => child.data) + // @ts-ignore .map(child => this._reduce(child, reduce)) ) } - return reduce(node.data.concat(children)) + return reduce((node.data || []).concat(children)) } + /** + * @param {TrickleDagNode} node + * @param {number} depth + * @returns {TrickleDagNode | undefined} + */ _findParent (node, depth) { const parent = node.parent @@ -133,6 +195,9 @@ class SubTree { } class Root extends SubTree { + /** + * @param {number} layerRepeat + */ constructor (layerRepeat) { super(0, layerRepeat) @@ -140,11 +205,17 @@ class Root extends SubTree { this.currentDepth = 1 } + /** + * @param {PartialImportResult} child + */ addChild (child) { this.root.children.push(child) } + /** + * @param {Reducer} reduce + */ reduce (reduce) { - return reduce(this.root.data.concat(this.root.children)) + return reduce((this.root.data || []).concat(this.root.children)) } } diff --git a/packages/ipfs-unixfs-importer/src/dag-builder/index.js b/packages/ipfs-unixfs-importer/src/dag-builder/index.js index dc591c46..abb4361d 100644 --- a/packages/ipfs-unixfs-importer/src/dag-builder/index.js +++ b/packages/ipfs-unixfs-importer/src/dag-builder/index.js @@ -2,7 +2,48 @@ const dirBuilder = require('./dir') const fileBuilder = require('./file') +const errCode = require('err-code') +/** + * @typedef {import('../').BlockAPI} BlockAPI + * @typedef {import('../').ImporterOptions} ImporterOptions + * @typedef {import('../').ImportResult} ImportResult + * @typedef {import('../').PartialImportResult} PartialImportResult + * @typedef {import('../').ImportCandidate} ImportCandidate + * @typedef {import('../').File} File + * @typedef {import('../').Directory} Directory + */ + +/** + * @template T + * @typedef {(item: T, block: BlockAPI, options: ImporterOptions) => Promise} UnixFSV1DagBuilder + */ + +/** + * @typedef {(source: AsyncIterable | Iterable, block: BlockAPI, options: ImporterOptions) => AsyncIterable<() => Promise>} DAGBuilder + */ + +/** + * @param {any} item + * @returns {item is ArrayLike} + */ +function isArrayLike (item) { + return ( + Array.isArray(item) || + (Boolean(item) && + typeof item === 'object' && + typeof (item.length) === 'number' && + (item.length === 0 || + (item.length > 0 && + (item.length - 1) in item) + ) + ) + ) +} + +/** + * @type {DAGBuilder} + */ async function * dagBuilder (source, block, options) { for await (const entry of source) { if (entry.path) { @@ -17,17 +58,24 @@ async function * dagBuilder (source, block, options) { } if (entry.content) { - let source = entry.content - - // wrap in iterator if it is array-like or not an iterator - if ((!source[Symbol.asyncIterator] && !source[Symbol.iterator]) || source.length !== undefined) { - source = { - [Symbol.iterator]: function * () { - yield entry.content - } + const source = entry.content + + /** @type {AsyncIterable>} */ + const content = (async function * () { + // wrap in iterator if it is a, string, Uint8Array or array-like + if (typeof source === 'string' || isArrayLike(source)) { + yield source + // @ts-ignore + } else if (source[Symbol.asyncIterator] || source[Symbol.iterator]) { + yield * source + } else { + throw errCode(new Error('Content was invalid'), 'ERR_INVALID_CONTENT') } - } + }()) + /** + * @type {import('../chunker').Chunker} + */ let chunker if (typeof options.chunker === 'function') { @@ -38,6 +86,9 @@ async function * dagBuilder (source, block, options) { chunker = require('../chunker/fixed-size') } + /** + * @type {import('./validate-chunks').ChunkValidator} + */ let chunkValidator if (typeof options.chunkValidator === 'function') { @@ -46,11 +97,26 @@ async function * dagBuilder (source, block, options) { chunkValidator = require('./validate-chunks') } - // item is a file - yield () => fileBuilder(entry, chunker(chunkValidator(source, options), options), block, options) + /** @type {File} */ + const file = { + path: entry.path, + mtime: entry.mtime, + mode: entry.mode, + content: chunker(chunkValidator(content, options), options) + } + + yield () => fileBuilder(file, block, options) + } else if (entry.path) { + /** @type {Directory} */ + const dir = { + path: entry.path, + mtime: entry.mtime, + mode: entry.mode + } + + yield () => dirBuilder(dir, block, options) } else { - // item is a directory - yield () => dirBuilder(entry, block, options) + throw new Error('Import candidate must have content or path or both') } } } diff --git a/packages/ipfs-unixfs-importer/src/dag-builder/validate-chunks.js b/packages/ipfs-unixfs-importer/src/dag-builder/validate-chunks.js index 2fe95ddc..cfd1f46f 100644 --- a/packages/ipfs-unixfs-importer/src/dag-builder/validate-chunks.js +++ b/packages/ipfs-unixfs-importer/src/dag-builder/validate-chunks.js @@ -3,7 +3,14 @@ const errCode = require('err-code') const uint8ArrayFromString = require('uint8arrays/from-string') -// make sure the content only emits buffer-a-likes +/** + * @typedef {import('../').ImporterOptions} ImporterOptions + * @typedef {(source: AsyncIterable>, options: ImporterOptions) => AsyncIterable} ChunkValidator + */ + +/** + * @type {ChunkValidator} + */ async function * validateChunks (source) { for await (const content of source) { if (content.length === undefined) { @@ -11,11 +18,13 @@ async function * validateChunks (source) { } if (typeof content === 'string' || content instanceof String) { - yield uint8ArrayFromString(content) + yield uint8ArrayFromString(content.toString()) } else if (Array.isArray(content)) { yield Uint8Array.from(content) - } else { + } else if (content instanceof Uint8Array) { yield content + } else { + throw errCode(new Error('Content was invalid'), 'ERR_INVALID_CONTENT') } } } diff --git a/packages/ipfs-unixfs-importer/src/dir-flat.js b/packages/ipfs-unixfs-importer/src/dir-flat.js index d5ac982f..e292f8e8 100644 --- a/packages/ipfs-unixfs-importer/src/dir-flat.js +++ b/packages/ipfs-unixfs-importer/src/dir-flat.js @@ -8,21 +8,43 @@ const UnixFS = require('ipfs-unixfs') const Dir = require('./dir') const persist = require('./utils/persist') +/** + * @typedef {import('./').ImporterOptions} ImporterOptions + * @typedef {import('./').ImportResult} ImportResult + * @typedef {import('./').PartialImportResult} PartialImportResult + * @typedef {import('./').BlockAPI} BlockAPI + * @typedef {import('./dir').DirProps} DirProps + * @typedef {import('cids')} CID + */ + class DirFlat extends Dir { + /** + * @param {DirProps} props + * @param {ImporterOptions} options + */ constructor (props, options) { super(props, options) + + /** @type {{ [key: string]: PartialImportResult | Dir }} */ this._children = {} } - put (name, value) { + /** + * @param {string} name + * @param {PartialImportResult | Dir} value + */ + async put (name, value) { this.cid = undefined this.size = undefined this._children[name] = value } + /** + * @param {string} name + */ get (name) { - return this._children[name] + return Promise.resolve(this._children[name]) } childCount () { @@ -37,7 +59,7 @@ class DirFlat extends Dir { return this._children[Object.keys(this._children)[0]] } - * eachChildSeries () { + async * eachChildSeries () { const keys = Object.keys(this._children) for (let i = 0; i < keys.length; i++) { @@ -50,22 +72,28 @@ class DirFlat extends Dir { } } - async * flush (path, block) { + /** + * @param {BlockAPI} block + * @returns {AsyncIterable} + */ + async * flush (block) { const children = Object.keys(this._children) const links = [] for (let i = 0; i < children.length; i++) { let child = this._children[children[i]] - if (typeof child.flush === 'function') { - for await (const entry of child.flush(child.path, block)) { + if (child instanceof Dir) { + for await (const entry of child.flush(block)) { child = entry yield child } } - links.push(new DAGLink(children[i], child.size, child.cid)) + if (child.size != null && child.cid) { + links.push(new DAGLink(children[i], child.size, child.cid)) + } } const unixfs = new UnixFS({ @@ -77,7 +105,13 @@ class DirFlat extends Dir { const node = new DAGNode(unixfs.marshal(), links) const buffer = node.serialize() const cid = await persist(buffer, block, this.options) - const size = buffer.length + node.Links.reduce((acc, curr) => acc + curr.Tsize, 0) + const size = buffer.length + node.Links.reduce( + /** + * @param {number} acc + * @param {DAGLink} curr + */ + (acc, curr) => acc + curr.Tsize, + 0) this.cid = cid this.size = size @@ -85,7 +119,7 @@ class DirFlat extends Dir { yield { cid, unixfs, - path, + path: this.path, size } } diff --git a/packages/ipfs-unixfs-importer/src/dir-sharded.js b/packages/ipfs-unixfs-importer/src/dir-sharded.js index 2810ae49..4e9277a1 100644 --- a/packages/ipfs-unixfs-importer/src/dir-sharded.js +++ b/packages/ipfs-unixfs-importer/src/dir-sharded.js @@ -5,54 +5,47 @@ const { DAGNode } = require('ipld-dag-pb') const UnixFS = require('ipfs-unixfs') -const multihashing = require('multihashing-async') const Dir = require('./dir') const persist = require('./utils/persist') -const Bucket = require('hamt-sharding') -const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) -const uint8ArrayFromString = require('uint8arrays/from-string') - -const hashFn = async function (value) { - const buf = uint8ArrayFromString(value) - const hash = await multihashing(buf, 'murmur3-128') - - // Multihashing inserts preamble of 2 bytes. Remove it. - // Also, murmur3 outputs 128 bit but, accidently, IPFS Go's - // implementation only uses the first 64, so we must do the same - // for parity.. - const justHash = hash.slice(2, 10) - const length = justHash.length - const result = new Uint8Array(length) - // TODO: invert buffer because that's how Go impl does it - for (let i = 0; i < length; i++) { - result[length - i - 1] = justHash[i] - } +const { createHAMT, Bucket } = require('hamt-sharding') - return result -} -hashFn.code = 0x22 // TODO: get this from multihashing-async? +/** + * @typedef {import('./').ImporterOptions} ImporterOptions + * @typedef {import('./').ImportResult} ImportResult + * @typedef {import('./').PartialImportResult} PartialImportResult + * @typedef {import('./').BlockAPI} BlockAPI + */ -const defaultOptions = { - hamtHashFn: hashFn, - hamtBucketBits: 8 -} +/** + * @typedef {import('./dir').DirProps} DirProps + */ class DirSharded extends Dir { + /** + * @param {DirProps} props + * @param {ImporterOptions} options + */ constructor (props, options) { - options = mergeOptions(defaultOptions, options) - super(props, options) - this._bucket = Bucket({ + /** @type {Bucket} */ + this._bucket = createHAMT({ hashFn: options.hamtHashFn, bits: options.hamtBucketBits }) } + /** + * @param {string} name + * @param {PartialImportResult | Dir} value + */ async put (name, value) { await this._bucket.put(name, value) } + /** + * @param {string} name + */ get (name) { return this._bucket.get(name) } @@ -78,18 +71,30 @@ class DirSharded extends Dir { } } - async * flush (path, block) { - for await (const entry of flush(path, this._bucket, block, this, this.options)) { - yield entry + /** + * @param {BlockAPI} block + * @returns {AsyncIterable} + */ + async * flush (block) { + for await (const entry of flush(this._bucket, block, this, this.options)) { + yield { + ...entry, + path: this.path + } } } } module.exports = DirSharded -module.exports.hashFn = hashFn - -async function * flush (path, bucket, block, shardRoot, options) { +/** + * @param {Bucket} bucket + * @param {BlockAPI} block + * @param {*} shardRoot + * @param {ImporterOptions} options + * @returns {AsyncIterable} + */ +async function * flush (bucket, block, shardRoot, options) { const children = bucket._children const links = [] let childrenSize = 0 @@ -103,20 +108,24 @@ async function * flush (path, bucket, block, shardRoot, options) { const labelPrefix = i.toString(16).toUpperCase().padStart(2, '0') - if (Bucket.isBucket(child)) { + if (child instanceof Bucket) { let shard - for await (const subShard of await flush('', child, block, null, options)) { + for await (const subShard of await flush(child, block, null, options)) { shard = subShard } + if (!shard) { + throw new Error('Could not flush sharded directory, no subshard found') + } + links.push(new DAGLink(labelPrefix, shard.size, shard.cid)) childrenSize += shard.size } else if (typeof child.value.flush === 'function') { const dir = child.value let flushedDir - for await (const entry of dir.flush(dir.path, block)) { + for await (const entry of dir.flush(block)) { flushedDir = entry yield flushedDir @@ -148,7 +157,7 @@ async function * flush (path, bucket, block, shardRoot, options) { type: 'hamt-sharded-directory', data, fanout: bucket.tableSize(), - hashType: options.hamtHashFn.code, + hashType: options.hamtHashCode, mtime: shardRoot && shardRoot.mtime, mode: shardRoot && shardRoot.mode }) @@ -161,7 +170,6 @@ async function * flush (path, bucket, block, shardRoot, options) { yield { cid, unixfs: dir, - path, size } } diff --git a/packages/ipfs-unixfs-importer/src/dir.js b/packages/ipfs-unixfs-importer/src/dir.js index 24a1023c..db7656d7 100644 --- a/packages/ipfs-unixfs-importer/src/dir.js +++ b/packages/ipfs-unixfs-importer/src/dir.js @@ -1,8 +1,73 @@ 'use strict' -module.exports = class Dir { +/** + * @typedef {import('./').ImporterOptions} ImporterOptions + * @typedef {import('./').ImportResult} ImportResult + * @typedef {import('./').PartialImportResult} PartialImportResult + * @typedef {import('./').BlockAPI} BlockAPI + * @typedef {import('cids')} CID + * @typedef {object} DirProps + * @property {boolean} root + * @property {boolean} dir + * @property {string} path + * @property {boolean} dirty + * @property {boolean} flat + * @property {Dir} [parent] + * @property {string} [parentKey] + * @property {import('ipfs-unixfs')} [unixfs] + * @property {number} [mode] + * @property {import('ipfs-unixfs').Mtime} [mtime] + */ +class Dir { + /** + * + * @param {DirProps} props + * @param {ImporterOptions} options + */ constructor (props, options) { this.options = options || {} - Object.assign(this, props) + + this.root = props.root + this.dir = props.dir + this.path = props.path + this.dirty = props.dirty + this.flat = props.flat + this.parent = props.parent + this.parentKey = props.parentKey + this.unixfs = props.unixfs + this.mode = props.mode + this.mtime = props.mtime + + /** @type {CID | undefined} */ + this.cid = undefined + /** @type {number | undefined} */ + this.size = undefined + } + + /** + * @param {string} name + * @param {PartialImportResult | Dir} value + */ + async put (name, value) { } + + /** + * @param {string} name + * @returns {Promise} + */ + get (name) { + return Promise.resolve(this) } + + /** + * @returns {AsyncIterable<{ key: string, child: PartialImportResult | Dir}>} + */ + async * eachChildSeries () { } + + /** + * @param {BlockAPI} block + * @returns {AsyncIterable} + */ + async * flush (block) { } } + +module.exports = Dir diff --git a/packages/ipfs-unixfs-importer/src/flat-to-shard.js b/packages/ipfs-unixfs-importer/src/flat-to-shard.js index 1617b4dc..4ef40066 100644 --- a/packages/ipfs-unixfs-importer/src/flat-to-shard.js +++ b/packages/ipfs-unixfs-importer/src/flat-to-shard.js @@ -1,11 +1,24 @@ 'use strict' const DirSharded = require('./dir-sharded') +const DirFlat = require('./dir-flat') +/** + * @typedef {import('./dir')} Dir + * @typedef {import('./').ImporterOptions} ImporterOptions + */ + +/** + * @param {Dir | null} child + * @param {Dir} dir + * @param {number} threshold + * @param {ImporterOptions} options + * @returns {Promise} + */ module.exports = async function flatToShard (child, dir, threshold, options) { let newDir = dir - if (dir.flat && dir.directChildrenCount() >= threshold) { + if (dir instanceof DirFlat && dir.directChildrenCount() >= threshold) { newDir = await convertToShard(dir, options) } @@ -17,15 +30,24 @@ module.exports = async function flatToShard (child, dir, threshold, options) { child.parent = newDir } + if (!newDir.parentKey) { + throw new Error('No parent key found') + } + await parent.put(newDir.parentKey, newDir) } return flatToShard(newDir, parent, threshold, options) } + // @ts-ignore return newDir } +/** + * @param {DirFlat} oldDir + * @param {ImporterOptions} options + */ async function convertToShard (oldDir, options) { const newDir = new DirSharded({ root: oldDir.root, diff --git a/packages/ipfs-unixfs-importer/src/index.js b/packages/ipfs-unixfs-importer/src/index.js index 2559ffb3..6a993a59 100644 --- a/packages/ipfs-unixfs-importer/src/index.js +++ b/packages/ipfs-unixfs-importer/src/index.js @@ -1,40 +1,129 @@ 'use strict' const parallelBatch = require('it-parallel-batch') -const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) - -const defaultOptions = { - chunker: 'fixed', - strategy: 'balanced', // 'flat', 'trickle' - rawLeaves: false, - onlyHash: false, - reduceSingleLeafToSelf: true, - codec: 'dag-pb', - hashAlg: 'sha2-256', - leafType: 'file', // 'raw' - cidVersion: 0, - progress: () => () => {}, - shardSplitThreshold: 1000, - fileImportConcurrency: 50, - blockWriteConcurrency: 10, - minChunkSize: 262144, - maxChunkSize: 262144, - avgChunkSize: 262144, - window: 16, - polynomial: 17437180132763653, // https://github.com/ipfs/go-ipfs-chunker/blob/d0125832512163708c0804a3cda060e21acddae4/rabin.go#L11 - maxChildrenPerNode: 174, - layerRepeat: 4, - wrapWithDirectory: false, - pin: false, - recursive: false, - hidden: false, - preload: false, - chunkValidator: null, - importBuffer: null -} +const defaultOptions = require('./options') + +/** + * @typedef {import('cids')} CID + * @typedef {import('ipfs-unixfs')} UnixFS + * + * @typedef {object} Block + * @property {Uint8Array} data + * @property {CID} cid + * + * @typedef {object} BlockAPI + * @property {(cid: CID, options?: any) => Promise} get + * @property {(buffer: Uint8Array, options: any) => Promise} put + * + * @typedef {object} ImportCandidate + * @property {string} [path] + * @property {AsyncIterable | Iterable | Uint8Array | ArrayLike | string} [content] + * @property {import('ipfs-unixfs').Mtime | Date} [mtime] + * @property {number} [mode] + * + * @typedef {object} File + * @property {AsyncIterable} content + * @property {string} [path] + * @property {import('ipfs-unixfs').Mtime | Date} [mtime] + * @property {number} [mode] + * + * @typedef {object} Directory + * @property {string} path + * @property {import('ipfs-unixfs').Mtime | Date} [mtime] + * @property {number} [mode] + * + * @typedef {object} ImportResult + * @property {CID} cid + * @property {number} size + * @property {string} [path] + * @property {UnixFS} [unixfs] + * + * @typedef {object} PartialImportResult + * @property {CID} cid + * @property {number} size + * @property {string} [path] + * @property {UnixFS} [unixfs] + * @property {boolean} [single] + * + * @typedef {'fixed'|'rabin'} ChunkerType + * + * @typedef {object} UserImporterOptions + * @property {ChunkerType | import('./chunker').Chunker} [chunker='fixed'] + * @property {'balanced'|'flat'|'trickle'} [strategy='balanced'] + * @property {boolean} [rawLeaves=false] + * @property {boolean} [onlyHash=false] + * @property {boolean} [reduceSingleLeafToSelf=true] + * @property {import('multicodec').CodecName} [hashAlg='sha2-256'] + * @property {'file'|'raw'} [leafType='file'] + * @property {import('cids').CIDVersion} [cidVersion=0] + * @property {(chunkSize: number, path?: string) => void} [progress=() => {}] + * @property {number} [shardSplitThreshold=1000] + * @property {number} [fileImportConcurrency=50] + * @property {number} [blockWriteConcurrency=10] + * @property {number} [minChunkSize=262144] + * @property {number} [maxChunkSize=262144] + * @property {number} [avgChunkSize=262144] + * @property {number} [window=16] + * @property {number} [polynomial=17437180132763653] + * @property {number} [maxChildrenPerNode=174] + * @property {number} [layerRepeat=4] + * @property {boolean} [wrapWithDirectory=false] + * @property {boolean} [pin=false] + * @property {boolean} [recursive=false] + * @property {boolean} [hidden=false] + * @property {boolean} [preload=false] + * @property {string | number} [timeout] + * @property {(value: Uint8Array) => Promise} [hamtHashFn] + * @property {number} [hamtBucketBits=8] + * @property {number} [hamtHashCode=0x22] + * @property {import('./dag-builder').DAGBuilder} [dagBuilder] + * @property {import('./tree-builder').TreeBuilder} [treeBuilder] + * @property {import('./dag-builder/file/buffer-importer').BufferImporter} [bufferImporter] + * @property {import('./dag-builder/validate-chunks').ChunkValidator} [chunkValidator] + * + * @typedef {object} ImporterOptions + * @property {ChunkerType} chunker + * @property {'balanced'|'flat'|'trickle'} strategy + * @property {boolean} rawLeaves + * @property {boolean} onlyHash + * @property {boolean} reduceSingleLeafToSelf + * @property {'dag-pb'|'raw'} codec + * @property {import('multihashing-async').multihash.HashName} hashAlg + * @property {'file'|'raw'} leafType + * @property {import('cids').CIDVersion} cidVersion + * @property {(chunkSize: number, path?: string) => void} progress + * @property {number} shardSplitThreshold + * @property {number} fileImportConcurrency + * @property {number} blockWriteConcurrency + * @property {number} minChunkSize + * @property {number} maxChunkSize + * @property {number} avgChunkSize + * @property {number} window + * @property {number} polynomial + * @property {number} maxChildrenPerNode + * @property {number} layerRepeat + * @property {boolean} wrapWithDirectory + * @property {boolean} pin + * @property {boolean} recursive + * @property {boolean} hidden + * @property {boolean} preload + * @property {string | number | undefined} timeout + * @property {(value: Uint8Array) => Promise} hamtHashFn + * @property {number} hamtHashCode + * @property {number} hamtBucketBits + * @property {import('./dag-builder').DAGBuilder} [dagBuilder] + * @property {import('./tree-builder').TreeBuilder} [treeBuilder] + * @property {import('./dag-builder/file/buffer-importer').BufferImporter} [bufferImporter] + * @property {import('./dag-builder/validate-chunks').ChunkValidator} [chunkValidator] + */ +/** + * @param {AsyncIterable | Iterable} source + * @param {BlockAPI} block + * @param {UserImporterOptions} options + */ module.exports = async function * (source, block, options = {}) { - const opts = mergeOptions(defaultOptions, options) + const opts = defaultOptions(options) let dagBuilder diff --git a/packages/ipfs-unixfs-importer/src/options.js b/packages/ipfs-unixfs-importer/src/options.js new file mode 100644 index 00000000..15d02fe6 --- /dev/null +++ b/packages/ipfs-unixfs-importer/src/options.js @@ -0,0 +1,75 @@ +'use strict' + +const mergeOptions = require('merge-options').bind({ ignoreUndefined: true }) +const multihashing = require('multihashing-async') + +/** + * @param {Uint8Array} buf + */ +async function hamtHashFn (buf) { + const hash = await multihashing(buf, 'murmur3-128') + + // Multihashing inserts preamble of 2 bytes. Remove it. + // Also, murmur3 outputs 128 bit but, accidentally, IPFS Go's + // implementation only uses the first 64, so we must do the same + // for parity.. + const justHash = hash.slice(2, 10) + const length = justHash.length + const result = new Uint8Array(length) + // TODO: invert buffer because that's how Go impl does it + for (let i = 0; i < length; i++) { + result[length - i - 1] = justHash[i] + } + + return result +} + +/** + * @typedef {import('../').UserImporterOptions} UserImporterOptions + * @typedef {import('../').ImporterOptions} ImporterOptions + */ + +/** + * @type {ImporterOptions} + */ +const defaultOptions = { + chunker: 'fixed', + strategy: 'balanced', // 'flat', 'trickle' + rawLeaves: false, + onlyHash: false, + reduceSingleLeafToSelf: true, + codec: 'dag-pb', + hashAlg: 'sha2-256', + leafType: 'file', // 'raw' + cidVersion: 0, + progress: () => () => {}, + shardSplitThreshold: 1000, + fileImportConcurrency: 50, + blockWriteConcurrency: 10, + minChunkSize: 262144, + maxChunkSize: 262144, + avgChunkSize: 262144, + window: 16, + // FIXME: This number is too big for JavaScript + // https://github.com/ipfs/go-ipfs-chunker/blob/d0125832512163708c0804a3cda060e21acddae4/rabin.go#L11 + polynomial: 17437180132763653, // eslint-disable-line no-loss-of-precision + maxChildrenPerNode: 174, + layerRepeat: 4, + wrapWithDirectory: false, + pin: false, + recursive: false, + hidden: false, + preload: false, + timeout: undefined, + hamtHashFn, + hamtHashCode: 0x22, + hamtBucketBits: 8 +} + +/** + * @param {UserImporterOptions} options + * @returns {ImporterOptions} + */ +module.exports = function (options = {}) { + return mergeOptions(defaultOptions, options) +} diff --git a/packages/ipfs-unixfs-importer/src/tree-builder.js b/packages/ipfs-unixfs-importer/src/tree-builder.js index 1b13fee6..d06ee069 100644 --- a/packages/ipfs-unixfs-importer/src/tree-builder.js +++ b/packages/ipfs-unixfs-importer/src/tree-builder.js @@ -5,6 +5,19 @@ const flatToShard = require('./flat-to-shard') const Dir = require('./dir') const toPathComponents = require('./utils/to-path-components') +/** + * @typedef {import('./').ImportResult} ImportResult + * @typedef {import('./').PartialImportResult} PartialImportResult + * @typedef {import('./').ImporterOptions} ImporterOptions + * @typedef {import('./').BlockAPI} BlockAPI + * @typedef {(source: AsyncIterable, block: BlockAPI, options: ImporterOptions) => AsyncIterable} TreeBuilder + */ + +/** + * @param {PartialImportResult} elem + * @param {Dir} tree + * @param {ImporterOptions} options + */ async function addToTree (elem, tree, options) { const pathElems = toPathComponents(elem.path || '') const lastIndex = pathElems.length - 1 @@ -18,8 +31,8 @@ async function addToTree (elem, tree, options) { const last = (i === lastIndex) parent.dirty = true - parent.cid = null - parent.size = null + parent.cid = undefined + parent.size = undefined if (last) { await parent.put(pathElem, elem) @@ -29,6 +42,7 @@ async function addToTree (elem, tree, options) { if (!dir || !(dir instanceof Dir)) { dir = new DirFlat({ + root: false, dir: true, parent: parent, parentKey: pathElem, @@ -49,6 +63,10 @@ async function addToTree (elem, tree, options) { return tree } +/** + * @param {Dir | PartialImportResult} tree + * @param {BlockAPI} block + */ async function * flushAndYield (tree, block) { if (!(tree instanceof Dir)) { if (tree && tree.unixfs && tree.unixfs.isDirectory()) { @@ -58,10 +76,14 @@ async function * flushAndYield (tree, block) { return } - yield * tree.flush(tree.path, block) + yield * tree.flush(block) } +/** + * @type {TreeBuilder} + */ async function * treeBuilder (source, block, options) { + /** @type {Dir} */ let tree = new DirFlat({ root: true, dir: true, diff --git a/packages/ipfs-unixfs-importer/src/utils/persist.js b/packages/ipfs-unixfs-importer/src/utils/persist.js index afdb352e..f00d8832 100644 --- a/packages/ipfs-unixfs-importer/src/utils/persist.js +++ b/packages/ipfs-unixfs-importer/src/utils/persist.js @@ -3,6 +3,11 @@ const mh = require('multihashing-async') const CID = require('cids') +/** + * @param {Uint8Array} buffer + * @param {import('../').BlockAPI} block + * @param {import('../').ImporterOptions} options + */ const persist = async (buffer, block, options) => { if (!options.codec) { options.codec = 'dag-pb' @@ -25,7 +30,9 @@ const persist = async (buffer, block, options) => { if (!options.onlyHash) { await block.put(buffer, { - ...options, + pin: options.pin, + preload: options.preload, + timeout: options.timeout, cid }) } diff --git a/packages/ipfs-unixfs-importer/test/benchmark.spec.js b/packages/ipfs-unixfs-importer/test/benchmark.spec.js index 57f18fde..b1fdbde4 100644 --- a/packages/ipfs-unixfs-importer/test/benchmark.spec.js +++ b/packages/ipfs-unixfs-importer/test/benchmark.spec.js @@ -3,10 +3,13 @@ const importer = require('../src') +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') const bufferStream = require('it-buffer-stream') const all = require('it-all') +const blockApi = require('./helpers/block') const REPEATS = 10 const FILE_SIZE = Math.pow(2, 20) * 500 // 500MB @@ -15,18 +18,23 @@ const CHUNK_SIZE = 65536 describe.skip('benchmark', function () { this.timeout(30 * 1000) + /** @type {import('./helpers/block').IPLDResolver} */ let ipld + /** @type {import('../src').BlockAPI} */ + let block before(async () => { ipld = await inMemory(IPLD) + block = blockApi(ipld) }) + /** @type {number[]} */ const times = [] after(() => { console.info('Percent\tms') // eslint-disable-line no-console times.forEach((time, index) => { - console.info(`${index}\t${parseInt(time / REPEATS)}`) // eslint-disable-line no-console + console.info(`${index}\t${Math.round(time / REPEATS)}`) // eslint-disable-line no-console }) }) @@ -40,10 +48,13 @@ describe.skip('benchmark', function () { let lastPercent = 0 const options = { + /** + * @param {number} prog + */ progress: (prog) => { read += prog - const percent = parseInt((read / size) * 100) + const percent = Math.round((read / size) * 100) if (percent > lastPercent) { times[percent] = (times[percent] || 0) + (Date.now() - lastDate) @@ -64,7 +75,7 @@ describe.skip('benchmark', function () { return buf } }) - }], ipld, options)) + }], block, options)) }) } }) diff --git a/packages/ipfs-unixfs-importer/test/builder-balanced.spec.js b/packages/ipfs-unixfs-importer/test/builder-balanced.spec.js index 8135a803..fe472b41 100644 --- a/packages/ipfs-unixfs-importer/test/builder-balanced.spec.js +++ b/packages/ipfs-unixfs-importer/test/builder-balanced.spec.js @@ -4,42 +4,73 @@ const { expect } = require('aegir/utils/chai') const builder = require('../src/dag-builder/file/balanced') const all = require('it-all') +const CID = require('cids') +const defaultOptions = require('../src/options') -function reduce (leaves) { +/** + * @typedef {import('../src').PartialImportResult} PartialImportResult + * + * @param {PartialImportResult[]} leaves + * @returns {Promise} + */ +async function reduce (leaves) { if (leaves.length > 1) { - return { children: leaves } + return { + // @ts-ignore + children: leaves + } } else { return leaves[0] } } const options = { + ...defaultOptions(), maxChildrenPerNode: 3 } describe('builder: balanced', () => { it('reduces one value into itself', async () => { - const source = [1] + const source = [{ + cid: new CID('QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn'), + size: 0 + }] - const result = await all(builder(source, reduce, options)) + const result = await all(builder((async function * () { + yield * source + }()), reduce, options)) expect(result).to.deep.equal(source) }) it('reduces 3 values into parent', async () => { - const source = [1, 2, 3] + const source = [{ + cid: new CID('QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn'), + size: 0 + }, { + cid: new CID('QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn'), + size: 0 + }, { + cid: new CID('QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn'), + size: 0 + }] - const result = await all(builder(source, reduce, options)) + const result = await all(builder((async function * () { + yield * source + }()), reduce, options)) expect(result).to.deep.equal([{ - children: [1, 2, 3] + children: source }]) }) it('obeys max children per node', async () => { const source = [1, 2, 3, 4] - const result = await all(builder(source, reduce, options)) + // @ts-ignore + const result = await all(builder((async function * () { + yield * source + }()), reduce, options)) expect(result).to.deep.equal([{ children: [{ @@ -53,7 +84,10 @@ describe('builder: balanced', () => { it('refolds 2 parent nodes', async () => { const source = [1, 2, 3, 4, 5, 6, 7] - const result = await all(builder(source, reduce, options)) + // @ts-ignore + const result = await all(builder((async function * () { + yield * source + }()), reduce, options)) expect(result).to.deep.equal([{ children: [{ diff --git a/packages/ipfs-unixfs-importer/test/builder-flat.spec.js b/packages/ipfs-unixfs-importer/test/builder-flat.spec.js index a1559976..22f06715 100644 --- a/packages/ipfs-unixfs-importer/test/builder-flat.spec.js +++ b/packages/ipfs-unixfs-importer/test/builder-flat.spec.js @@ -5,6 +5,9 @@ const { expect } = require('aegir/utils/chai') const builder = require('../src/dag-builder/file/flat') const all = require('it-all') +/** + * @param {*} leaves + */ function reduce (leaves) { if (leaves.length > 1) { return { children: leaves } @@ -16,6 +19,7 @@ function reduce (leaves) { describe('builder: flat', () => { it('reduces one value into itself', async () => { const source = [1] + // @ts-ignore const result = await all(builder(source, reduce)) expect(result).to.be.eql([1]) @@ -23,6 +27,7 @@ describe('builder: flat', () => { it('reduces 2 values into parent', async () => { const source = [1, 2] + // @ts-ignore const result = await all(builder(source, reduce)) expect(result).to.be.eql([{ children: [1, 2] }]) diff --git a/packages/ipfs-unixfs-importer/test/builder-only-hash.spec.js b/packages/ipfs-unixfs-importer/test/builder-only-hash.spec.js index b0483e81..0aa03e4a 100644 --- a/packages/ipfs-unixfs-importer/test/builder-only-hash.spec.js +++ b/packages/ipfs-unixfs-importer/test/builder-only-hash.spec.js @@ -2,14 +2,19 @@ 'use strict' const { expect } = require('aegir/utils/chai') +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') const builder = require('../src/dag-builder') const all = require('it-all') const blockApi = require('./helpers/block') +const defaultOptions = require('../src/options') describe('builder: onlyHash', () => { + /** @type {import('./helpers/block').IPLDResolver} */ let ipld + /** @type {import('../src').BlockAPI} */ let block before(async () => { @@ -22,17 +27,8 @@ describe('builder: onlyHash', () => { path: 'foo.txt', content: Uint8Array.from([0, 1, 2, 3, 4]) }], block, { - onlyHash: true, - chunker: 'fixed', - strategy: 'balanced', - progress: () => {}, - leafType: 'file', - reduceSingleLeafToSelf: true, - format: 'dag-pb', - hashAlg: 'sha2-256', - wrap: true, - maxChunkSize: 1024, - maxChildrenPerNode: 254 + ...defaultOptions({}), + onlyHash: true })) expect(nodes.length).to.equal(1) diff --git a/packages/ipfs-unixfs-importer/test/builder-trickle-dag.spec.js b/packages/ipfs-unixfs-importer/test/builder-trickle-dag.spec.js index 45e779bd..ed748171 100644 --- a/packages/ipfs-unixfs-importer/test/builder-trickle-dag.spec.js +++ b/packages/ipfs-unixfs-importer/test/builder-trickle-dag.spec.js @@ -4,7 +4,11 @@ const { expect } = require('aegir/utils/chai') const builder = require('../src/dag-builder/file/trickle') const all = require('it-all') +const asAsyncIterable = require('./helpers/as-async-iterable') +/** + * @param {number} max + */ const createValues = (max) => { const output = [] @@ -15,6 +19,9 @@ const createValues = (max) => { return output } +/** + * @param {*} leaves + */ function reduce (leaves) { if (leaves.length > 1) { return { children: leaves } @@ -30,12 +37,14 @@ const options = { describe('builder: trickle', () => { it('reduces one value into itself', async () => { - const result = await all(builder([1], reduce, options)) + // @ts-ignore + const result = await all(builder(asAsyncIterable([1]), reduce, options)) expect(result).to.deep.equal([1]) }) it('reduces 3 values into parent', async () => { + // @ts-ignore const result = await all(builder(createValues(3), reduce, options)) expect(result).to.deep.equal([{ @@ -48,6 +57,7 @@ describe('builder: trickle', () => { }) it('reduces 6 values correctly', async () => { + // @ts-ignore const result = await all(builder(createValues(6), reduce, options)) expect(result).to.deep.equal([{ @@ -67,6 +77,7 @@ describe('builder: trickle', () => { }) it('reduces 9 values correctly', async () => { + // @ts-ignore const result = await all(builder(createValues(9), reduce, options)) expect(result).to.deep.equal([{ @@ -93,6 +104,7 @@ describe('builder: trickle', () => { }) it('reduces 12 values correctly', async () => { + // @ts-ignore const result = await all(builder(createValues(12), reduce, options)) expect(result).to.deep.equal([{ @@ -126,6 +138,7 @@ describe('builder: trickle', () => { }) it('reduces 21 values correctly', async () => { + // @ts-ignore const result = await all(builder(createValues(21), reduce, options)) expect(result).to.deep.equal([{ @@ -180,6 +193,7 @@ describe('builder: trickle', () => { }) it('reduces 68 values correctly', async () => { + // @ts-ignore const result = await all(builder(createValues(68), reduce, options)) expect(result).to.deep.equal([ @@ -347,6 +361,7 @@ describe('builder: trickle', () => { }) it('reduces 93 values correctly', async () => { + // @ts-ignore const result = await all(builder(createValues(93), reduce, options)) expect(result).to.deep.equal([ diff --git a/packages/ipfs-unixfs-importer/test/builder.spec.js b/packages/ipfs-unixfs-importer/test/builder.spec.js index d20198cc..a1b136c9 100644 --- a/packages/ipfs-unixfs-importer/test/builder.spec.js +++ b/packages/ipfs-unixfs-importer/test/builder.spec.js @@ -3,16 +3,21 @@ const { expect } = require('aegir/utils/chai') const mh = require('multihashing-async').multihash +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') const UnixFS = require('ipfs-unixfs') const builder = require('../src/dag-builder') const first = require('it-first') const blockApi = require('./helpers/block') const uint8ArrayFromString = require('uint8arrays/from-string') +const defaultOptions = require('../src/options') describe('builder', () => { + /** @type {import('./helpers/block').IPLDResolver} */ let ipld + /** @type {import('../src').BlockAPI} */ let block before(async () => { @@ -21,31 +26,27 @@ describe('builder', () => { }) const testMultihashes = Object.keys(mh.names).slice(1, 10) - const opts = { - strategy: 'flat', - chunker: 'fixed', - leafType: 'file', - reduceSingleLeafToSelf: true, - format: 'dag-pb', - hashAlg: 'sha2-256', - progress: () => {}, - maxChunkSize: 262144 - } it('allows multihash hash algorithm to be specified', async () => { for (let i = 0; i < testMultihashes.length; i++) { const hashAlg = testMultihashes[i] - const options = { - ...opts, - hashAlg - } const content = String(Math.random() + Date.now()) const inputFile = { path: content + '.txt', content: uint8ArrayFromString(content) } - const imported = await (await first(builder([inputFile], block, options)))() + const result = await first(builder([inputFile], block, { + ...defaultOptions(), + // @ts-ignore thinks these aren't valid hash alg names + hashAlg + })) + + if (!result) { + throw new Error('Nothing built') + } + + const imported = await result() expect(imported).to.exist() @@ -65,10 +66,6 @@ describe('builder', () => { for (let i = 0; i < testMultihashes.length; i++) { const hashAlg = testMultihashes[i] - const options = { - ...opts, - hashAlg - } const content = String(Math.random() + Date.now()) const inputFile = { path: content + '.txt', @@ -76,7 +73,17 @@ describe('builder', () => { content: new Uint8Array(262144 + 5).fill(1) } - const imported = await (await first(builder([inputFile], block, options)))() + const result = await first(builder([inputFile], block, { + ...defaultOptions(), + // @ts-ignore thinks these aren't valid hash alg names + hashAlg + })) + + if (!result) { + throw new Error('Nothing built') + } + + const imported = await result() expect(imported).to.exist() expect(mh.decode(imported.cid.multihash).name).to.equal(hashAlg) @@ -86,17 +93,21 @@ describe('builder', () => { it('allows multihash hash algorithm to be specified for a directory', async () => { for (let i = 0; i < testMultihashes.length; i++) { const hashAlg = testMultihashes[i] + const inputFile = { + path: `${String(Math.random() + Date.now())}-dir` + } - const options = { - ...opts, + const result = await first(builder([{ ...inputFile }], block, { + ...defaultOptions(), + // @ts-ignore thinks these aren't valid hash alg names hashAlg - } - const inputFile = { - path: `${String(Math.random() + Date.now())}-dir`, - content: null + })) + + if (!result) { + return new Error('Nothing built') } - const imported = await (await first(builder([Object.assign({}, inputFile)], block, options)))() + const imported = await result() expect(mh.decode(imported.cid.multihash).name).to.equal(hashAlg) diff --git a/packages/ipfs-unixfs-importer/test/chunker-custom.spec.js b/packages/ipfs-unixfs-importer/test/chunker-custom.spec.js index ac6765c8..d21994e0 100644 --- a/packages/ipfs-unixfs-importer/test/chunker-custom.spec.js +++ b/packages/ipfs-unixfs-importer/test/chunker-custom.spec.js @@ -3,32 +3,50 @@ const importer = require('../src') const { expect } = require('aegir/utils/chai') +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') const mc = require('multicodec') const blockApi = require('./helpers/block') const uint8ArrayFromString = require('uint8arrays/from-string') +const UnixFS = require('ipfs-unixfs') -// eslint bug https://github.com/eslint/eslint/issues/12459 -// eslint-disable-next-line require-await const iter = async function * () { yield uint8ArrayFromString('one') yield uint8ArrayFromString('two') } describe('custom chunker', function () { - let inmem + /** @type {import('./helpers/block').IPLDResolver} */ + let ipld + /** @type {import('../src').BlockAPI} */ let block - const fromPartsTest = (iter, size) => async () => { + /** + * @param {AsyncIterable} content + * @param {number} size + */ + const fromPartsTest = (content, size) => async () => { + /** + * @param {Uint8Array} buf + */ + const put = async (buf) => { + const cid = await ipld.put(buf, mc.RAW) + return { + cid, + size: buf.length, + unixfs: new UnixFS() + } + } + for await (const part of importer([{ - content: iter() + content }], block, { - chunkValidator: source => source, chunker: source => source, - bufferImporter: async function * (file, source, ipld, options) { - for await (const item of source) { - yield () => Promise.resolve(item) + bufferImporter: async function * (file, block, options) { + for await (const item of file.content) { + yield async () => put(item) } } })) { @@ -37,38 +55,28 @@ describe('custom chunker', function () { } before(async () => { - inmem = await inMemory(IPLD) - block = blockApi(inmem) + ipld = await inMemory(IPLD) + block = blockApi(ipld) }) it('keeps custom chunking', async () => { - const chunker = source => source const content = iter() for await (const part of importer([{ path: 'test', content }], block, { - chunker + chunker: source => source })) { expect(part.size).to.equal(116) } }) - // eslint bug https://github.com/eslint/eslint/issues/12459 const multi = async function * () { - yield { - size: 11, - cid: await inmem.put(uint8ArrayFromString('hello world'), mc.RAW) - } - yield { - size: 11, - cid: await inmem.put(uint8ArrayFromString('hello world'), mc.RAW) - } + yield uint8ArrayFromString('hello world') + yield uint8ArrayFromString('hello world') } - it('works with multiple parts', fromPartsTest(multi, 120)) + it('works with multiple parts', fromPartsTest(multi(), 120)) const single = async function * () { - yield { - size: 11, - cid: await inmem.put(uint8ArrayFromString('hello world'), mc.RAW) - } + yield uint8ArrayFromString('hello world') } - it('works with single part', fromPartsTest(single, 11)) + + it('works with single part', fromPartsTest(single(), 11)) }) diff --git a/packages/ipfs-unixfs-importer/test/chunker-fixed-size.spec.js b/packages/ipfs-unixfs-importer/test/chunker-fixed-size.spec.js index 17a19c17..3845fd8d 100644 --- a/packages/ipfs-unixfs-importer/test/chunker-fixed-size.spec.js +++ b/packages/ipfs-unixfs-importer/test/chunker-fixed-size.spec.js @@ -7,6 +7,8 @@ const all = require('it-all') const rawFile = new Uint8Array(Math.pow(2, 20)) const uint8ArrayFromString = require('uint8arrays/from-string') const uint8ArrayConcat = require('uint8arrays/concat') +const defaultOptions = require('../src/options') +const asAsyncIterable = require('./helpers/as-async-iterable') describe('chunker: fixed size', function () { this.timeout(30000) @@ -16,11 +18,12 @@ describe('chunker: fixed size', function () { const b2 = new Uint8Array(1 * 256) const b3 = new Uint8Array(5 * 256) - b1.fill('a') - b2.fill('b') - b3.fill('c') + b1.fill('a'.charCodeAt(0)) + b2.fill('b'.charCodeAt(0)) + b3.fill('c'.charCodeAt(0)) - const chunks = await all(chunker([b1, b2, b3], { + const chunks = await all(chunker(asAsyncIterable([b1, b2, b3]), { + ...defaultOptions(), maxChunkSize: 256 })) @@ -37,7 +40,8 @@ describe('chunker: fixed size', function () { for (let i = 0; i < (256 * 12); i++) { input.push(buf) } - const chunks = await all(chunker(input, { + const chunks = await all(chunker(asAsyncIterable(input), { + ...defaultOptions(), maxChunkSize: 256 })) @@ -49,7 +53,8 @@ describe('chunker: fixed size', function () { it('256 KiB chunks', async () => { const KiB256 = 262144 - const chunks = await all(chunker([rawFile], { + const chunks = await all(chunker(asAsyncIterable([rawFile]), { + ...defaultOptions(), maxChunkSize: KiB256 })) @@ -63,7 +68,8 @@ describe('chunker: fixed size', function () { const KiB256 = 262144 const file = uint8ArrayConcat([rawFile, uint8ArrayFromString('hello')]) - const chunks = await all(chunker([file], { + const chunks = await all(chunker(asAsyncIterable([file]), { + ...defaultOptions(), maxChunkSize: KiB256 })) diff --git a/packages/ipfs-unixfs-importer/test/chunker-rabin.spec.js b/packages/ipfs-unixfs-importer/test/chunker-rabin.spec.js index 3c61d7d8..3418e2b5 100644 --- a/packages/ipfs-unixfs-importer/test/chunker-rabin.spec.js +++ b/packages/ipfs-unixfs-importer/test/chunker-rabin.spec.js @@ -6,18 +6,14 @@ const { expect } = require('aegir/utils/chai') const all = require('it-all') const uint8ArrayFromString = require('uint8arrays/from-string') const uint8ArrayConcat = require('uint8arrays/concat') +const asAsyncIterable = require('./helpers/as-async-iterable') +const defaultOptions = require('../src/options') const rawFile = new Uint8Array(Math.pow(2, 20)).fill(1) describe('chunker: rabin', function () { this.timeout(30000) - const defaultOptions = { - avgChunkSize: 262144, - window: 64, - polynomial: 17437180132763653 - } - it('chunks non flat buffers', async () => { const b1 = new Uint8Array(2 * 256) const b2 = new Uint8Array(1 * 256) @@ -27,8 +23,8 @@ describe('chunker: rabin', function () { b2.fill('b'.charCodeAt(0)) b3.fill('c'.charCodeAt(0)) - const chunks = await all(chunker([b1, b2, b3], { - ...defaultOptions, + const chunks = await all(chunker(asAsyncIterable([b1, b2, b3]), { + ...defaultOptions(), minChunkSize: 48, avgChunkSize: 96, maxChunkSize: 192 @@ -51,8 +47,8 @@ describe('chunker: rabin', function () { const b1 = new Uint8Array(10 * 256) b1.fill('a'.charCodeAt(0)) - const chunks = await all(chunker([b1], { - ...defaultOptions, + const chunks = await all(chunker(asAsyncIterable([b1]), { + ...defaultOptions(), maxChunkSize: 262144, minChunkSize: 18, avgChunkSize: 256 @@ -68,13 +64,13 @@ describe('chunker: rabin', function () { const KiB256 = 262144 const file = uint8ArrayConcat([rawFile, uint8ArrayFromString('hello')]) const opts = { - ...defaultOptions, + ...defaultOptions(), minChunkSize: Math.round(KiB256 / 3), avgChunkSize: KiB256, maxChunkSize: Math.round(KiB256 + (KiB256 / 2)) } - const chunks = await all(chunker([file], opts)) + const chunks = await all(chunker(asAsyncIterable([file]), opts)) chunks.forEach((chunk) => { expect(chunk).to.have.length.gte(opts.minChunkSize) @@ -84,13 +80,13 @@ describe('chunker: rabin', function () { it('throws when min chunk size is too small', async () => { const opts = { - ...defaultOptions, + ...defaultOptions(), minChunkSize: 1, maxChunkSize: 100 } try { - await all(chunker([], opts)) + await all(chunker(asAsyncIterable([]), opts)) throw new Error('Should have thrown') } catch (err) { expect(err.code).to.equal('ERR_INVALID_MIN_CHUNK_SIZE') @@ -99,12 +95,13 @@ describe('chunker: rabin', function () { it('throws when avg chunk size is not specified', async () => { const opts = { - ...defaultOptions, + ...defaultOptions(), avgChunkSize: undefined } try { - await all(chunker([], opts)) + // @ts-expect-error invalid opts + await all(chunker(asAsyncIterable([]), opts)) throw new Error('Should have thrown') } catch (err) { expect(err.code).to.equal('ERR_INVALID_AVG_CHUNK_SIZE') @@ -114,13 +111,13 @@ describe('chunker: rabin', function () { it('uses the min chunk size when max and avg are too small', async () => { const file = uint8ArrayConcat([rawFile, uint8ArrayFromString('hello')]) const opts = { - ...defaultOptions, + ...defaultOptions(), minChunkSize: 100, maxChunkSize: 5, avgChunkSize: 5 } - const chunks = await all(chunker([file], opts)) + const chunks = await all(chunker(asAsyncIterable([file]), opts)) chunks.forEach((chunk, index) => { if (index === chunks.length - 1) { diff --git a/packages/ipfs-unixfs-importer/test/hash-parity-with-go-ipfs.spec.js b/packages/ipfs-unixfs-importer/test/hash-parity-with-go-ipfs.spec.js index ae2279d3..8cbce072 100644 --- a/packages/ipfs-unixfs-importer/test/hash-parity-with-go-ipfs.spec.js +++ b/packages/ipfs-unixfs-importer/test/hash-parity-with-go-ipfs.spec.js @@ -4,12 +4,16 @@ const importer = require('../src') const { expect } = require('aegir/utils/chai') +// @ts-ignore const IPLD = require('ipld') +// @ts-ignore const inMemory = require('ipld-in-memory') const randomByteStream = require('./helpers/finite-pseudorandom-byte-stream') const first = require('it-first') const blockApi = require('./helpers/block') +const defaultOptions = require('../src/options') +/** @type {('flat' | 'trickle' | 'balanced')[]} */ const strategies = [ 'flat', 'trickle', @@ -24,6 +28,7 @@ const expectedHashes = { strategies.forEach(strategy => { const options = { + ...defaultOptions(), strategy: strategy } @@ -34,7 +39,9 @@ strategies.forEach(strategy => { } describe('go-ipfs interop using importer:' + strategy, () => { + /** @type {import('./helpers/block').IPLDResolver} */ let ipld + /** @type {import('../src').BlockAPI} */ let block before(async () => { @@ -52,6 +59,10 @@ strategies.forEach(strategy => { const file = await first(importer(source, block, options)) + if (!file) { + throw new Error('Nothing imported') + } + expect(file.cid.toBaseEncodedString()).to.be.equal(expectedHashes[strategy]) }) }) diff --git a/packages/ipfs-unixfs-importer/test/helpers/as-async-iterable.js b/packages/ipfs-unixfs-importer/test/helpers/as-async-iterable.js new file mode 100644 index 00000000..28a8d3ae --- /dev/null +++ b/packages/ipfs-unixfs-importer/test/helpers/as-async-iterable.js @@ -0,0 +1,10 @@ +'use strict' + +/** + * @param {Uint8Array[]} arr + */ +async function * asAsyncIterable (arr) { + yield * arr +} + +module.exports = asAsyncIterable diff --git a/packages/ipfs-unixfs-importer/test/helpers/block.js b/packages/ipfs-unixfs-importer/test/helpers/block.js index 74728a15..ec010a3a 100644 --- a/packages/ipfs-unixfs-importer/test/helpers/block.js +++ b/packages/ipfs-unixfs-importer/test/helpers/block.js @@ -1,21 +1,39 @@ 'use strict' -const DAG_PB = require('ipld-dag-pb') +const { + DAGNode, + util +} = require('ipld-dag-pb') const multicodec = require('multicodec') const mh = require('multihashing-async').multihash -module.exports = (ipld) => { +/** + * @typedef {import('cids')} CID + * @typedef {object} IPLDResolver + * @property {(cid: CID, options?: any) => Promise} get + * @property {(node: any, codec: number, options?: any) => Promise} put + */ + +/** + * + * @param {IPLDResolver} ipld + */ +function createBlockApi (ipld) { // make ipld behave like the block api, some tests need to pull // data from ipld so can't use a simple in-memory cid->block map - return { + /** @type {import('../../src').BlockAPI} */ + const BlockApi = { put: async (buf, { cid }) => { const multihash = mh.decode(cid.multihash) + /** @type {any} */ + let obj = buf + if (cid.codec === 'dag-pb') { - buf = DAG_PB.util.deserialize(buf) + obj = util.deserialize(buf) } - await ipld.put(buf, cid.codec === 'dag-pb' ? multicodec.DAG_PB : multicodec.RAW, { + await ipld.put(obj, cid.codec === 'dag-pb' ? multicodec.DAG_PB : multicodec.RAW, { cidVersion: cid.version, hashAlg: multihash.code }) @@ -23,13 +41,18 @@ module.exports = (ipld) => { return { cid, data: buf } }, get: async (cid, options) => { - const node = await ipld.get(cid, options) + /** @type {Uint8Array} */ + let buf = await ipld.get(cid, options) - if (cid.codec === 'dag-pb') { - return node.serialize() + if (buf instanceof DAGNode) { + buf = buf.serialize() } - return { cid, data: node } + return { cid, data: buf } } } + + return BlockApi } + +module.exports = createBlockApi diff --git a/packages/ipfs-unixfs-importer/test/helpers/finite-pseudorandom-byte-stream.js b/packages/ipfs-unixfs-importer/test/helpers/finite-pseudorandom-byte-stream.js index 0371b3f6..e6593605 100644 --- a/packages/ipfs-unixfs-importer/test/helpers/finite-pseudorandom-byte-stream.js +++ b/packages/ipfs-unixfs-importer/test/helpers/finite-pseudorandom-byte-stream.js @@ -2,6 +2,10 @@ const REPEATABLE_CHUNK_SIZE = 300000 +/** + * @param {number} maxSize + * @param {number} seed + */ module.exports = function * (maxSize, seed) { const chunks = Math.ceil(maxSize / REPEATABLE_CHUNK_SIZE) let emitted = 0 @@ -18,6 +22,9 @@ module.exports = function * (maxSize, seed) { } } +/** + * @param {number} seed + */ function random (seed) { const x = Math.sin(seed) * 10000 return x - Math.floor(x) diff --git a/packages/ipfs-unixfs-importer/test/helpers/random-byte-stream.js b/packages/ipfs-unixfs-importer/test/helpers/random-byte-stream.js index 38cf2748..ff171e37 100644 --- a/packages/ipfs-unixfs-importer/test/helpers/random-byte-stream.js +++ b/packages/ipfs-unixfs-importer/test/helpers/random-byte-stream.js @@ -1,6 +1,9 @@ 'use strict' -module.exports = function * randomByteStream (seed) { +/** + * @param {number} seed + */ +function * randomByteStream (seed) { while (true) { const r = Math.floor(random(seed) * 256) seed = r @@ -9,7 +12,12 @@ module.exports = function * randomByteStream (seed) { } } +/** + * @param {number} seed + */ function random (seed) { const x = Math.sin(seed) * 10000 return x - Math.floor(x) } + +module.exports = randomByteStream diff --git a/packages/ipfs-unixfs-importer/tsconfig.json b/packages/ipfs-unixfs-importer/tsconfig.json new file mode 100644 index 00000000..c5c7aae8 --- /dev/null +++ b/packages/ipfs-unixfs-importer/tsconfig.json @@ -0,0 +1,19 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ], + "exclude": [ + "dist", + "node_modules" + ], + "references": [ + { + "path": "../ipfs-unixfs" + } + ] +} diff --git a/packages/ipfs-unixfs/package.json b/packages/ipfs-unixfs/package.json index 2c3a207c..f5739ca1 100644 --- a/packages/ipfs-unixfs/package.json +++ b/packages/ipfs-unixfs/package.json @@ -8,15 +8,16 @@ "fs": false }, "scripts": { - "test": "aegir test -t node -t browser -t webworker", - "test:node": "aegir test -t node", - "test:browser": "aegir test -t browser", - "test:webworker": "aegir test -t webworker", - "build": "aegir build", + "prepare": "run-s prepare:*", + "prepare:proto": "pbjs -t static-module -w commonjs --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/unixfs.js ./src/unixfs.proto", + "prepare:proto:types": "pbts -o src/unixfs.d.ts src/unixfs.js", + "prepare:types": "aegir build --no-bundle", + "prepare:copy": "cp ./src/*.d.ts ./dist/src", + "test": "aegir test", "clean": "rm -rf ./dist", "lint": "aegir lint", "coverage": "nyc -s aegir test -t node && nyc report --reporter=html", - "depcheck": "aegir dep-check" + "depcheck": "aegir dep-check -i mkdirp -i protobufjs -i @types/mocha -i nyc -i npm-run-all" }, "repository": { "type": "git", @@ -35,12 +36,23 @@ }, "homepage": "https://github.com/ipfs/js-ipfs-unixfs#readme", "devDependencies": { - "aegir": "^29.2.2", + "@types/mocha": "^8.2.0", + "aegir": "^30.3.0", + "mkdirp": "^1.0.4", + "npm-run-all": "^4.1.5", "nyc": "^15.0.0", - "uint8arrays": "^1.1.0" + "uint8arrays": "^2.0.5" }, "dependencies": { - "err-code": "^2.0.0", - "protons": "^2.0.0" + "err-code": "^3.0.0", + "protobufjs": "^6.10.2" + }, + "types": "dist/src/index.d.ts", + "files": [ + "src", + "dist" + ], + "eslintConfig": { + "extends": "ipfs" } } diff --git a/packages/ipfs-unixfs/src/index.js b/packages/ipfs-unixfs/src/index.js index ae22d0b8..fb85f61b 100644 --- a/packages/ipfs-unixfs/src/index.js +++ b/packages/ipfs-unixfs/src/index.js @@ -1,10 +1,16 @@ 'use strict' -const protons = require('protons') -const pb = protons(require('./unixfs.proto')) -const unixfsData = pb.Data +const { + Data: PBData +} = require('./unixfs') const errcode = require('err-code') +/** + * @typedef {object} Mtime + * @property {number} secs + * @property {number | null} [nsecs] + */ + const types = [ 'raw', 'directory', @@ -22,30 +28,25 @@ const dirTypes = [ const DEFAULT_FILE_MODE = parseInt('0644', 8) const DEFAULT_DIRECTORY_MODE = parseInt('0755', 8) -function parseArgs (args) { - if (args.length === 0) { - return { - type: 'file' - } - } - - if (args.length === 2) { - // support old-style constructor - return { - type: args[0], - data: args[1] - } +/** + * @param {string | number | undefined} [mode] + */ +function parseMode (mode) { + if (mode == null) { + return undefined } - if (typeof args[0] === 'string' || args[0] instanceof String) { - return { - type: args[0] - } + if (typeof mode === 'string') { + mode = parseInt(mode, 8) } - return args[0] + return mode & 0xFFF } +/** + * @param {null | undefined | { secs: number, nsecs?: number} | { Seconds: number, FractionalNanoseconds?: number} | Mtime | [number, number] | Date} mtime + * @returns {Mtime | undefined} + */ function parseMtime (mtime) { if (mtime == null) { return undefined @@ -54,15 +55,20 @@ function parseMtime (mtime) { // { secs, nsecs } if (Object.prototype.hasOwnProperty.call(mtime, 'secs')) { mtime = { + // @ts-ignore secs: mtime.secs, + // @ts-ignore nsecs: mtime.nsecs } } // UnixFS TimeSpec if (Object.prototype.hasOwnProperty.call(mtime, 'Seconds')) { + // @ts-ignore mtime = { + // @ts-ignore secs: mtime.Seconds, + // @ts-ignore nsecs: mtime.FractionalNanoseconds } } @@ -105,45 +111,62 @@ function parseMtime (mtime) { return undefined } + // @ts-ignore if (mtime.nsecs < 0 || mtime.nsecs > 999999999) { throw errcode(new Error('mtime-nsecs must be within the range [0,999999999]'), 'ERR_INVALID_MTIME_NSECS') } + // @ts-ignore return mtime } -function parseMode (mode) { - if (mode == null) { - return undefined - } - - if (typeof mode === 'string' || mode instanceof String) { - mode = parseInt(mode, 8) - } - - return mode & 0xFFF -} - class Data { - // decode from protobuf https://github.com/ipfs/specs/blob/master/UNIXFS.md + /** + * Decode from protobuf https://github.com/ipfs/specs/blob/master/UNIXFS.md + * + * @param {Uint8Array} marshaled + */ static unmarshal (marshaled) { - const decoded = unixfsData.decode(marshaled) + const message = PBData.decode(marshaled) + const decoded = PBData.toObject(message, { + defaults: false, + arrays: true, + longs: Number, + objects: false + }) const data = new Data({ type: types[decoded.Type], - data: decoded.hasData() ? decoded.Data : undefined, + data: decoded.Data, blockSizes: decoded.blocksizes, - mode: decoded.hasMode() ? decoded.mode : undefined, - mtime: decoded.hasMtime() ? decoded.mtime : undefined + mode: decoded.mode, + mtime: decoded.mtime + ? { + secs: decoded.mtime.Seconds, + nsecs: decoded.mtime.FractionalNanoseconds + } + : undefined }) - // make sure we honor the original mode - data._originalMode = decoded.hasMode() ? decoded.mode : undefined + // make sure we honour the original mode + data._originalMode = decoded.mode || 0 return data } - constructor (...args) { + /** + * @param {object} [options] + * @param {string} [options.type='file'] + * @param {Uint8Array} [options.data] + * @param {number[]} [options.blockSizes] + * @param {number} [options.hashType] + * @param {number} [options.fanout] + * @param {Mtime | Date | null} [options.mtime] + * @param {number | string} [options.mode] + */ + constructor (options = { + type: 'file' + }) { const { type, data, @@ -152,56 +175,76 @@ class Data { fanout, mtime, mode - } = parseArgs(args) + } = options - if (!types.includes(type)) { + if (type && !types.includes(type)) { throw errcode(new Error('Type: ' + type + ' is not valid'), 'ERR_INVALID_TYPE') } - this.type = type + this.type = type || 'file' this.data = data this.hashType = hashType this.fanout = fanout - this.blockSizes = blockSizes || [] - const parsedMode = parseMode(mode) + /** @type {number[]} */ + this.blockSizes = blockSizes || [] + this._originalMode = 0 + this.mode = parseMode(mode) - if (parsedMode !== undefined) { - this.mode = parsedMode - } + if (mtime) { + this.mtime = parseMtime(mtime) - if (this.mode === undefined && type === 'file') { - this.mode = DEFAULT_FILE_MODE + if (this.mtime && !this.mtime.nsecs) { + this.mtime.nsecs = 0 + } } + } - if (this.mode === undefined && this.isDirectory()) { - this.mode = DEFAULT_DIRECTORY_MODE - } + /** + * @param {number | undefined} mode + */ + set mode (mode) { + this._mode = this.isDirectory() ? DEFAULT_DIRECTORY_MODE : DEFAULT_FILE_MODE - const parsedMtime = parseMtime(mtime) + const parsedMode = parseMode(mode) - if (parsedMtime) { - this.mtime = parsedMtime + if (parsedMode !== undefined) { + this._mode = parsedMode } } + /** + * @returns {number | undefined} + */ + get mode () { + return this._mode + } + isDirectory () { - return dirTypes.includes(this.type) + return Boolean(this.type && dirTypes.includes(this.type)) } + /** + * @param {number} size + */ addBlockSize (size) { this.blockSizes.push(size) } + /** + * @param {number} index + */ removeBlockSize (index) { this.blockSizes.splice(index, 1) } - // data.length + blockSizes + /** + * Returns `0` for directories or `data.length + sum(blockSizes)` for everything else + */ fileSize () { if (this.isDirectory()) { // dirs don't have file size - return undefined + return 0 } let sum = 0 @@ -216,17 +259,19 @@ class Data { return sum } - // encode to protobuf + /** + * encode to protobuf Uint8Array + */ marshal () { let type switch (this.type) { - case 'raw': type = unixfsData.DataType.Raw; break - case 'directory': type = unixfsData.DataType.Directory; break - case 'file': type = unixfsData.DataType.File; break - case 'metadata': type = unixfsData.DataType.Metadata; break - case 'symlink': type = unixfsData.DataType.Symlink; break - case 'hamt-sharded-directory': type = unixfsData.DataType.HAMTShard; break + case 'raw': type = PBData.DataType.Raw; break + case 'directory': type = PBData.DataType.Directory; break + case 'file': type = PBData.DataType.File; break + case 'metadata': type = PBData.DataType.Metadata; break + case 'symlink': type = PBData.DataType.Symlink; break + case 'hamt-sharded-directory': type = PBData.DataType.HAMTShard; break default: throw errcode(new Error('Type: ' + type + ' is not valid'), 'ERR_INVALID_TYPE') } @@ -237,18 +282,12 @@ class Data { data = undefined } - let blockSizes = this.blockSizes - - if (!this.blockSizes || !this.blockSizes.length) { - blockSizes = undefined - } - let mode if (this.mode != null) { - mode = (this._originalMode & 0xFFFFF000) | parseMode(this.mode) + mode = (this._originalMode & 0xFFFFF000) | (parseMode(this.mode) || 0) - if (mode === DEFAULT_FILE_MODE && this.type === 'file') { + if (mode === DEFAULT_FILE_MODE && !this.isDirectory()) { mode = undefined } @@ -274,16 +313,18 @@ class Data { } } - return unixfsData.encode({ + const pbData = { Type: type, Data: data, - filesize: this.fileSize(), - blocksizes: blockSizes, + filesize: this.isDirectory() ? undefined : this.fileSize(), + blocksizes: this.blockSizes, hashType: this.hashType, fanout: this.fanout, mode, mtime - }) + } + + return PBData.encode(pbData).finish() } } diff --git a/packages/ipfs-unixfs/src/unixfs.d.ts b/packages/ipfs-unixfs/src/unixfs.d.ts new file mode 100644 index 00000000..ca5a8549 --- /dev/null +++ b/packages/ipfs-unixfs/src/unixfs.d.ts @@ -0,0 +1,238 @@ +import * as $protobuf from "protobufjs"; +/** Properties of a Data. */ +export interface IData { + + /** Data Type */ + Type: Data.DataType; + + /** Data Data */ + Data?: (Uint8Array|null); + + /** Data filesize */ + filesize?: (number|null); + + /** Data blocksizes */ + blocksizes?: (number[]|null); + + /** Data hashType */ + hashType?: (number|null); + + /** Data fanout */ + fanout?: (number|null); + + /** Data mode */ + mode?: (number|null); + + /** Data mtime */ + mtime?: (IUnixTime|null); +} + +/** Represents a Data. */ +export class Data implements IData { + + /** + * Constructs a new Data. + * @param [p] Properties to set + */ + constructor(p?: IData); + + /** Data Type. */ + public Type: Data.DataType; + + /** Data Data. */ + public Data: Uint8Array; + + /** Data filesize. */ + public filesize: number; + + /** Data blocksizes. */ + public blocksizes: number[]; + + /** Data hashType. */ + public hashType: number; + + /** Data fanout. */ + public fanout: number; + + /** Data mode. */ + public mode: number; + + /** Data mtime. */ + public mtime?: (IUnixTime|null); + + /** + * Encodes the specified Data message. Does not implicitly {@link Data.verify|verify} messages. + * @param m Data message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: IData, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a Data message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns Data + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Data; + + /** + * Creates a Data message from a plain object. Also converts values to their respective internal types. + * @param d Plain object + * @returns Data + */ + public static fromObject(d: { [k: string]: any }): Data; + + /** + * Creates a plain object from a Data message. Also converts values to other types if specified. + * @param m Data + * @param [o] Conversion options + * @returns Plain object + */ + public static toObject(m: Data, o?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this Data to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; +} + +export namespace Data { + + /** DataType enum. */ + enum DataType { + Raw = 0, + Directory = 1, + File = 2, + Metadata = 3, + Symlink = 4, + HAMTShard = 5 + } +} + +/** Properties of an UnixTime. */ +export interface IUnixTime { + + /** UnixTime Seconds */ + Seconds: number; + + /** UnixTime FractionalNanoseconds */ + FractionalNanoseconds?: (number|null); +} + +/** Represents an UnixTime. */ +export class UnixTime implements IUnixTime { + + /** + * Constructs a new UnixTime. + * @param [p] Properties to set + */ + constructor(p?: IUnixTime); + + /** UnixTime Seconds. */ + public Seconds: number; + + /** UnixTime FractionalNanoseconds. */ + public FractionalNanoseconds: number; + + /** + * Encodes the specified UnixTime message. Does not implicitly {@link UnixTime.verify|verify} messages. + * @param m UnixTime message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: IUnixTime, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes an UnixTime message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns UnixTime + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): UnixTime; + + /** + * Creates an UnixTime message from a plain object. Also converts values to their respective internal types. + * @param d Plain object + * @returns UnixTime + */ + public static fromObject(d: { [k: string]: any }): UnixTime; + + /** + * Creates a plain object from an UnixTime message. Also converts values to other types if specified. + * @param m UnixTime + * @param [o] Conversion options + * @returns Plain object + */ + public static toObject(m: UnixTime, o?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this UnixTime to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; +} + +/** Properties of a Metadata. */ +export interface IMetadata { + + /** Metadata MimeType */ + MimeType?: (string|null); +} + +/** Represents a Metadata. */ +export class Metadata implements IMetadata { + + /** + * Constructs a new Metadata. + * @param [p] Properties to set + */ + constructor(p?: IMetadata); + + /** Metadata MimeType. */ + public MimeType: string; + + /** + * Encodes the specified Metadata message. Does not implicitly {@link Metadata.verify|verify} messages. + * @param m Metadata message or plain object to encode + * @param [w] Writer to encode to + * @returns Writer + */ + public static encode(m: IMetadata, w?: $protobuf.Writer): $protobuf.Writer; + + /** + * Decodes a Metadata message from the specified reader or buffer. + * @param r Reader or buffer to decode from + * @param [l] Message length if known beforehand + * @returns Metadata + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Metadata; + + /** + * Creates a Metadata message from a plain object. Also converts values to their respective internal types. + * @param d Plain object + * @returns Metadata + */ + public static fromObject(d: { [k: string]: any }): Metadata; + + /** + * Creates a plain object from a Metadata message. Also converts values to other types if specified. + * @param m Metadata + * @param [o] Conversion options + * @returns Plain object + */ + public static toObject(m: Metadata, o?: $protobuf.IConversionOptions): { [k: string]: any }; + + /** + * Converts this Metadata to JSON. + * @returns JSON object + */ + public toJSON(): { [k: string]: any }; +} diff --git a/packages/ipfs-unixfs/src/unixfs.js b/packages/ipfs-unixfs/src/unixfs.js new file mode 100644 index 00000000..d7819a67 --- /dev/null +++ b/packages/ipfs-unixfs/src/unixfs.js @@ -0,0 +1,720 @@ +/*eslint-disable*/ +"use strict"; + +var $protobuf = require("protobufjs/minimal"); + +// Common aliases +var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util; + +// Exported root namespace +var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {}); + +$root.Data = (function() { + + /** + * Properties of a Data. + * @exports IData + * @interface IData + * @property {Data.DataType} Type Data Type + * @property {Uint8Array|null} [Data] Data Data + * @property {number|null} [filesize] Data filesize + * @property {Array.|null} [blocksizes] Data blocksizes + * @property {number|null} [hashType] Data hashType + * @property {number|null} [fanout] Data fanout + * @property {number|null} [mode] Data mode + * @property {IUnixTime|null} [mtime] Data mtime + */ + + /** + * Constructs a new Data. + * @exports Data + * @classdesc Represents a Data. + * @implements IData + * @constructor + * @param {IData=} [p] Properties to set + */ + function Data(p) { + this.blocksizes = []; + if (p) + for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) + if (p[ks[i]] != null) + this[ks[i]] = p[ks[i]]; + } + + /** + * Data Type. + * @member {Data.DataType} Type + * @memberof Data + * @instance + */ + Data.prototype.Type = 0; + + /** + * Data Data. + * @member {Uint8Array} Data + * @memberof Data + * @instance + */ + Data.prototype.Data = $util.newBuffer([]); + + /** + * Data filesize. + * @member {number} filesize + * @memberof Data + * @instance + */ + Data.prototype.filesize = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Data blocksizes. + * @member {Array.} blocksizes + * @memberof Data + * @instance + */ + Data.prototype.blocksizes = $util.emptyArray; + + /** + * Data hashType. + * @member {number} hashType + * @memberof Data + * @instance + */ + Data.prototype.hashType = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Data fanout. + * @member {number} fanout + * @memberof Data + * @instance + */ + Data.prototype.fanout = $util.Long ? $util.Long.fromBits(0,0,true) : 0; + + /** + * Data mode. + * @member {number} mode + * @memberof Data + * @instance + */ + Data.prototype.mode = 0; + + /** + * Data mtime. + * @member {IUnixTime|null|undefined} mtime + * @memberof Data + * @instance + */ + Data.prototype.mtime = null; + + /** + * Encodes the specified Data message. Does not implicitly {@link Data.verify|verify} messages. + * @function encode + * @memberof Data + * @static + * @param {IData} m Data message or plain object to encode + * @param {$protobuf.Writer} [w] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Data.encode = function encode(m, w) { + if (!w) + w = $Writer.create(); + w.uint32(8).int32(m.Type); + if (m.Data != null && Object.hasOwnProperty.call(m, "Data")) + w.uint32(18).bytes(m.Data); + if (m.filesize != null && Object.hasOwnProperty.call(m, "filesize")) + w.uint32(24).uint64(m.filesize); + if (m.blocksizes != null && m.blocksizes.length) { + for (var i = 0; i < m.blocksizes.length; ++i) + w.uint32(32).uint64(m.blocksizes[i]); + } + if (m.hashType != null && Object.hasOwnProperty.call(m, "hashType")) + w.uint32(40).uint64(m.hashType); + if (m.fanout != null && Object.hasOwnProperty.call(m, "fanout")) + w.uint32(48).uint64(m.fanout); + if (m.mode != null && Object.hasOwnProperty.call(m, "mode")) + w.uint32(56).uint32(m.mode); + if (m.mtime != null && Object.hasOwnProperty.call(m, "mtime")) + $root.UnixTime.encode(m.mtime, w.uint32(66).fork()).ldelim(); + return w; + }; + + /** + * Decodes a Data message from the specified reader or buffer. + * @function decode + * @memberof Data + * @static + * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from + * @param {number} [l] Message length if known beforehand + * @returns {Data} Data + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Data.decode = function decode(r, l) { + if (!(r instanceof $Reader)) + r = $Reader.create(r); + var c = l === undefined ? r.len : r.pos + l, m = new $root.Data(); + while (r.pos < c) { + var t = r.uint32(); + switch (t >>> 3) { + case 1: + m.Type = r.int32(); + break; + case 2: + m.Data = r.bytes(); + break; + case 3: + m.filesize = r.uint64(); + break; + case 4: + if (!(m.blocksizes && m.blocksizes.length)) + m.blocksizes = []; + if ((t & 7) === 2) { + var c2 = r.uint32() + r.pos; + while (r.pos < c2) + m.blocksizes.push(r.uint64()); + } else + m.blocksizes.push(r.uint64()); + break; + case 5: + m.hashType = r.uint64(); + break; + case 6: + m.fanout = r.uint64(); + break; + case 7: + m.mode = r.uint32(); + break; + case 8: + m.mtime = $root.UnixTime.decode(r, r.uint32()); + break; + default: + r.skipType(t & 7); + break; + } + } + if (!m.hasOwnProperty("Type")) + throw $util.ProtocolError("missing required 'Type'", { instance: m }); + return m; + }; + + /** + * Creates a Data message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof Data + * @static + * @param {Object.} d Plain object + * @returns {Data} Data + */ + Data.fromObject = function fromObject(d) { + if (d instanceof $root.Data) + return d; + var m = new $root.Data(); + switch (d.Type) { + case "Raw": + case 0: + m.Type = 0; + break; + case "Directory": + case 1: + m.Type = 1; + break; + case "File": + case 2: + m.Type = 2; + break; + case "Metadata": + case 3: + m.Type = 3; + break; + case "Symlink": + case 4: + m.Type = 4; + break; + case "HAMTShard": + case 5: + m.Type = 5; + break; + } + if (d.Data != null) { + if (typeof d.Data === "string") + $util.base64.decode(d.Data, m.Data = $util.newBuffer($util.base64.length(d.Data)), 0); + else if (d.Data.length) + m.Data = d.Data; + } + if (d.filesize != null) { + if ($util.Long) + (m.filesize = $util.Long.fromValue(d.filesize)).unsigned = true; + else if (typeof d.filesize === "string") + m.filesize = parseInt(d.filesize, 10); + else if (typeof d.filesize === "number") + m.filesize = d.filesize; + else if (typeof d.filesize === "object") + m.filesize = new $util.LongBits(d.filesize.low >>> 0, d.filesize.high >>> 0).toNumber(true); + } + if (d.blocksizes) { + if (!Array.isArray(d.blocksizes)) + throw TypeError(".Data.blocksizes: array expected"); + m.blocksizes = []; + for (var i = 0; i < d.blocksizes.length; ++i) { + if ($util.Long) + (m.blocksizes[i] = $util.Long.fromValue(d.blocksizes[i])).unsigned = true; + else if (typeof d.blocksizes[i] === "string") + m.blocksizes[i] = parseInt(d.blocksizes[i], 10); + else if (typeof d.blocksizes[i] === "number") + m.blocksizes[i] = d.blocksizes[i]; + else if (typeof d.blocksizes[i] === "object") + m.blocksizes[i] = new $util.LongBits(d.blocksizes[i].low >>> 0, d.blocksizes[i].high >>> 0).toNumber(true); + } + } + if (d.hashType != null) { + if ($util.Long) + (m.hashType = $util.Long.fromValue(d.hashType)).unsigned = true; + else if (typeof d.hashType === "string") + m.hashType = parseInt(d.hashType, 10); + else if (typeof d.hashType === "number") + m.hashType = d.hashType; + else if (typeof d.hashType === "object") + m.hashType = new $util.LongBits(d.hashType.low >>> 0, d.hashType.high >>> 0).toNumber(true); + } + if (d.fanout != null) { + if ($util.Long) + (m.fanout = $util.Long.fromValue(d.fanout)).unsigned = true; + else if (typeof d.fanout === "string") + m.fanout = parseInt(d.fanout, 10); + else if (typeof d.fanout === "number") + m.fanout = d.fanout; + else if (typeof d.fanout === "object") + m.fanout = new $util.LongBits(d.fanout.low >>> 0, d.fanout.high >>> 0).toNumber(true); + } + if (d.mode != null) { + m.mode = d.mode >>> 0; + } + if (d.mtime != null) { + if (typeof d.mtime !== "object") + throw TypeError(".Data.mtime: object expected"); + m.mtime = $root.UnixTime.fromObject(d.mtime); + } + return m; + }; + + /** + * Creates a plain object from a Data message. Also converts values to other types if specified. + * @function toObject + * @memberof Data + * @static + * @param {Data} m Data + * @param {$protobuf.IConversionOptions} [o] Conversion options + * @returns {Object.} Plain object + */ + Data.toObject = function toObject(m, o) { + if (!o) + o = {}; + var d = {}; + if (o.arrays || o.defaults) { + d.blocksizes = []; + } + if (o.defaults) { + d.Type = o.enums === String ? "Raw" : 0; + if (o.bytes === String) + d.Data = ""; + else { + d.Data = []; + if (o.bytes !== Array) + d.Data = $util.newBuffer(d.Data); + } + if ($util.Long) { + var n = new $util.Long(0, 0, true); + d.filesize = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n; + } else + d.filesize = o.longs === String ? "0" : 0; + if ($util.Long) { + var n = new $util.Long(0, 0, true); + d.hashType = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n; + } else + d.hashType = o.longs === String ? "0" : 0; + if ($util.Long) { + var n = new $util.Long(0, 0, true); + d.fanout = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n; + } else + d.fanout = o.longs === String ? "0" : 0; + d.mode = 0; + d.mtime = null; + } + if (m.Type != null && m.hasOwnProperty("Type")) { + d.Type = o.enums === String ? $root.Data.DataType[m.Type] : m.Type; + } + if (m.Data != null && m.hasOwnProperty("Data")) { + d.Data = o.bytes === String ? $util.base64.encode(m.Data, 0, m.Data.length) : o.bytes === Array ? Array.prototype.slice.call(m.Data) : m.Data; + } + if (m.filesize != null && m.hasOwnProperty("filesize")) { + if (typeof m.filesize === "number") + d.filesize = o.longs === String ? String(m.filesize) : m.filesize; + else + d.filesize = o.longs === String ? $util.Long.prototype.toString.call(m.filesize) : o.longs === Number ? new $util.LongBits(m.filesize.low >>> 0, m.filesize.high >>> 0).toNumber(true) : m.filesize; + } + if (m.blocksizes && m.blocksizes.length) { + d.blocksizes = []; + for (var j = 0; j < m.blocksizes.length; ++j) { + if (typeof m.blocksizes[j] === "number") + d.blocksizes[j] = o.longs === String ? String(m.blocksizes[j]) : m.blocksizes[j]; + else + d.blocksizes[j] = o.longs === String ? $util.Long.prototype.toString.call(m.blocksizes[j]) : o.longs === Number ? new $util.LongBits(m.blocksizes[j].low >>> 0, m.blocksizes[j].high >>> 0).toNumber(true) : m.blocksizes[j]; + } + } + if (m.hashType != null && m.hasOwnProperty("hashType")) { + if (typeof m.hashType === "number") + d.hashType = o.longs === String ? String(m.hashType) : m.hashType; + else + d.hashType = o.longs === String ? $util.Long.prototype.toString.call(m.hashType) : o.longs === Number ? new $util.LongBits(m.hashType.low >>> 0, m.hashType.high >>> 0).toNumber(true) : m.hashType; + } + if (m.fanout != null && m.hasOwnProperty("fanout")) { + if (typeof m.fanout === "number") + d.fanout = o.longs === String ? String(m.fanout) : m.fanout; + else + d.fanout = o.longs === String ? $util.Long.prototype.toString.call(m.fanout) : o.longs === Number ? new $util.LongBits(m.fanout.low >>> 0, m.fanout.high >>> 0).toNumber(true) : m.fanout; + } + if (m.mode != null && m.hasOwnProperty("mode")) { + d.mode = m.mode; + } + if (m.mtime != null && m.hasOwnProperty("mtime")) { + d.mtime = $root.UnixTime.toObject(m.mtime, o); + } + return d; + }; + + /** + * Converts this Data to JSON. + * @function toJSON + * @memberof Data + * @instance + * @returns {Object.} JSON object + */ + Data.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + /** + * DataType enum. + * @name Data.DataType + * @enum {number} + * @property {number} Raw=0 Raw value + * @property {number} Directory=1 Directory value + * @property {number} File=2 File value + * @property {number} Metadata=3 Metadata value + * @property {number} Symlink=4 Symlink value + * @property {number} HAMTShard=5 HAMTShard value + */ + Data.DataType = (function() { + var valuesById = {}, values = Object.create(valuesById); + values[valuesById[0] = "Raw"] = 0; + values[valuesById[1] = "Directory"] = 1; + values[valuesById[2] = "File"] = 2; + values[valuesById[3] = "Metadata"] = 3; + values[valuesById[4] = "Symlink"] = 4; + values[valuesById[5] = "HAMTShard"] = 5; + return values; + })(); + + return Data; +})(); + +$root.UnixTime = (function() { + + /** + * Properties of an UnixTime. + * @exports IUnixTime + * @interface IUnixTime + * @property {number} Seconds UnixTime Seconds + * @property {number|null} [FractionalNanoseconds] UnixTime FractionalNanoseconds + */ + + /** + * Constructs a new UnixTime. + * @exports UnixTime + * @classdesc Represents an UnixTime. + * @implements IUnixTime + * @constructor + * @param {IUnixTime=} [p] Properties to set + */ + function UnixTime(p) { + if (p) + for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) + if (p[ks[i]] != null) + this[ks[i]] = p[ks[i]]; + } + + /** + * UnixTime Seconds. + * @member {number} Seconds + * @memberof UnixTime + * @instance + */ + UnixTime.prototype.Seconds = $util.Long ? $util.Long.fromBits(0,0,false) : 0; + + /** + * UnixTime FractionalNanoseconds. + * @member {number} FractionalNanoseconds + * @memberof UnixTime + * @instance + */ + UnixTime.prototype.FractionalNanoseconds = 0; + + /** + * Encodes the specified UnixTime message. Does not implicitly {@link UnixTime.verify|verify} messages. + * @function encode + * @memberof UnixTime + * @static + * @param {IUnixTime} m UnixTime message or plain object to encode + * @param {$protobuf.Writer} [w] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + UnixTime.encode = function encode(m, w) { + if (!w) + w = $Writer.create(); + w.uint32(8).int64(m.Seconds); + if (m.FractionalNanoseconds != null && Object.hasOwnProperty.call(m, "FractionalNanoseconds")) + w.uint32(21).fixed32(m.FractionalNanoseconds); + return w; + }; + + /** + * Decodes an UnixTime message from the specified reader or buffer. + * @function decode + * @memberof UnixTime + * @static + * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from + * @param {number} [l] Message length if known beforehand + * @returns {UnixTime} UnixTime + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + UnixTime.decode = function decode(r, l) { + if (!(r instanceof $Reader)) + r = $Reader.create(r); + var c = l === undefined ? r.len : r.pos + l, m = new $root.UnixTime(); + while (r.pos < c) { + var t = r.uint32(); + switch (t >>> 3) { + case 1: + m.Seconds = r.int64(); + break; + case 2: + m.FractionalNanoseconds = r.fixed32(); + break; + default: + r.skipType(t & 7); + break; + } + } + if (!m.hasOwnProperty("Seconds")) + throw $util.ProtocolError("missing required 'Seconds'", { instance: m }); + return m; + }; + + /** + * Creates an UnixTime message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof UnixTime + * @static + * @param {Object.} d Plain object + * @returns {UnixTime} UnixTime + */ + UnixTime.fromObject = function fromObject(d) { + if (d instanceof $root.UnixTime) + return d; + var m = new $root.UnixTime(); + if (d.Seconds != null) { + if ($util.Long) + (m.Seconds = $util.Long.fromValue(d.Seconds)).unsigned = false; + else if (typeof d.Seconds === "string") + m.Seconds = parseInt(d.Seconds, 10); + else if (typeof d.Seconds === "number") + m.Seconds = d.Seconds; + else if (typeof d.Seconds === "object") + m.Seconds = new $util.LongBits(d.Seconds.low >>> 0, d.Seconds.high >>> 0).toNumber(); + } + if (d.FractionalNanoseconds != null) { + m.FractionalNanoseconds = d.FractionalNanoseconds >>> 0; + } + return m; + }; + + /** + * Creates a plain object from an UnixTime message. Also converts values to other types if specified. + * @function toObject + * @memberof UnixTime + * @static + * @param {UnixTime} m UnixTime + * @param {$protobuf.IConversionOptions} [o] Conversion options + * @returns {Object.} Plain object + */ + UnixTime.toObject = function toObject(m, o) { + if (!o) + o = {}; + var d = {}; + if (o.defaults) { + if ($util.Long) { + var n = new $util.Long(0, 0, false); + d.Seconds = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n; + } else + d.Seconds = o.longs === String ? "0" : 0; + d.FractionalNanoseconds = 0; + } + if (m.Seconds != null && m.hasOwnProperty("Seconds")) { + if (typeof m.Seconds === "number") + d.Seconds = o.longs === String ? String(m.Seconds) : m.Seconds; + else + d.Seconds = o.longs === String ? $util.Long.prototype.toString.call(m.Seconds) : o.longs === Number ? new $util.LongBits(m.Seconds.low >>> 0, m.Seconds.high >>> 0).toNumber() : m.Seconds; + } + if (m.FractionalNanoseconds != null && m.hasOwnProperty("FractionalNanoseconds")) { + d.FractionalNanoseconds = m.FractionalNanoseconds; + } + return d; + }; + + /** + * Converts this UnixTime to JSON. + * @function toJSON + * @memberof UnixTime + * @instance + * @returns {Object.} JSON object + */ + UnixTime.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return UnixTime; +})(); + +$root.Metadata = (function() { + + /** + * Properties of a Metadata. + * @exports IMetadata + * @interface IMetadata + * @property {string|null} [MimeType] Metadata MimeType + */ + + /** + * Constructs a new Metadata. + * @exports Metadata + * @classdesc Represents a Metadata. + * @implements IMetadata + * @constructor + * @param {IMetadata=} [p] Properties to set + */ + function Metadata(p) { + if (p) + for (var ks = Object.keys(p), i = 0; i < ks.length; ++i) + if (p[ks[i]] != null) + this[ks[i]] = p[ks[i]]; + } + + /** + * Metadata MimeType. + * @member {string} MimeType + * @memberof Metadata + * @instance + */ + Metadata.prototype.MimeType = ""; + + /** + * Encodes the specified Metadata message. Does not implicitly {@link Metadata.verify|verify} messages. + * @function encode + * @memberof Metadata + * @static + * @param {IMetadata} m Metadata message or plain object to encode + * @param {$protobuf.Writer} [w] Writer to encode to + * @returns {$protobuf.Writer} Writer + */ + Metadata.encode = function encode(m, w) { + if (!w) + w = $Writer.create(); + if (m.MimeType != null && Object.hasOwnProperty.call(m, "MimeType")) + w.uint32(10).string(m.MimeType); + return w; + }; + + /** + * Decodes a Metadata message from the specified reader or buffer. + * @function decode + * @memberof Metadata + * @static + * @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from + * @param {number} [l] Message length if known beforehand + * @returns {Metadata} Metadata + * @throws {Error} If the payload is not a reader or valid buffer + * @throws {$protobuf.util.ProtocolError} If required fields are missing + */ + Metadata.decode = function decode(r, l) { + if (!(r instanceof $Reader)) + r = $Reader.create(r); + var c = l === undefined ? r.len : r.pos + l, m = new $root.Metadata(); + while (r.pos < c) { + var t = r.uint32(); + switch (t >>> 3) { + case 1: + m.MimeType = r.string(); + break; + default: + r.skipType(t & 7); + break; + } + } + return m; + }; + + /** + * Creates a Metadata message from a plain object. Also converts values to their respective internal types. + * @function fromObject + * @memberof Metadata + * @static + * @param {Object.} d Plain object + * @returns {Metadata} Metadata + */ + Metadata.fromObject = function fromObject(d) { + if (d instanceof $root.Metadata) + return d; + var m = new $root.Metadata(); + if (d.MimeType != null) { + m.MimeType = String(d.MimeType); + } + return m; + }; + + /** + * Creates a plain object from a Metadata message. Also converts values to other types if specified. + * @function toObject + * @memberof Metadata + * @static + * @param {Metadata} m Metadata + * @param {$protobuf.IConversionOptions} [o] Conversion options + * @returns {Object.} Plain object + */ + Metadata.toObject = function toObject(m, o) { + if (!o) + o = {}; + var d = {}; + if (o.defaults) { + d.MimeType = ""; + } + if (m.MimeType != null && m.hasOwnProperty("MimeType")) { + d.MimeType = m.MimeType; + } + return d; + }; + + /** + * Converts this Metadata to JSON. + * @function toJSON + * @memberof Metadata + * @instance + * @returns {Object.} JSON object + */ + Metadata.prototype.toJSON = function toJSON() { + return this.constructor.toObject(this, $protobuf.util.toJSONOptions); + }; + + return Metadata; +})(); + +module.exports = $root; diff --git a/packages/ipfs-unixfs/src/unixfs.proto.js b/packages/ipfs-unixfs/src/unixfs.proto similarity index 94% rename from packages/ipfs-unixfs/src/unixfs.proto.js rename to packages/ipfs-unixfs/src/unixfs.proto index 5b6b3181..d351f402 100644 --- a/packages/ipfs-unixfs/src/unixfs.proto.js +++ b/packages/ipfs-unixfs/src/unixfs.proto @@ -1,6 +1,3 @@ -'use strict' - -module.exports = ` syntax = "proto2"; message Data { @@ -31,4 +28,3 @@ message UnixTime { message Metadata { optional string MimeType = 1; } -` diff --git a/packages/ipfs-unixfs/test/unixfs-format.spec.js b/packages/ipfs-unixfs/test/unixfs-format.spec.js index ed934353..5e05432a 100644 --- a/packages/ipfs-unixfs/test/unixfs-format.spec.js +++ b/packages/ipfs-unixfs/test/unixfs-format.spec.js @@ -2,6 +2,9 @@ 'use strict' const { expect } = require('aegir/utils/chai') + +/** @type {(path: string) => Uint8Array} */ +// @ts-ignore const loadFixture = require('aegir/fixtures') const UnixFS = require('../src') @@ -10,25 +13,12 @@ const raw = loadFixture('test/fixtures/raw.unixfs') const directory = loadFixture('test/fixtures/directory.unixfs') const file = loadFixture('test/fixtures/file.txt.unixfs') const symlink = loadFixture('test/fixtures/symlink.txt.unixfs') -const protons = require('protons') -const unixfsData = protons(require('../src/unixfs.proto')).Data +const { + Data: PBData +} = require('../src/unixfs') const uint8ArrayFromString = require('uint8arrays/from-string') describe('unixfs-format', () => { - it('old style constructor', () => { - const buf = uint8ArrayFromString('hello world') - const entry = new UnixFS('file', buf) - - expect(entry.type).to.equal('file') - expect(entry.data).to.deep.equal(buf) - }) - - it('old style constructor with single argument', () => { - const entry = new UnixFS('file') - - expect(entry.type).to.equal('file') - }) - it('defaults to file', () => { const data = new UnixFS() expect(data.type).to.equal('file') @@ -175,6 +165,7 @@ describe('unixfs-format', () => { const data = new UnixFS({ type: 'file' }) + // @ts-ignore it's ok, really data.mode = '0555' expect(UnixFS.unmarshal(data.marshal())).to.have.property('mode', parseInt('0555', 8)) @@ -205,53 +196,6 @@ describe('unixfs-format', () => { expect(unmarshaled).to.not.have.property('mtime') }) - it('mtime as date', () => { - const mtime = { - secs: 5, - nsecs: 0 - } - const data = new UnixFS({ - type: 'file', - mtime: new Date(5000) - }) - - const marshaled = data.marshal() - const unmarshaled = UnixFS.unmarshal(marshaled) - expect(unmarshaled).to.have.deep.property('mtime', mtime) - }) - - it('mtime as hrtime', () => { - const mtime = { - secs: 5, - nsecs: 0 - } - const data = new UnixFS({ - type: 'file', - mtime: [5, 0] - }) - - const marshaled = data.marshal() - const unmarshaled = UnixFS.unmarshal(marshaled) - expect(unmarshaled).to.have.deep.property('mtime', mtime) - }) - /* - TODO: https://github.com/ipfs/aegir/issues/487 - - it('mtime as bigint', () => { - const mtime = { - secs: 5, - nsecs: 0 - } - const data = new UnixFS({ - type: 'file', - mtime: BigInt(5 * 1e9) - }) - - const marshaled = data.marshal() - const unmarshaled = UnixFS.unmarshal(marshaled) - expect(unmarshaled).to.have.deep.property('mtime', mtime) - }) - */ it('sets mtime to 0', () => { const mtime = { secs: 0, @@ -267,48 +211,11 @@ describe('unixfs-format', () => { expect(unmarshaled).to.have.deep.property('mtime', mtime) }) - it('mtime as date set outside constructor', () => { - const mtime = { - secs: 5, - nsecs: 0 - } - const data = new UnixFS({ - type: 'file' - }) - data.mtime = new Date(5000) - - const marshaled = data.marshal() - const unmarshaled = UnixFS.unmarshal(marshaled) - expect(unmarshaled).to.have.deep.property('mtime', mtime) - }) - - it('ignores invalid mtime', () => { - const data = new UnixFS({ - type: 'file', - mtime: 'what is this' - }) - - const marshaled = data.marshal() - const unmarshaled = UnixFS.unmarshal(marshaled) - expect(unmarshaled).to.not.have.property('mtime') - }) - - it('ignores invalid mtime set outside of constructor', () => { - const entry = new UnixFS({ - type: 'file' - }) - entry.mtime = 'what is this' - - const marshaled = entry.marshal() - const unmarshaled = UnixFS.unmarshal(marshaled) - expect(unmarshaled).to.not.have.property('mtime') - }) - - it('survives null mtime', () => { + it('survives undefined mtime', () => { const entry = new UnixFS({ - type: 'file' + type: 'file', + mtime: undefined }) - entry.mtime = null const marshaled = entry.marshal() const unmarshaled = UnixFS.unmarshal(marshaled) @@ -317,15 +224,15 @@ describe('unixfs-format', () => { it('does not overwrite unknown mode bits', () => { const mode = 0xFFFFFFF // larger than currently defined mode bits - const buf = unixfsData.encode({ + const buf = PBData.encode({ Type: 0, mode - }) + }).finish() const unmarshaled = UnixFS.unmarshal(buf) const marshaled = unmarshaled.marshal() - const entry = unixfsData.decode(marshaled) + const entry = PBData.decode(marshaled) expect(entry).to.have.property('mode', mode) }) @@ -336,9 +243,11 @@ describe('unixfs-format', () => { }) const marshaled = entry.marshal() - - const protobuf = unixfsData.decode(marshaled) - expect(protobuf.hasMode()).to.be.false() + const protobuf = PBData.decode(marshaled) + const object = PBData.toObject(protobuf, { + defaults: false + }) + expect(object).not.to.have.property('mode') }) it('omits default directory mode from protobuf', () => { @@ -348,17 +257,19 @@ describe('unixfs-format', () => { }) const marshaled = entry.marshal() - - const protobuf = unixfsData.decode(marshaled) - expect(protobuf.hasMode()).to.be.false() + const protobuf = PBData.decode(marshaled) + const object = PBData.toObject(protobuf, { + defaults: false + }) + expect(object).not.to.have.property('mode') }) it('respects high bits in mode read from buffer', () => { const mode = 0o0100644 // similar to output from fs.stat - const buf = unixfsData.encode({ - Type: unixfsData.DataType.File, + const buf = PBData.encode({ + Type: PBData.DataType.File, mode - }) + }).finish() const entry = UnixFS.unmarshal(buf) @@ -367,7 +278,7 @@ describe('unixfs-format', () => { const marshaled = entry.marshal() - const protobuf = unixfsData.decode(marshaled) + const protobuf = PBData.decode(marshaled) expect(protobuf).to.have.property('mode', mode) }) @@ -386,8 +297,11 @@ describe('unixfs-format', () => { expect(unmarshaled).to.have.property('mode', 0o644) - const protobuf = unixfsData.decode(marshaled) - expect(protobuf.hasMode()).to.be.false() + const protobuf = PBData.decode(marshaled) + const object = PBData.toObject(protobuf, { + defaults: false + }) + expect(object).not.to.have.property('mode') }) // figuring out what is this metadata for https://github.com/ipfs/js-ipfs-data-importing/issues/3#issuecomment-182336526 @@ -426,16 +340,6 @@ describe('unixfs-format', () => { } }) - it('invalid type with old style constructor', (done) => { - try { - // eslint-disable-next-line no-new - new UnixFS('bananas') - } catch (err) { - expect(err).to.have.property('code', 'ERR_INVALID_TYPE') - done() - } - }) - it('invalid type set outside constructor', (done) => { const entry = new UnixFS() entry.type = 'bananas' diff --git a/packages/ipfs-unixfs/tsconfig.json b/packages/ipfs-unixfs/tsconfig.json new file mode 100644 index 00000000..1f8fd1e4 --- /dev/null +++ b/packages/ipfs-unixfs/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ], + "exclude": [ + "dist", + "node_modules", + "src/unixfs.js" // exclude generated file + ] +}