From 40881ddbd2c86e80f19689f012736fb19f18d945 Mon Sep 17 00:00:00 2001 From: Mateusz Woda Date: Fri, 2 Sep 2022 15:05:01 +0200 Subject: [PATCH] feat: create destination path during download (#393) --- package-lock.json | 247 ++++++++++++------------ package.json | 1 + src/commands/files/download.js | 14 +- src/commands/files/versions/download.js | 10 +- src/commands/files/zip.js | 21 +- src/commands/folders/download.js | 20 +- src/util.js | 23 +++ test/commands/files.test.js | 208 +++++++++++++++++++- test/commands/folders.test.js | 99 ++++++++-- test/helpers/test-helper.js | 5 + test/util.test.js | 32 +++ 11 files changed, 536 insertions(+), 144 deletions(-) diff --git a/package-lock.json b/package-lock.json index 628fd194..8987b0a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1047,7 +1047,7 @@ "ansicolors": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.3.2.tgz", - "integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==" + "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" }, "anymatch": { "version": "3.1.2", @@ -1134,7 +1134,7 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, "array-from": { "version": "2.1.1", @@ -1166,7 +1166,7 @@ "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, "asn1": { @@ -1497,12 +1497,12 @@ "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" }, "buffer-equal-constant-time": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, "buffer-fill": { "version": "1.0.0", @@ -1608,7 +1608,7 @@ "cardinal": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-2.1.1.tgz", - "integrity": "sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==", + "integrity": "sha1-fMEFXYItISlU0HsIXeolHMe8VQU=", "requires": { "ansicolors": "~0.3.2", "redeyed": "~2.1.0" @@ -1633,6 +1633,15 @@ "type-detect": "^4.0.0" } }, + "chai-as-promised": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", + "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "dev": true, + "requires": { + "check-error": "^1.0.2" + } + }, "chalk": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", @@ -1651,7 +1660,7 @@ "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", "dev": true }, "chokidar": { @@ -1737,7 +1746,7 @@ "clean-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", - "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", + "integrity": "sha1-jffHquUf02h06PjQW5GAvBGj/tc=", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" @@ -1751,7 +1760,7 @@ "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", "requires": { "restore-cursor": "^2.0.0" } @@ -1900,12 +1909,12 @@ "clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==" + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, "color-convert": { @@ -1974,7 +1983,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { "version": "2.0.0", @@ -2004,7 +2013,7 @@ "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, "content-disposition": { @@ -2294,7 +2303,7 @@ "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, "core-util-is": { "version": "1.0.2", @@ -2407,13 +2416,13 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "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": "sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", "dev": true, "requires": { "decamelize": "^1.1.0", @@ -2423,7 +2432,7 @@ "map-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true } } @@ -2481,7 +2490,7 @@ "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "requires": { "clone": "^1.0.2" } @@ -2556,7 +2565,7 @@ "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true }, "depd": { @@ -2578,7 +2587,7 @@ "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", - "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true }, "detect-newline": { @@ -2704,7 +2713,7 @@ "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "electron-to-chromium": { "version": "1.4.224", @@ -2720,7 +2729,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "end-of-stream": { "version": "1.4.1", @@ -2778,7 +2787,7 @@ "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" }, "escape-string-regexp": { "version": "1.0.5", @@ -3076,7 +3085,7 @@ "etag": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" }, "execa": { "version": "0.10.0", @@ -3186,7 +3195,7 @@ "extract-stack": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/extract-stack/-/extract-stack-1.0.0.tgz", - "integrity": "sha512-M5Ge0JIrn12EtIVpje2G+hI5X78hmX4UDzynZ7Vnp1MiPSqleEonmgr2Rh59eygEEgq3YJ1GDP96rnM8tnVg/Q==" + "integrity": "sha1-uXrK+UQe6iMyUpYktzL8WhyBZfo=" }, "extsprintf": { "version": "1.3.0", @@ -3250,7 +3259,7 @@ "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", "requires": { "escape-string-regexp": "^1.0.5" } @@ -3492,12 +3501,12 @@ "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, "from2": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", "dev": true, "requires": { "inherits": "^2.0.1", @@ -3528,7 +3537,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fsevents": { "version": "2.3.2", @@ -3578,13 +3587,13 @@ "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, "gauge": { "version": "2.7.4", "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "requires": { "aproba": "^1.0.3", @@ -3600,13 +3609,13 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "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": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { "number-is-nan": "^1.0.0" @@ -3615,7 +3624,7 @@ "string-width": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { "code-point-at": "^1.0.0", @@ -3626,7 +3635,7 @@ "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { "ansi-regex": "^2.0.0" @@ -3649,7 +3658,7 @@ "get-func-name": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, "get-package-type": { @@ -3769,7 +3778,7 @@ "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": "sha512-eU+GGrZgccNJcsDH5LkXR3PB9M958hxc7sbA8DFJjrv9j4L2P/eZfKhM+QD6wyzpiv+b1BpK0XrYCxkovtjSLw==", + "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", "dev": true, "requires": { "gitconfiglocal": "^1.0.0", @@ -3779,7 +3788,7 @@ "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", "dev": true } } @@ -3805,7 +3814,7 @@ "gitconfiglocal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", - "integrity": "sha512-spLUXeTAVHxDtKsJc8FkFVgFtMdEN9qPGpL23VfSHx4fP4+Ds097IXLvymbnDH8FnmxX5Nr9bPw3A+AQ6mWEaQ==", + "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", "dev": true, "requires": { "ini": "^1.3.2" @@ -3814,7 +3823,7 @@ "github-from-package": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", - "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" }, "glob": { "version": "7.1.2", @@ -3983,7 +3992,7 @@ "has-unicode": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true }, "hasha": { @@ -4138,13 +4147,13 @@ "import-modules": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/import-modules/-/import-modules-1.1.0.tgz", - "integrity": "sha512-szMf9iPglnnDYueTxUzJWM+dXlwgfOIIONjVj36ZX8YHG9vBGCHPCpawKr+uIXD0Znm7QQlznIQtVjxfwJkq4g==", + "integrity": "sha1-dI23nFzEK7lwHvq0JPiU5yYA6dw=", "dev": true }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, "indent-string": { @@ -4155,7 +4164,7 @@ "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "requires": { "once": "^1.3.0", "wrappy": "1" @@ -4222,7 +4231,7 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, "is-binary-path": { @@ -4272,7 +4281,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, "is-fullwidth-code-point": { @@ -4333,7 +4342,7 @@ "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==" + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" }, "is-promise": { "version": "2.1.0", @@ -4364,7 +4373,7 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, "is-symbol": { @@ -4376,7 +4385,7 @@ "is-text-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", - "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", "dev": true, "requires": { "text-extensions": "^1.0.0" @@ -4406,12 +4415,12 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isstream": { "version": "0.1.2", @@ -4686,13 +4695,13 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", "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": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json5": { "version": "2.2.1", @@ -4703,7 +4712,7 @@ "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "requires": { "graceful-fs": "^4.1.6" } @@ -4711,7 +4720,7 @@ "jsonparse": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, "jsonwebtoken": { @@ -4780,7 +4789,7 @@ "keychain": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/keychain/-/keychain-1.3.0.tgz", - "integrity": "sha512-VHdsIWwXNO1l+fqwNdYZ/dDGnaN60RLuOIgMnwL+2kE3woPvxpOpeusjfaMZbTFaQFwGnTTzFbVHqQrDqf1FnQ==" + "integrity": "sha1-zLjdxkpi801UGsJeYSGGRCpDJBA=" }, "keytar": { "version": "7.9.0", @@ -4873,7 +4882,7 @@ "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "requires": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -4947,7 +4956,7 @@ "lodash._reinterpolate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==" + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" }, "lodash.assign": { "version": "4.2.0", @@ -4957,23 +4966,23 @@ "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, "lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==" + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" }, "lodash.difference": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==" + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" }, "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==" + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" }, "lodash.flattendeep": { "version": "4.4.0", @@ -4984,59 +4993,59 @@ "lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" }, "lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" }, "lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" }, "lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", - "integrity": "sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==", + "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", "dev": true }, "lodash.isnumber": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" }, "lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" }, "lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" }, "lodash.kebabcase": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", - "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", "dev": true }, "lodash.once": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" }, "lodash.snakecase": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", - "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "integrity": "sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=", "dev": true }, "lodash.template": { @@ -5064,18 +5073,18 @@ "lodash.union": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==" + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" }, "lodash.upperfirst": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", - "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "integrity": "sha1-E2Xt9DFIBIHvDRxolXpe2Z1J984=", "dev": true }, "lodash.zip": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz", - "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==", + "integrity": "sha1-7GZi5IlkCO1KtsVCo5kLcswIACA=", "dev": true }, "log-symbols": { @@ -5172,7 +5181,7 @@ "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" }, "meow": { "version": "8.1.2", @@ -5415,7 +5424,7 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, "merge-options": { "version": "1.0.1", @@ -5434,7 +5443,7 @@ "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" }, "micromatch": { "version": "4.0.5", @@ -5783,7 +5792,7 @@ "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==" + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" }, "nanoid": { "version": "3.3.1", @@ -5798,7 +5807,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, "negotiator": { @@ -5981,7 +5990,7 @@ "npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { "path-key": "^2.0.0" @@ -6002,7 +6011,7 @@ "number-is-nan": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, "nyc": { @@ -6265,7 +6274,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, "object-keys": { @@ -6285,7 +6294,7 @@ "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "requires": { "wrappy": "1" } @@ -6293,7 +6302,7 @@ "onetime": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "requires": { "mimic-fn": "^1.0.0" } @@ -6471,7 +6480,7 @@ "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" }, "p-limit": { "version": "1.3.0", @@ -6563,7 +6572,7 @@ "parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { "error-ex": "^1.3.1", @@ -6598,13 +6607,13 @@ "path-is-inside": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, "path-key": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==" + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" }, "path-parse": { "version": "1.0.7", @@ -7349,7 +7358,7 @@ "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==" + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "process-nextick-args": { "version": "2.0.0", @@ -7433,7 +7442,7 @@ "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, "qqjs": { @@ -7591,7 +7600,7 @@ "read-pkg": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { "load-json-file": "^4.0.0", @@ -7602,7 +7611,7 @@ "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -7616,7 +7625,7 @@ "read-pkg-up": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", - "integrity": "sha512-YFzFrVvpC6frF1sz8psoHDBGF7fLPc+llq/8NB43oagqWkx8ar5zYtsTORtOjw9W2RHLpWP+zTWwBvf1bCmcSw==", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { "find-up": "^2.0.0", @@ -7667,7 +7676,7 @@ "redeyed": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-2.1.1.tgz", - "integrity": "sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==", + "integrity": "sha1-iYS1gV2ZyyIEacme7v/jiRPmzAs=", "requires": { "esprima": "~4.0.0" } @@ -7731,7 +7740,7 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, "require-main-filename": { @@ -7768,7 +7777,7 @@ "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "requires": { "onetime": "^2.0.0", "signal-exit": "^3.0.2" @@ -7915,7 +7924,7 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, "setprototypeof": { @@ -7926,7 +7935,7 @@ "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "requires": { "shebang-regex": "^1.0.0" } @@ -7934,7 +7943,7 @@ "shebang-regex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==" + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" }, "signal-exit": { "version": "3.0.2", @@ -8355,7 +8364,7 @@ "stream-meter": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/stream-meter/-/stream-meter-1.0.4.tgz", - "integrity": "sha512-4sOEtrbgFotXwnEuzzsQBYEV1elAeFSO8rSGeTwabuX1RRn/kEq9JVH7I0MRBhKVRR0sJkr0M0QCH7yOLf9fhQ==", + "integrity": "sha1-Uq+Vql6nYKJJFxZwTb/5D3Ov3R0=", "dev": true, "requires": { "readable-stream": "^2.1.4" @@ -8434,7 +8443,7 @@ "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==" + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "supports-color": { "version": "5.4.0", @@ -8456,7 +8465,7 @@ "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng==" + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" } } }, @@ -8592,7 +8601,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, "through": { @@ -8638,7 +8647,7 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, "to-regex-range": { @@ -8667,7 +8676,7 @@ "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", "dev": true }, "treeify": { @@ -8690,7 +8699,7 @@ "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "requires": { "safe-buffer": "^5.0.1" } @@ -8703,7 +8712,7 @@ "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "requires": { "prelude-ls": "~1.1.2" } @@ -8732,7 +8741,7 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, "typedarray-to-buffer": { @@ -8759,7 +8768,7 @@ "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, "update-browserslist-db": { "version": "1.0.5", @@ -8794,12 +8803,12 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { "version": "3.4.0", @@ -8819,7 +8828,7 @@ "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" }, "verror": { "version": "1.10.0", @@ -8850,7 +8859,7 @@ "wcwidth": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", "requires": { "defaults": "^1.0.3" } @@ -8858,13 +8867,13 @@ "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", "dev": true }, "whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", "dev": true, "requires": { "tr46": "~0.0.3", @@ -8905,7 +8914,7 @@ "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" }, "workerpool": { "version": "6.2.1", @@ -8926,7 +8935,7 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "write": { "version": "0.2.1", diff --git a/package.json b/package.json index 2bdd6052..810bc5a3 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "@oclif/dev-cli": "^1.19.5", "@oclif/test": "^1.1.0", "chai": "^4.1.2", + "chai-as-promised": "^7.1.1", "eslint": "^5.3.0", "eslint-plugin-node": "^7.0.1", "eslint-plugin-promise": "^3.8.0", diff --git a/src/commands/files/download.js b/src/commands/files/download.js index c1f19e2d..0fdcf1e8 100644 --- a/src/commands/files/download.js +++ b/src/commands/files/download.js @@ -15,7 +15,14 @@ class FilesDownloadCommand extends BoxCommand { let file = await this.client.files.get(args.id); let fileName = file.name; - let filePath = path.join(flags.destination || this.settings.boxDownloadsFolderPath, fileName); + let filePath; + + if (flags.destination) { + await utils.checkDir(flags.destination, flags['create-path']); + filePath = path.join(flags.destination, fileName); + } else { + filePath = path.join(this.settings.boxDownloadsFolderPath, fileName); + } /* eslint-disable no-sync */ if (fs.existsSync(filePath)) { @@ -84,6 +91,11 @@ FilesDownloadCommand.flags = { description: 'The destination folder to write the file to', parse: utils.parsePath, }), + 'create-path': flags.boolean({ + description: 'Recursively creates a path to a directory if it does not exist', + allowNo: true, + default: true + }), }; FilesDownloadCommand.args = [ diff --git a/src/commands/files/versions/download.js b/src/commands/files/versions/download.js index 410d6bb7..5e41d431 100644 --- a/src/commands/files/versions/download.js +++ b/src/commands/files/versions/download.js @@ -6,6 +6,7 @@ const BoxCLIError = require('../../../cli-error'); const _ = require('lodash'); const path = require('path'); const fs = require('fs'); +const utils = require('../../../util'); class FilesVersionsDownloadCommand extends BoxCommand { async run() { @@ -15,7 +16,14 @@ class FilesVersionsDownloadCommand extends BoxCommand { let file = await this.client.files.get(args.fileID); let fileName = file.name; - let filePath = path.join(flags.destination || this.settings.boxDownloadsFolderPath, fileName); + let filePath; + + if (flags.destination) { + await utils.checkDir(flags.destination, flags['create-path']); + filePath = path.join(flags.destination, fileName); + } else { + filePath = path.join(this.settings.boxDownloadsFolderPath, fileName); + } /* eslint-disable no-sync */ if (fs.existsSync(filePath)) { diff --git a/src/commands/files/zip.js b/src/commands/files/zip.js index e0230320..da6439ef 100644 --- a/src/commands/files/zip.js +++ b/src/commands/files/zip.js @@ -15,7 +15,14 @@ class FilesZipCommand extends BoxCommand { fileName += '.zip'; } - let filePath = path.join(flags.destination || this.settings.boxDownloadsFolderPath, fileName); + let filePath; + + if (flags.destination) { + await utils.checkDir(flags.destination, flags['create-path']); + filePath = path.join(flags.destination, fileName); + } else { + filePath = path.join(this.settings.boxDownloadsFolderPath, fileName); + } /* eslint-disable no-sync */ if (fs.existsSync(filePath)) { @@ -45,13 +52,19 @@ FilesZipCommand.flags = { parse: utils.parsePath, }), item: flags.string({ - description: 'Files or folders to be part of zip in the form type:ID (i.e. file:1374652)', + description: + 'Files or folders to be part of zip in the form type:ID (i.e. file:1374652)', multiple: true, required: true, parse(val) { let splitVal = val.split(':'); - return {type: splitVal[0], id: splitVal[1]}; - } + return { type: splitVal[0], id: splitVal[1] }; + }, + }), + 'create-path': flags.boolean({ + description: 'Recursively creates a path to a directory if it does not exist', + allowNo: true, + default: true, }), }; diff --git a/src/commands/folders/download.js b/src/commands/folders/download.js index e1810efb..6d773407 100644 --- a/src/commands/folders/download.js +++ b/src/commands/folders/download.js @@ -8,6 +8,7 @@ const BoxCLIError = require('../../cli-error'); const ora = require('ora'); const archiver = require('archiver'); const dateTime = require('date-fns'); +const utils = require('../../util'); /** * Saves a file to disk @@ -43,11 +44,18 @@ class FoldersDownloadCommand extends BoxCommand { this.maxDepth = flags.hasOwnProperty('depth') && flags.depth >= 0 ? flags.depth : Number.POSITIVE_INFINITY; - let destinationPath = flags.destination || this.settings.boxDownloadsFolderPath; let outputPath; let id = args.id; let outputFinalized = Promise.resolve(); + let destinationPath; + if (flags.destination) { + await utils.checkDir(flags.destination, flags['create-path']); + destinationPath = flags.destination; + } else { + destinationPath = this.settings.boxDownloadsFolderPath; + } + /* eslint-disable no-sync */ if (!fs.existsSync(destinationPath) || !fs.statSync(destinationPath).isDirectory()) { throw new BoxCLIError('Destination path must be a directory'); @@ -190,8 +198,14 @@ FoldersDownloadCommand.flags = { description: 'Download the folder into a single .zip archive', }), depth: flags.integer({ - description: 'Number of levels deep to recurse when downloading the folder tree', - }) + description: + 'Number of levels deep to recurse when downloading the folder tree', + }), + 'create-path': flags.boolean({ + description: 'Recursively creates a path to a directory if it does not exist', + allowNo: true, + default: true, + }), }; FoldersDownloadCommand.args = [ diff --git a/src/util.js b/src/util.js index 7bae97f2..f87a702a 100644 --- a/src/util.js +++ b/src/util.js @@ -4,6 +4,7 @@ const _ = require('lodash'); const BoxCLIError = require('./cli-error'); const os = require('os'); const path = require('path'); +const fs = require('fs-extra'); const REQUIRED_CONFIG_VALUES = Object.freeze([ 'boxAppSettings.clientID', @@ -182,6 +183,27 @@ function parseMetadataString(input) { return op; } +/** + * Check if directory exists and creates it if shouldCreate flag was passed. + * + * @param {string} dirPath Directory path to check and create + * @param {boolean} shouldCreate Flag indicating if the directory should be created + * @returns {Promise} empty promise + * @throws BoxCLIError + */ +async function checkDir(dirPath, shouldCreate) { + /* eslint-disable no-sync */ + if (!fs.existsSync(dirPath)) { + if (shouldCreate) { + await fs.mkdirp(dirPath, { recursive: true }); + } else { + throw new BoxCLIError( + `The ${dirPath} path does not exist. Either create it, or pass the --create-path flag set to true` + ); + } + } +} + module.exports = { /** * Validates the a configuration object has all required properties @@ -258,4 +280,5 @@ module.exports = { parseMetadataOp(value) { return parseMetadataString(value); }, + checkDir, }; diff --git a/test/commands/files.test.js b/test/commands/files.test.js index 06010da9..a4c283c2 100644 --- a/test/commands/files.test.js +++ b/test/commands/files.test.js @@ -4,7 +4,7 @@ const { test } = require('@oclif/test'); const assert = require('chai').assert; const fs = require('fs'); const path = require('path'); -const { getFixture, TEST_API_ROOT, TEST_UPLOAD_ROOT, TEST_DOWNLOAD_ROOT, getDownloadProgressBar } = require('../helpers/test-helper'); +const { getFixture, TEST_API_ROOT, TEST_UPLOAD_ROOT, TEST_DOWNLOAD_ROOT, DEFAULT_DOWNLOAD_PATH, getDownloadProgressBar } = require('../helpers/test-helper'); const os = require('os'); const leche = require('leche'); @@ -1869,6 +1869,72 @@ describe('Files', () => { assert.equal(ctx.stderr, expectedMessage); }); + const destination = `${fileDownloadPath}/temp`; + + test + .nock(TEST_API_ROOT, api => api + .get(`/2.0/files/${fileId}`) + .reply(200, getFileFixture) + .get(`/2.0/files/${fileId}/content`) + .reply(302, '', { + Location: TEST_DOWNLOAD_ROOT + fileDownloadPath + }) + ) + .nock(TEST_DOWNLOAD_ROOT, api => api + .get(fileDownloadPath) + .reply(200, function() { return fs.createReadStream(testFilePath, 'utf8'); }) + ) + .stdout() + .stderr() + .command([ + 'files:download', + fileId, + `--destination=${destination}`, + '-y', + '--token=test' + ]) + .it('should download a file to a non-existing destination', () => { + /* eslint-disable no-sync */ + let downloadedFilePath = path.join(destination, fileName); + let downloadContent = fs.readFileSync(downloadedFilePath); + let expectedContent = fs.readFileSync(testFilePath); + fs.unlinkSync(downloadedFilePath); + fs.rmdirSync(destination); + /* eslint-enable no-sync */ + assert.ok(downloadContent.equals(expectedContent)); + }); + + test + .nock(TEST_API_ROOT, api => api + .get(`/2.0/files/${fileId}`) + .reply(200, getFileFixture) + .get(`/2.0/files/${fileId}/content`) + .reply(302, '', { + Location: TEST_DOWNLOAD_ROOT + fileDownloadPath + }) + ) + .nock(TEST_DOWNLOAD_ROOT, api => api + .get(fileDownloadPath) + .reply(200, function() { return fs.createReadStream(testFilePath, 'utf8'); }) + ) + .stdout() + .stderr() + .command([ + 'files:download', + fileId, + '-y', + '--token=test' + ]) + .it('should download a file to a default destination', () => { + /* eslint-disable no-sync */ + let downloadedFilePath = path.join(DEFAULT_DOWNLOAD_PATH, fileName); + let downloadContent = fs.readFileSync(downloadedFilePath); + let expectedContent = fs.readFileSync(testFilePath); + fs.unlinkSync(downloadedFilePath); + /* eslint-enable no-sync */ + assert.ok(downloadContent.equals(expectedContent)); + }); + test .nock(TEST_API_ROOT, api => api .get(`/2.0/files/${fileId}`) @@ -1985,6 +2051,76 @@ describe('Files', () => { assert.ok(downloadContent.equals(expectedContent)); assert.equal(ctx.stderr, 'Downloaded file test_file_download.txt\n'); }); + + const destination = `${fileDownloadPath}/temp`; + + test + .nock(TEST_API_ROOT, api => api + .get(`/2.0/files/${fileId}`) + .reply(200, getFileFixture) + .get(`/2.0/files/${fileId}/content`) + .query({ version: fileVersionID }) + .reply(302, '', { + Location: TEST_DOWNLOAD_ROOT + fileDownloadPath + }) + ) + .nock(TEST_DOWNLOAD_ROOT, api => api + .get(fileDownloadPath) + .reply(200, function() { return fs.createReadStream(testFilePath, 'utf8'); }) + ) + .stdout() + .stderr() + .command([ + 'files:versions:download', + fileId, + '-y', + fileVersionID, + '--token=test' + ]) + .it('should download a file version to a default destination', () => { + /* eslint-disable no-sync */ + let downloadedFilePath = path.join(DEFAULT_DOWNLOAD_PATH, fileName); + let downloadContent = fs.readFileSync(downloadedFilePath); + let expectedContent = fs.readFileSync(testFilePath); + fs.unlinkSync(downloadedFilePath); + /* eslint-enable no-sync */ + assert.ok(downloadContent.equals(expectedContent)); + }); + + test + .nock(TEST_API_ROOT, api => api + .get(`/2.0/files/${fileId}`) + .reply(200, getFileFixture) + .get(`/2.0/files/${fileId}/content`) + .query({ version: fileVersionID }) + .reply(302, '', { + Location: TEST_DOWNLOAD_ROOT + fileDownloadPath + }) + ) + .nock(TEST_DOWNLOAD_ROOT, api => api + .get(fileDownloadPath) + .reply(200, function() { return fs.createReadStream(testFilePath, 'utf8'); }) + ) + .stdout() + .stderr() + .command([ + 'files:versions:download', + fileId, + `--destination=${destination}`, + '-y', + fileVersionID, + '--token=test' + ]) + .it('should download a file version to a non-existing destination', () => { + /* eslint-disable no-sync */ + let downloadedFilePath = path.join(destination, fileName); + let downloadContent = fs.readFileSync(downloadedFilePath); + let expectedContent = fs.readFileSync(testFilePath); + fs.unlinkSync(downloadedFilePath); + fs.rmdirSync(destination); + /* eslint-enable no-sync */ + assert.ok(downloadContent.equals(expectedContent)); + }); }); describe('files:zip', () => { @@ -2044,5 +2180,75 @@ describe('Files', () => { assert.ok(downloadContent.equals(expectedContent)); assert.equal(ctx.stdout, downloadStatusFixture); }); + + const destination = `${fileDownloadPath}/temp`; + + test + .nock(TEST_API_ROOT, api => api + .post('/2.0/zip_downloads', expectedBody) + .reply(202, createFileFixture) + ) + .nock(TEST_DOWNLOAD_ROOT, api => api + .get(downloadUrl) + .reply(200, function() { return fs.createReadStream(testFilePath, 'utf8'); }) + ) + .nock(TEST_API_ROOT, api => api + .get(statusUrl) + .reply(200, downloadStatusFixture) + ) + .stdout() + .command([ + 'files:zip', + fileName, + `--item=${items[0].type}:${items[0].id}`, + `--item=${items[1].type}:${items[1].id}`, + `--destination=${destination}`, + '--json', + '--token=test' + ]) + .it('should create a zip in a non-existent path', ctx => { + /* eslint-disable no-sync */ + let downloadedFilePath = path.join(destination, fileName); + let downloadContent = fs.readFileSync(downloadedFilePath); + let expectedContent = fs.readFileSync(testFilePath); + fs.unlinkSync(downloadedFilePath); + fs.rmdirSync(destination); + /* eslint-enable no-sync */ + assert.ok(downloadContent.equals(expectedContent)); + assert.equal(ctx.stdout, downloadStatusFixture); + }); + + test + .nock(TEST_API_ROOT, api => api + .post('/2.0/zip_downloads', expectedBody) + .reply(202, createFileFixture) + ) + .nock(TEST_DOWNLOAD_ROOT, api => api + .get(downloadUrl) + .reply(200, function() { return fs.createReadStream(testFilePath, 'utf8'); }) + ) + .nock(TEST_API_ROOT, api => api + .get(statusUrl) + .reply(200, downloadStatusFixture) + ) + .stdout() + .command([ + 'files:zip', + fileName, + `--item=${items[0].type}:${items[0].id}`, + `--item=${items[1].type}:${items[1].id}`, + '--json', + '--token=test' + ]) + .it('should create a zip in a default destination', ctx => { + /* eslint-disable no-sync */ + let downloadedFilePath = path.join(DEFAULT_DOWNLOAD_PATH, fileName); + let downloadContent = fs.readFileSync(downloadedFilePath); + let expectedContent = fs.readFileSync(testFilePath); + fs.unlinkSync(downloadedFilePath); + /* eslint-enable no-sync */ + assert.ok(downloadContent.equals(expectedContent)); + assert.equal(ctx.stdout, downloadStatusFixture); + }); }); }); diff --git a/test/commands/folders.test.js b/test/commands/folders.test.js index 5416fa40..d68bcbcb 100644 --- a/test/commands/folders.test.js +++ b/test/commands/folders.test.js @@ -4,7 +4,7 @@ const { test } = require('@oclif/test'); const assert = require('chai').assert; const fs = require('fs-extra'); const path = require('path'); -const { getFixture, TEST_API_ROOT, TEST_UPLOAD_ROOT, TEST_DOWNLOAD_ROOT } = require('../helpers/test-helper'); +const { getFixture, TEST_API_ROOT, TEST_UPLOAD_ROOT, TEST_DOWNLOAD_ROOT, DEFAULT_DOWNLOAD_PATH } = require('../helpers/test-helper'); const os = require('os'); const leche = require('leche'); const _ = require('lodash'); @@ -1510,9 +1510,6 @@ describe('Folders', () => { ) .stdout() .stderr() - .do(async() => { - await fs.mkdirp(downloadPath); - }) .command([ 'folders:download', folderID, @@ -1563,9 +1560,6 @@ describe('Folders', () => { }) .stdout() .stderr() - .do(async() => { - await fs.mkdirp(downloadPath); - }) .command([ 'folders:download', folderID, @@ -1602,9 +1596,6 @@ describe('Folders', () => { ) .stdout() .stderr() - .do(async() => { - await fs.mkdirp(downloadPath); - }) .command([ 'folders:download', folderID, @@ -1644,9 +1635,6 @@ describe('Folders', () => { ) .stdout() .stderr() - .do(async() => { - await fs.mkdirp(downloadPath); - }) .command([ 'folders:download', folderID, @@ -1674,10 +1662,91 @@ describe('Folders', () => { folderID, '--destination=/path/really/should/not/exist', '--no-color', - '--token=test' + '--token=test', + '--no-create-path' ]) .it('should output error when destination directory does not exist', ctx => { - assert.equal(ctx.stderr, `Destination path must be a directory${os.EOL}`); + assert.equal( + ctx.stderr, + `The /path/really/should/not/exist path does not exist. Either create it, or pass the --create-path flag set to true${os.EOL}` + ); + }); + + const destination = `${downloadPath}/temp`; + + test + .nock(TEST_API_ROOT, api => api + .get(`/2.0/folders/${folderID}`) + .reply(200, getFolderFixture) + .get('/2.0/folders/22222') + .reply(200, getSubfolderFixture) + .get('/2.0/files/77777/content') + .reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/77777` }) + .get('/2.0/files/44444/content') + .reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/44444` }) + .get('/2.0/files/55555/content') + .reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/55555` }) + ) + .nock(TEST_DOWNLOAD_ROOT, api => api + .get('/44444') + .reply(200, expectedContents['file 1.txt']) + .get('/55555') + .reply(200, expectedContents['file 2.txt']) + .get('/77777') + .reply(200, expectedContents.subfolder['subfolder file 1.txt']) + ) + .stdout() + .stderr() + .command([ + 'folders:download', + folderID, + `--destination=${destination}`, + '--token=test', + ]) + .it('should download a folder a non-existent path', async(ctx) => { + let folderPath = path.join(destination, folderName); + let actualContents = await getDirectoryContents(folderPath); + await fs.remove(destination); + + assert.deepEqual(actualContents, expectedContents); + assert.equal(ctx.stdout, ''); + }); + + test + .nock(TEST_API_ROOT, api => api + .get(`/2.0/folders/${folderID}`) + .reply(200, getFolderFixture) + .get('/2.0/folders/22222') + .reply(200, getSubfolderFixture) + .get('/2.0/files/77777/content') + .reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/77777` }) + .get('/2.0/files/44444/content') + .reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/44444` }) + .get('/2.0/files/55555/content') + .reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/55555` }) + ) + .nock(TEST_DOWNLOAD_ROOT, api => api + .get('/44444') + .reply(200, expectedContents['file 1.txt']) + .get('/55555') + .reply(200, expectedContents['file 2.txt']) + .get('/77777') + .reply(200, expectedContents.subfolder['subfolder file 1.txt']) + ) + .stdout() + .stderr() + .command([ + 'folders:download', + folderID, + '--token=test', + ]) + .it('should download a folder to a default destination', async(ctx) => { + let folderPath = path.join(DEFAULT_DOWNLOAD_PATH, folderName); + let actualContents = await getDirectoryContents(folderPath); + await fs.remove(folderPath); + + assert.deepEqual(actualContents, expectedContents); + assert.equal(ctx.stdout, ''); }); }); diff --git a/test/helpers/test-helper.js b/test/helpers/test-helper.js index 3ec4c72d..44691089 100644 --- a/test/helpers/test-helper.js +++ b/test/helpers/test-helper.js @@ -7,6 +7,10 @@ const os = require('os'); const TEST_API_ROOT = 'https://api.box.com'; const TEST_UPLOAD_ROOT = 'https://upload.box.com/api'; const TEST_DOWNLOAD_ROOT = 'https://dl.boxcloud.com'; +const DEFAULT_DOWNLOAD_PATH = path.join( + os.homedir(), + 'Downloads/Box-Downloads' +) function getFixture(fixture) { if (!path.extname(fixture)) { @@ -40,6 +44,7 @@ module.exports = { TEST_API_ROOT, TEST_UPLOAD_ROOT, TEST_DOWNLOAD_ROOT, + DEFAULT_DOWNLOAD_PATH, getFixture, getBulkProgressBar, getDownloadProgressBar, diff --git a/test/util.test.js b/test/util.test.js index 1c5722bc..d934f425 100644 --- a/test/util.test.js +++ b/test/util.test.js @@ -1,10 +1,15 @@ 'use strict'; +const chai = require('chai'); const assert = require('chai').assert; const mockery = require('mockery'); const leche = require('leche'); const sinon = require('sinon'); const process = require('process'); +const fs = require('fs'); +const chaiAsPromised = require('chai-as-promised'); + +chai.use(chaiAsPromised); describe('Utilities', () => { @@ -596,4 +601,31 @@ describe('Utilities', () => { }); }); }); + + /* eslint-disable no-sync */ + describe('checkDir()', () => { + it('should create directory if create flag is true', async() => { + const destination = `${process.cwd()}/temp`; + await cliUtils.checkDir(destination, true); + assert.isTrue(fs.existsSync(destination)); + fs.rmdirSync(destination); + }); + + it('should create nested directory if create flag is true', async() => { + const destination = `${process.cwd()}/nestedTemp`; + const nestedDestination = `${destination}/temp`; + await cliUtils.checkDir(nestedDestination, true); + assert.isTrue(fs.existsSync(nestedDestination)); + fs.rmdirSync(nestedDestination); + fs.rmdirSync(destination); + }); + + it('should throw expection if directory does not exist and create flag is false', () => { + const destination = `${process.cwd()}/nonExistingPath`; + const retrieveException = async() => { + await cliUtils.checkDir(destination, false); + }; + return assert.isRejected(retrieveException(), Error); + }); + }); });