├── .github └── workflows │ └── test.yaml ├── .gitignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── src └── index.js └── test ├── integration ├── chunk-test.js └── upload-test.js ├── oci-integration ├── chunk-test.js └── upload-test.js └── uploader-test.js /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | name: s3-streaming-upload CI 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | test: 7 | runs-on: ubuntu-latest 8 | 9 | strategy: 10 | matrix: 11 | node-version: [12.x, 14.x] 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Use Node.js ${{ matrix.node-version }} 16 | uses: actions/setup-node@v1 17 | with: 18 | node-version: ${{ matrix.node-version }} 19 | - run: npm install 20 | - run: npm test 21 | - name: Integration tests 22 | env: 23 | AWS_S3_ACCESS_KEY: ${{ secrets.AWS_S3_ACCESS_KEY }} 24 | AWS_S3_SECRET_KEY: ${{ secrets.AWS_S3_SECRET_KEY }} 25 | AWS_S3_TEST_BUCKET: ${{ secrets.AWS_S3_TEST_BUCKET }} 26 | OCI_TENANCY: ${{ secrets.OCI_TENANCY }} 27 | OCI_REGION: ${{ secrets.OCI_REGION }} 28 | run: npm run test:integration:oci 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | lib-cov 3 | coverage 4 | *.seed 5 | *.log 6 | *.csv 7 | *.dat 8 | *.out 9 | *.pid 10 | *.gz 11 | 12 | pids 13 | logs 14 | results 15 | 16 | npm-debug.log 17 | 18 | /.idea 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2013 Apiary Inc. . 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## s3-streaming-upload [![s3-streaming-upload](https://github.com/apiaryio/s3-streaming-upload/workflows/s3-streaming-upload%20CI/badge.svg)](https://github.com/apiaryio/s3-streaming-upload/actions?query=workflow%3A%22s3-streaming-upload+CI%22) 2 | 3 | [s3-streaming-upload](https://github.com/apiaryio/s3-streaming-upload) is [node.js](http://nodejs.org) library that listens to your [stream](http://nodejs.org/docs/v0.8.9/api/stream.html) and upload its data to Amazon S3 and OCI Bucket Store. 4 | 5 | It is heavily inspired by [knox-mpu](https://github.com/nathanoehlman/knox-mpu), but unlike it, it does not buffer data to disk and is build on top of [official AWS SDK](https://github.com/aws/aws-sdk-js) instead of knox. 6 | 7 | ### Changes 8 | 9 | - Version 0.3.2 NodeJS 12+ supported. 10 | - Version 0.3.x Change from Coffee-script to Javascript. NodeJS 6 and 8 supported. 11 | 12 | - Version 0.2.x using [ManagedUpload API](http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3/ManagedUpload.html). NodeJS 0.10 and 0.12 supported. 13 | 14 | - Version 0.1.x using [MultiPartUpload API](http://docs.amazonwebservices.com/AmazonS3/latest/dev/sdksupportformpu.html). NodeJS 0.8 and 0.10 supported. 15 | 16 | ### Installation 17 | 18 | Installation is done via NPM, by running `npm install s3-streaming-upload` 19 | 20 | ### Features 21 | 22 | - Super easy to use 23 | - No need to know data size beforehand 24 | - Stream is buffered up to specified size (default 5MBs) and then uploaded to S3 25 | - Segments are not written to disk and memory is freed as soon as possible after upload 26 | - Uploading is asynchronous 27 | - You can react to upload status through events 28 | 29 | ### Quick example 30 | 31 | ```javascript 32 | var Uploader = require('s3-streaming-upload').Uploader, 33 | upload = null, 34 | stream = require('fs').createReadStream('/etc/resolv.conf'); 35 | 36 | upload = new Uploader({ 37 | // credentials to access AWS 38 | accessKey: process.env.AWS_S3_ACCESS_KEY, 39 | secretKey: process.env.AWS_S3_SECRET_KEY, 40 | bucket: process.env.AWS_S3_TEST_BUCKET, 41 | objectName: 'myUploadedFile', 42 | stream: stream, 43 | debug: true, 44 | }); 45 | 46 | upload.send(function(err) { 47 | if (err) { 48 | console.error('Upload error' + err); 49 | } 50 | }); 51 | ``` 52 | 53 | ### Setting up ACL 54 | 55 | Pass it in `objectParams` to the `Uploader`: 56 | 57 | ```javascript 58 | upload = new Uploader({ 59 | // credentials to access AWS 60 | accessKey: process.env.AWS_API_KEY, 61 | secretKey: process.env.AWS_SECRET, 62 | bucket: process.env.AWS_S3_TRAFFIC_BACKUP_BUCKET, 63 | objectName: 'myUploadedFile', 64 | stream: stream, 65 | objectParams: { 66 | ACL: 'public-read', 67 | }, 68 | }); 69 | ``` 70 | 71 | ### Example usage with Oracle Cloud (OCI) compatible S3 API 72 | 73 | ```javascript 74 | region = process.env.OCI_REGION; 75 | tenancy = process.env.OCI_TENANCY; 76 | // define custom service 77 | service = new aws.S3({ 78 | apiVersion: '2006-03-01', 79 | credentials: { 80 | accessKeyId: process.env.BUCKET_ACCESS_KEY, 81 | secretAccessKey: process.env.BUCKET_SECRET_KEY, 82 | }, 83 | params: { Bucket: process.env.BUCKET_NAME }, 84 | endpoint: `${tenancy}.compat.objectstorage.${region}.oraclecloud.com`, 85 | region: region, 86 | signatureVersion: 'v4', 87 | s3ForcePathStyle: true, 88 | }); 89 | 90 | uploader = new Uploader({ 91 | accessKey: process.env.BUCKET_ACCESS_KEY, 92 | secretKey: process.env.BUCKET_SECRET_KEY, 93 | bucket: process.env.BUCKET_NAME, 94 | objectName: filename, 95 | stream: source, 96 | service: service, 97 | objectParams: { 98 | ContentType: 'text/csv', 99 | }, 100 | debug: true, 101 | }); 102 | ``` 103 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "s3-streaming-upload", 3 | "version": "0.3.4", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@sinonjs/commons": { 8 | "version": "1.4.0", 9 | "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.4.0.tgz", 10 | "integrity": "sha512-9jHK3YF/8HtJ9wCAbG+j8cD0i0+ATS9A7gXFqS36TblLPNy6rEEc+SB0imo91eCboGaBYGV/MT1/br/J+EE7Tw==", 11 | "dev": true, 12 | "requires": { 13 | "type-detect": "4.0.8" 14 | } 15 | }, 16 | "@sinonjs/formatio": { 17 | "version": "3.2.1", 18 | "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.1.tgz", 19 | "integrity": "sha512-tsHvOB24rvyvV2+zKMmPkZ7dXX6LSLKZ7aOtXY6Edklp0uRcgGpOsQTTGTcWViFyx4uhWc6GV8QdnALbIbIdeQ==", 20 | "dev": true, 21 | "requires": { 22 | "@sinonjs/commons": "^1", 23 | "@sinonjs/samsam": "^3.1.0" 24 | } 25 | }, 26 | "@sinonjs/samsam": { 27 | "version": "3.3.1", 28 | "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.1.tgz", 29 | "integrity": "sha512-wRSfmyd81swH0hA1bxJZJ57xr22kC07a1N4zuIL47yTS04bDk6AoCkczcqHEjcRPmJ+FruGJ9WBQiJwMtIElFw==", 30 | "dev": true, 31 | "requires": { 32 | "@sinonjs/commons": "^1.0.2", 33 | "array-from": "^2.1.1", 34 | "lodash": "^4.17.11" 35 | } 36 | }, 37 | "@sinonjs/text-encoding": { 38 | "version": "0.7.1", 39 | "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", 40 | "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", 41 | "dev": true 42 | }, 43 | "@ungap/promise-all-settled": { 44 | "version": "1.1.2", 45 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", 46 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", 47 | "dev": true 48 | }, 49 | "ansi-colors": { 50 | "version": "4.1.1", 51 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 52 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 53 | "dev": true 54 | }, 55 | "ansi-regex": { 56 | "version": "3.0.0", 57 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 58 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 59 | "dev": true 60 | }, 61 | "ansi-styles": { 62 | "version": "4.3.0", 63 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 64 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 65 | "dev": true, 66 | "requires": { 67 | "color-convert": "^2.0.1" 68 | } 69 | }, 70 | "anymatch": { 71 | "version": "3.1.1", 72 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 73 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 74 | "dev": true, 75 | "requires": { 76 | "normalize-path": "^3.0.0", 77 | "picomatch": "^2.0.4" 78 | } 79 | }, 80 | "argparse": { 81 | "version": "1.0.10", 82 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 83 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 84 | "dev": true, 85 | "requires": { 86 | "sprintf-js": "~1.0.2" 87 | } 88 | }, 89 | "array-from": { 90 | "version": "2.1.1", 91 | "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", 92 | "integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU=", 93 | "dev": true 94 | }, 95 | "assertion-error": { 96 | "version": "1.1.0", 97 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 98 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 99 | "dev": true 100 | }, 101 | "async": { 102 | "version": "2.6.2", 103 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.2.tgz", 104 | "integrity": "sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg==", 105 | "dev": true, 106 | "requires": { 107 | "lodash": "^4.17.11" 108 | } 109 | }, 110 | "aws-sdk": { 111 | "version": "2.814.0", 112 | "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.814.0.tgz", 113 | "integrity": "sha512-empd1m/J/MAkL6d9OeRpmg9thobULu0wk4v8W3JToaxGi2TD7PIdvE6yliZKyOVAdJINhBWEBhxR4OUIHhcGbQ==", 114 | "requires": { 115 | "buffer": "4.9.2", 116 | "events": "1.1.1", 117 | "ieee754": "1.1.13", 118 | "jmespath": "0.15.0", 119 | "querystring": "0.2.0", 120 | "sax": "1.2.1", 121 | "url": "0.10.3", 122 | "uuid": "3.3.2", 123 | "xml2js": "0.4.19" 124 | } 125 | }, 126 | "balanced-match": { 127 | "version": "1.0.0", 128 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 129 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 130 | "dev": true 131 | }, 132 | "base64-js": { 133 | "version": "1.5.1", 134 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 135 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 136 | }, 137 | "binary-extensions": { 138 | "version": "2.1.0", 139 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", 140 | "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", 141 | "dev": true 142 | }, 143 | "brace-expansion": { 144 | "version": "1.1.11", 145 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 146 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 147 | "dev": true, 148 | "requires": { 149 | "balanced-match": "^1.0.0", 150 | "concat-map": "0.0.1" 151 | } 152 | }, 153 | "braces": { 154 | "version": "3.0.2", 155 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 156 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 157 | "dev": true, 158 | "requires": { 159 | "fill-range": "^7.0.1" 160 | } 161 | }, 162 | "browser-stdout": { 163 | "version": "1.3.1", 164 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 165 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 166 | "dev": true 167 | }, 168 | "buffer": { 169 | "version": "4.9.2", 170 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", 171 | "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", 172 | "requires": { 173 | "base64-js": "^1.0.2", 174 | "ieee754": "^1.1.4", 175 | "isarray": "^1.0.0" 176 | } 177 | }, 178 | "camelcase": { 179 | "version": "5.3.1", 180 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 181 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 182 | "dev": true 183 | }, 184 | "chai": { 185 | "version": "4.2.0", 186 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", 187 | "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", 188 | "dev": true, 189 | "requires": { 190 | "assertion-error": "^1.1.0", 191 | "check-error": "^1.0.2", 192 | "deep-eql": "^3.0.1", 193 | "get-func-name": "^2.0.0", 194 | "pathval": "^1.1.0", 195 | "type-detect": "^4.0.5" 196 | } 197 | }, 198 | "chalk": { 199 | "version": "4.1.0", 200 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 201 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 202 | "dev": true, 203 | "requires": { 204 | "ansi-styles": "^4.1.0", 205 | "supports-color": "^7.1.0" 206 | } 207 | }, 208 | "check-error": { 209 | "version": "1.0.2", 210 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 211 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 212 | "dev": true 213 | }, 214 | "chokidar": { 215 | "version": "3.4.3", 216 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", 217 | "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", 218 | "dev": true, 219 | "requires": { 220 | "anymatch": "~3.1.1", 221 | "braces": "~3.0.2", 222 | "fsevents": "~2.1.2", 223 | "glob-parent": "~5.1.0", 224 | "is-binary-path": "~2.1.0", 225 | "is-glob": "~4.0.1", 226 | "normalize-path": "~3.0.0", 227 | "readdirp": "~3.5.0" 228 | } 229 | }, 230 | "cliui": { 231 | "version": "4.1.0", 232 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", 233 | "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", 234 | "dev": true, 235 | "requires": { 236 | "string-width": "^2.1.1", 237 | "strip-ansi": "^4.0.0", 238 | "wrap-ansi": "^2.0.0" 239 | } 240 | }, 241 | "code-point-at": { 242 | "version": "1.1.0", 243 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 244 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", 245 | "dev": true 246 | }, 247 | "color-convert": { 248 | "version": "2.0.1", 249 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 250 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 251 | "dev": true, 252 | "requires": { 253 | "color-name": "~1.1.4" 254 | } 255 | }, 256 | "color-name": { 257 | "version": "1.1.4", 258 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 259 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 260 | "dev": true 261 | }, 262 | "concat-map": { 263 | "version": "0.0.1", 264 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 265 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 266 | "dev": true 267 | }, 268 | "cross-spawn": { 269 | "version": "6.0.5", 270 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", 271 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", 272 | "dev": true, 273 | "requires": { 274 | "nice-try": "^1.0.4", 275 | "path-key": "^2.0.1", 276 | "semver": "^5.5.0", 277 | "shebang-command": "^1.2.0", 278 | "which": "^1.2.9" 279 | } 280 | }, 281 | "debug": { 282 | "version": "4.2.0", 283 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", 284 | "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", 285 | "dev": true, 286 | "requires": { 287 | "ms": "2.1.2" 288 | } 289 | }, 290 | "decamelize": { 291 | "version": "1.2.0", 292 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 293 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 294 | "dev": true 295 | }, 296 | "deep-eql": { 297 | "version": "3.0.1", 298 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 299 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 300 | "dev": true, 301 | "requires": { 302 | "type-detect": "^4.0.0" 303 | } 304 | }, 305 | "diff": { 306 | "version": "3.5.0", 307 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 308 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 309 | "dev": true 310 | }, 311 | "emoji-regex": { 312 | "version": "7.0.3", 313 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 314 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 315 | "dev": true 316 | }, 317 | "end-of-stream": { 318 | "version": "1.4.1", 319 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", 320 | "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", 321 | "dev": true, 322 | "requires": { 323 | "once": "^1.4.0" 324 | } 325 | }, 326 | "escape-string-regexp": { 327 | "version": "4.0.0", 328 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 329 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 330 | "dev": true 331 | }, 332 | "esprima": { 333 | "version": "4.0.1", 334 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 335 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 336 | "dev": true 337 | }, 338 | "events": { 339 | "version": "1.1.1", 340 | "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", 341 | "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" 342 | }, 343 | "execa": { 344 | "version": "1.0.0", 345 | "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", 346 | "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", 347 | "dev": true, 348 | "requires": { 349 | "cross-spawn": "^6.0.0", 350 | "get-stream": "^4.0.0", 351 | "is-stream": "^1.1.0", 352 | "npm-run-path": "^2.0.0", 353 | "p-finally": "^1.0.0", 354 | "signal-exit": "^3.0.0", 355 | "strip-eof": "^1.0.0" 356 | } 357 | }, 358 | "eyes": { 359 | "version": "0.1.8", 360 | "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", 361 | "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", 362 | "dev": true 363 | }, 364 | "fill-range": { 365 | "version": "7.0.1", 366 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 367 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 368 | "dev": true, 369 | "requires": { 370 | "to-regex-range": "^5.0.1" 371 | } 372 | }, 373 | "find-up": { 374 | "version": "3.0.0", 375 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 376 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 377 | "dev": true, 378 | "requires": { 379 | "locate-path": "^3.0.0" 380 | } 381 | }, 382 | "flat": { 383 | "version": "5.0.2", 384 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 385 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 386 | "dev": true 387 | }, 388 | "fs.realpath": { 389 | "version": "1.0.0", 390 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 391 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 392 | "dev": true 393 | }, 394 | "fsevents": { 395 | "version": "2.1.3", 396 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 397 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 398 | "dev": true, 399 | "optional": true 400 | }, 401 | "get-caller-file": { 402 | "version": "2.0.5", 403 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 404 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 405 | "dev": true 406 | }, 407 | "get-func-name": { 408 | "version": "2.0.0", 409 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 410 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 411 | "dev": true 412 | }, 413 | "get-stream": { 414 | "version": "4.1.0", 415 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 416 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 417 | "dev": true, 418 | "requires": { 419 | "pump": "^3.0.0" 420 | } 421 | }, 422 | "glob": { 423 | "version": "7.1.6", 424 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 425 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 426 | "dev": true, 427 | "requires": { 428 | "fs.realpath": "^1.0.0", 429 | "inflight": "^1.0.4", 430 | "inherits": "2", 431 | "minimatch": "^3.0.4", 432 | "once": "^1.3.0", 433 | "path-is-absolute": "^1.0.0" 434 | } 435 | }, 436 | "glob-parent": { 437 | "version": "5.1.2", 438 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 439 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 440 | "dev": true, 441 | "requires": { 442 | "is-glob": "^4.0.1" 443 | } 444 | }, 445 | "growl": { 446 | "version": "1.10.5", 447 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 448 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 449 | "dev": true 450 | }, 451 | "has-flag": { 452 | "version": "3.0.0", 453 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 454 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 455 | "dev": true 456 | }, 457 | "he": { 458 | "version": "1.2.0", 459 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 460 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 461 | "dev": true 462 | }, 463 | "ieee754": { 464 | "version": "1.1.13", 465 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", 466 | "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" 467 | }, 468 | "inflight": { 469 | "version": "1.0.6", 470 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 471 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 472 | "dev": true, 473 | "requires": { 474 | "once": "^1.3.0", 475 | "wrappy": "1" 476 | } 477 | }, 478 | "inherits": { 479 | "version": "2.0.3", 480 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 481 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 482 | }, 483 | "invert-kv": { 484 | "version": "2.0.0", 485 | "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", 486 | "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", 487 | "dev": true 488 | }, 489 | "is-binary-path": { 490 | "version": "2.1.0", 491 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 492 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 493 | "dev": true, 494 | "requires": { 495 | "binary-extensions": "^2.0.0" 496 | } 497 | }, 498 | "is-extglob": { 499 | "version": "2.1.1", 500 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 501 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 502 | "dev": true 503 | }, 504 | "is-fullwidth-code-point": { 505 | "version": "2.0.0", 506 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 507 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 508 | "dev": true 509 | }, 510 | "is-glob": { 511 | "version": "4.0.1", 512 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 513 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 514 | "dev": true, 515 | "requires": { 516 | "is-extglob": "^2.1.1" 517 | } 518 | }, 519 | "is-number": { 520 | "version": "7.0.0", 521 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 522 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 523 | "dev": true 524 | }, 525 | "is-plain-obj": { 526 | "version": "2.1.0", 527 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 528 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 529 | "dev": true 530 | }, 531 | "is-stream": { 532 | "version": "1.1.0", 533 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 534 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", 535 | "dev": true 536 | }, 537 | "isarray": { 538 | "version": "1.0.0", 539 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 540 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 541 | }, 542 | "isexe": { 543 | "version": "2.0.0", 544 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 545 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 546 | "dev": true 547 | }, 548 | "jmespath": { 549 | "version": "0.15.0", 550 | "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", 551 | "integrity": "sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=" 552 | }, 553 | "js-yaml": { 554 | "version": "3.14.0", 555 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", 556 | "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", 557 | "dev": true, 558 | "requires": { 559 | "argparse": "^1.0.7", 560 | "esprima": "^4.0.0" 561 | } 562 | }, 563 | "just-extend": { 564 | "version": "4.0.2", 565 | "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", 566 | "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", 567 | "dev": true 568 | }, 569 | "lcid": { 570 | "version": "2.0.0", 571 | "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", 572 | "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", 573 | "dev": true, 574 | "requires": { 575 | "invert-kv": "^2.0.0" 576 | } 577 | }, 578 | "locate-path": { 579 | "version": "3.0.0", 580 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 581 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 582 | "dev": true, 583 | "requires": { 584 | "p-locate": "^3.0.0", 585 | "path-exists": "^3.0.0" 586 | } 587 | }, 588 | "lodash": { 589 | "version": "4.17.21", 590 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 591 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 592 | "dev": true 593 | }, 594 | "log-symbols": { 595 | "version": "4.0.0", 596 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", 597 | "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", 598 | "dev": true, 599 | "requires": { 600 | "chalk": "^4.0.0" 601 | } 602 | }, 603 | "lolex": { 604 | "version": "4.0.1", 605 | "resolved": "https://registry.npmjs.org/lolex/-/lolex-4.0.1.tgz", 606 | "integrity": "sha512-UHuOBZ5jjsKuzbB/gRNNW8Vg8f00Emgskdq2kvZxgBJCS0aqquAuXai/SkWORlKeZEiNQWZjFZOqIUcH9LqKCw==", 607 | "dev": true 608 | }, 609 | "map-age-cleaner": { 610 | "version": "0.1.3", 611 | "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", 612 | "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", 613 | "dev": true, 614 | "requires": { 615 | "p-defer": "^1.0.0" 616 | } 617 | }, 618 | "mem": { 619 | "version": "4.3.0", 620 | "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", 621 | "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", 622 | "dev": true, 623 | "requires": { 624 | "map-age-cleaner": "^0.1.1", 625 | "mimic-fn": "^2.0.0", 626 | "p-is-promise": "^2.0.0" 627 | } 628 | }, 629 | "mimic-fn": { 630 | "version": "2.1.0", 631 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 632 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 633 | "dev": true 634 | }, 635 | "minimatch": { 636 | "version": "3.0.4", 637 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 638 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 639 | "dev": true, 640 | "requires": { 641 | "brace-expansion": "^1.1.7" 642 | } 643 | }, 644 | "mocha": { 645 | "version": "8.2.1", 646 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", 647 | "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", 648 | "dev": true, 649 | "requires": { 650 | "@ungap/promise-all-settled": "1.1.2", 651 | "ansi-colors": "4.1.1", 652 | "browser-stdout": "1.3.1", 653 | "chokidar": "3.4.3", 654 | "debug": "4.2.0", 655 | "diff": "4.0.2", 656 | "escape-string-regexp": "4.0.0", 657 | "find-up": "5.0.0", 658 | "glob": "7.1.6", 659 | "growl": "1.10.5", 660 | "he": "1.2.0", 661 | "js-yaml": "3.14.0", 662 | "log-symbols": "4.0.0", 663 | "minimatch": "3.0.4", 664 | "ms": "2.1.2", 665 | "nanoid": "3.1.12", 666 | "serialize-javascript": "5.0.1", 667 | "strip-json-comments": "3.1.1", 668 | "supports-color": "7.2.0", 669 | "which": "2.0.2", 670 | "wide-align": "1.1.3", 671 | "workerpool": "6.0.2", 672 | "yargs": "13.3.2", 673 | "yargs-parser": "13.1.2", 674 | "yargs-unparser": "2.0.0" 675 | }, 676 | "dependencies": { 677 | "ansi-regex": { 678 | "version": "4.1.0", 679 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 680 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 681 | "dev": true 682 | }, 683 | "ansi-styles": { 684 | "version": "3.2.1", 685 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 686 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 687 | "dev": true, 688 | "requires": { 689 | "color-convert": "^1.9.0" 690 | } 691 | }, 692 | "cliui": { 693 | "version": "5.0.0", 694 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", 695 | "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", 696 | "dev": true, 697 | "requires": { 698 | "string-width": "^3.1.0", 699 | "strip-ansi": "^5.2.0", 700 | "wrap-ansi": "^5.1.0" 701 | } 702 | }, 703 | "color-convert": { 704 | "version": "1.9.3", 705 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 706 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 707 | "dev": true, 708 | "requires": { 709 | "color-name": "1.1.3" 710 | } 711 | }, 712 | "color-name": { 713 | "version": "1.1.3", 714 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 715 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 716 | "dev": true 717 | }, 718 | "diff": { 719 | "version": "4.0.2", 720 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 721 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 722 | "dev": true 723 | }, 724 | "find-up": { 725 | "version": "5.0.0", 726 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 727 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 728 | "dev": true, 729 | "requires": { 730 | "locate-path": "^6.0.0", 731 | "path-exists": "^4.0.0" 732 | } 733 | }, 734 | "locate-path": { 735 | "version": "6.0.0", 736 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 737 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 738 | "dev": true, 739 | "requires": { 740 | "p-locate": "^5.0.0" 741 | } 742 | }, 743 | "p-limit": { 744 | "version": "3.0.2", 745 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", 746 | "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", 747 | "dev": true, 748 | "requires": { 749 | "p-try": "^2.0.0" 750 | } 751 | }, 752 | "p-locate": { 753 | "version": "5.0.0", 754 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 755 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 756 | "dev": true, 757 | "requires": { 758 | "p-limit": "^3.0.2" 759 | } 760 | }, 761 | "path-exists": { 762 | "version": "4.0.0", 763 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 764 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 765 | "dev": true 766 | }, 767 | "string-width": { 768 | "version": "3.1.0", 769 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 770 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 771 | "dev": true, 772 | "requires": { 773 | "emoji-regex": "^7.0.1", 774 | "is-fullwidth-code-point": "^2.0.0", 775 | "strip-ansi": "^5.1.0" 776 | } 777 | }, 778 | "strip-ansi": { 779 | "version": "5.2.0", 780 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 781 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 782 | "dev": true, 783 | "requires": { 784 | "ansi-regex": "^4.1.0" 785 | } 786 | }, 787 | "which": { 788 | "version": "2.0.2", 789 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 790 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 791 | "dev": true, 792 | "requires": { 793 | "isexe": "^2.0.0" 794 | } 795 | }, 796 | "wrap-ansi": { 797 | "version": "5.1.0", 798 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", 799 | "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", 800 | "dev": true, 801 | "requires": { 802 | "ansi-styles": "^3.2.0", 803 | "string-width": "^3.0.0", 804 | "strip-ansi": "^5.0.0" 805 | } 806 | }, 807 | "yargs": { 808 | "version": "13.3.2", 809 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", 810 | "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", 811 | "dev": true, 812 | "requires": { 813 | "cliui": "^5.0.0", 814 | "find-up": "^3.0.0", 815 | "get-caller-file": "^2.0.1", 816 | "require-directory": "^2.1.1", 817 | "require-main-filename": "^2.0.0", 818 | "set-blocking": "^2.0.0", 819 | "string-width": "^3.0.0", 820 | "which-module": "^2.0.0", 821 | "y18n": "^4.0.0", 822 | "yargs-parser": "^13.1.2" 823 | }, 824 | "dependencies": { 825 | "find-up": { 826 | "version": "3.0.0", 827 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 828 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 829 | "dev": true, 830 | "requires": { 831 | "locate-path": "^3.0.0" 832 | } 833 | }, 834 | "locate-path": { 835 | "version": "3.0.0", 836 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 837 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 838 | "dev": true, 839 | "requires": { 840 | "p-locate": "^3.0.0", 841 | "path-exists": "^3.0.0" 842 | } 843 | }, 844 | "p-limit": { 845 | "version": "2.3.0", 846 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 847 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 848 | "dev": true, 849 | "requires": { 850 | "p-try": "^2.0.0" 851 | } 852 | }, 853 | "p-locate": { 854 | "version": "3.0.0", 855 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 856 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 857 | "dev": true, 858 | "requires": { 859 | "p-limit": "^2.0.0" 860 | } 861 | }, 862 | "path-exists": { 863 | "version": "3.0.0", 864 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 865 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 866 | "dev": true 867 | } 868 | } 869 | } 870 | } 871 | }, 872 | "ms": { 873 | "version": "2.1.2", 874 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 875 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 876 | "dev": true 877 | }, 878 | "nanoid": { 879 | "version": "3.1.12", 880 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", 881 | "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", 882 | "dev": true 883 | }, 884 | "nice-try": { 885 | "version": "1.0.5", 886 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 887 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", 888 | "dev": true 889 | }, 890 | "nise": { 891 | "version": "1.4.10", 892 | "resolved": "https://registry.npmjs.org/nise/-/nise-1.4.10.tgz", 893 | "integrity": "sha512-sa0RRbj53dovjc7wombHmVli9ZihXbXCQ2uH3TNm03DyvOSIQbxg+pbqDKrk2oxMK1rtLGVlKxcB9rrc6X5YjA==", 894 | "dev": true, 895 | "requires": { 896 | "@sinonjs/formatio": "^3.1.0", 897 | "@sinonjs/text-encoding": "^0.7.1", 898 | "just-extend": "^4.0.2", 899 | "lolex": "^2.3.2", 900 | "path-to-regexp": "^1.7.0" 901 | }, 902 | "dependencies": { 903 | "lolex": { 904 | "version": "2.7.5", 905 | "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", 906 | "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", 907 | "dev": true 908 | } 909 | } 910 | }, 911 | "normalize-path": { 912 | "version": "3.0.0", 913 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 914 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 915 | "dev": true 916 | }, 917 | "npm-run-path": { 918 | "version": "2.0.2", 919 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", 920 | "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", 921 | "dev": true, 922 | "requires": { 923 | "path-key": "^2.0.0" 924 | } 925 | }, 926 | "number-is-nan": { 927 | "version": "1.0.1", 928 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 929 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 930 | "dev": true 931 | }, 932 | "once": { 933 | "version": "1.4.0", 934 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 935 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 936 | "dev": true, 937 | "requires": { 938 | "wrappy": "1" 939 | } 940 | }, 941 | "os-locale": { 942 | "version": "3.1.0", 943 | "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", 944 | "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", 945 | "dev": true, 946 | "requires": { 947 | "execa": "^1.0.0", 948 | "lcid": "^2.0.0", 949 | "mem": "^4.0.0" 950 | } 951 | }, 952 | "p-defer": { 953 | "version": "1.0.0", 954 | "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", 955 | "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", 956 | "dev": true 957 | }, 958 | "p-finally": { 959 | "version": "1.0.0", 960 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 961 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", 962 | "dev": true 963 | }, 964 | "p-is-promise": { 965 | "version": "2.1.0", 966 | "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", 967 | "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", 968 | "dev": true 969 | }, 970 | "p-limit": { 971 | "version": "2.0.0", 972 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.0.0.tgz", 973 | "integrity": "sha512-fl5s52lI5ahKCernzzIyAP0QAZbGIovtVHGwpcu1Jr/EpzLVDI2myISHwGqK7m8uQFugVWSrbxH7XnhGtvEc+A==", 974 | "dev": true, 975 | "requires": { 976 | "p-try": "^2.0.0" 977 | } 978 | }, 979 | "p-locate": { 980 | "version": "3.0.0", 981 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 982 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 983 | "dev": true, 984 | "requires": { 985 | "p-limit": "^2.0.0" 986 | } 987 | }, 988 | "p-try": { 989 | "version": "2.0.0", 990 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.0.0.tgz", 991 | "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==", 992 | "dev": true 993 | }, 994 | "path-exists": { 995 | "version": "3.0.0", 996 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 997 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 998 | "dev": true 999 | }, 1000 | "path-is-absolute": { 1001 | "version": "1.0.1", 1002 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1003 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1004 | "dev": true 1005 | }, 1006 | "path-key": { 1007 | "version": "2.0.1", 1008 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 1009 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", 1010 | "dev": true 1011 | }, 1012 | "path-to-regexp": { 1013 | "version": "1.7.0", 1014 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", 1015 | "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", 1016 | "dev": true, 1017 | "requires": { 1018 | "isarray": "0.0.1" 1019 | }, 1020 | "dependencies": { 1021 | "isarray": { 1022 | "version": "0.0.1", 1023 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 1024 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", 1025 | "dev": true 1026 | } 1027 | } 1028 | }, 1029 | "pathval": { 1030 | "version": "1.1.0", 1031 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", 1032 | "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", 1033 | "dev": true 1034 | }, 1035 | "picomatch": { 1036 | "version": "2.2.2", 1037 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 1038 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 1039 | "dev": true 1040 | }, 1041 | "pump": { 1042 | "version": "3.0.0", 1043 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 1044 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 1045 | "dev": true, 1046 | "requires": { 1047 | "end-of-stream": "^1.1.0", 1048 | "once": "^1.3.1" 1049 | } 1050 | }, 1051 | "punycode": { 1052 | "version": "1.3.2", 1053 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", 1054 | "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" 1055 | }, 1056 | "querystring": { 1057 | "version": "0.2.0", 1058 | "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", 1059 | "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" 1060 | }, 1061 | "randombytes": { 1062 | "version": "2.1.0", 1063 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 1064 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 1065 | "dev": true, 1066 | "requires": { 1067 | "safe-buffer": "^5.1.0" 1068 | } 1069 | }, 1070 | "readable-stream": { 1071 | "version": "3.3.0", 1072 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", 1073 | "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", 1074 | "requires": { 1075 | "inherits": "^2.0.3", 1076 | "string_decoder": "^1.1.1", 1077 | "util-deprecate": "^1.0.1" 1078 | } 1079 | }, 1080 | "readdirp": { 1081 | "version": "3.5.0", 1082 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", 1083 | "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", 1084 | "dev": true, 1085 | "requires": { 1086 | "picomatch": "^2.2.1" 1087 | } 1088 | }, 1089 | "require-directory": { 1090 | "version": "2.1.1", 1091 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1092 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1093 | "dev": true 1094 | }, 1095 | "require-main-filename": { 1096 | "version": "2.0.0", 1097 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 1098 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 1099 | "dev": true 1100 | }, 1101 | "safe-buffer": { 1102 | "version": "5.1.2", 1103 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1104 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1105 | }, 1106 | "sax": { 1107 | "version": "1.2.1", 1108 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", 1109 | "integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o=" 1110 | }, 1111 | "semver": { 1112 | "version": "5.7.0", 1113 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", 1114 | "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==", 1115 | "dev": true 1116 | }, 1117 | "serialize-javascript": { 1118 | "version": "5.0.1", 1119 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", 1120 | "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", 1121 | "dev": true, 1122 | "requires": { 1123 | "randombytes": "^2.1.0" 1124 | } 1125 | }, 1126 | "set-blocking": { 1127 | "version": "2.0.0", 1128 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 1129 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 1130 | "dev": true 1131 | }, 1132 | "shebang-command": { 1133 | "version": "1.2.0", 1134 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1135 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1136 | "dev": true, 1137 | "requires": { 1138 | "shebang-regex": "^1.0.0" 1139 | } 1140 | }, 1141 | "shebang-regex": { 1142 | "version": "1.0.0", 1143 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1144 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 1145 | "dev": true 1146 | }, 1147 | "signal-exit": { 1148 | "version": "3.0.2", 1149 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1150 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 1151 | "dev": true 1152 | }, 1153 | "sinon": { 1154 | "version": "7.3.2", 1155 | "resolved": "https://registry.npmjs.org/sinon/-/sinon-7.3.2.tgz", 1156 | "integrity": "sha512-thErC1z64BeyGiPvF8aoSg0LEnptSaWE7YhdWWbWXgelOyThent7uKOnnEh9zBxDbKixtr5dEko+ws1sZMuFMA==", 1157 | "dev": true, 1158 | "requires": { 1159 | "@sinonjs/commons": "^1.4.0", 1160 | "@sinonjs/formatio": "^3.2.1", 1161 | "@sinonjs/samsam": "^3.3.1", 1162 | "diff": "^3.5.0", 1163 | "lolex": "^4.0.1", 1164 | "nise": "^1.4.10", 1165 | "supports-color": "^5.5.0" 1166 | }, 1167 | "dependencies": { 1168 | "supports-color": { 1169 | "version": "5.5.0", 1170 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1171 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1172 | "dev": true, 1173 | "requires": { 1174 | "has-flag": "^3.0.0" 1175 | } 1176 | } 1177 | } 1178 | }, 1179 | "sprintf-js": { 1180 | "version": "1.0.3", 1181 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1182 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1183 | "dev": true 1184 | }, 1185 | "streamers": { 1186 | "version": "0.1.1", 1187 | "resolved": "https://registry.npmjs.org/streamers/-/streamers-0.1.1.tgz", 1188 | "integrity": "sha1-OHk+rhRHAhaC7TYdHjEGrFlrDFU=", 1189 | "dev": true, 1190 | "requires": { 1191 | "underscore": "1.2.3", 1192 | "vows": "0.6.1" 1193 | } 1194 | }, 1195 | "string-width": { 1196 | "version": "2.1.1", 1197 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1198 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1199 | "dev": true, 1200 | "requires": { 1201 | "is-fullwidth-code-point": "^2.0.0", 1202 | "strip-ansi": "^4.0.0" 1203 | } 1204 | }, 1205 | "string_decoder": { 1206 | "version": "1.2.0", 1207 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", 1208 | "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", 1209 | "requires": { 1210 | "safe-buffer": "~5.1.0" 1211 | } 1212 | }, 1213 | "strip-ansi": { 1214 | "version": "4.0.0", 1215 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1216 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1217 | "dev": true, 1218 | "requires": { 1219 | "ansi-regex": "^3.0.0" 1220 | } 1221 | }, 1222 | "strip-eof": { 1223 | "version": "1.0.0", 1224 | "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", 1225 | "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", 1226 | "dev": true 1227 | }, 1228 | "strip-json-comments": { 1229 | "version": "3.1.1", 1230 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1231 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1232 | "dev": true 1233 | }, 1234 | "supports-color": { 1235 | "version": "7.2.0", 1236 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1237 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1238 | "dev": true, 1239 | "requires": { 1240 | "has-flag": "^4.0.0" 1241 | }, 1242 | "dependencies": { 1243 | "has-flag": { 1244 | "version": "4.0.0", 1245 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1246 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1247 | "dev": true 1248 | } 1249 | } 1250 | }, 1251 | "to-regex-range": { 1252 | "version": "5.0.1", 1253 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1254 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1255 | "dev": true, 1256 | "requires": { 1257 | "is-number": "^7.0.0" 1258 | } 1259 | }, 1260 | "type-detect": { 1261 | "version": "4.0.8", 1262 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 1263 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 1264 | "dev": true 1265 | }, 1266 | "underscore": { 1267 | "version": "1.2.3", 1268 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.2.3.tgz", 1269 | "integrity": "sha1-Ebh02nD0aD19SLuitEvh5gDS9s8=", 1270 | "dev": true 1271 | }, 1272 | "url": { 1273 | "version": "0.10.3", 1274 | "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", 1275 | "integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=", 1276 | "requires": { 1277 | "punycode": "1.3.2", 1278 | "querystring": "0.2.0" 1279 | } 1280 | }, 1281 | "util-deprecate": { 1282 | "version": "1.0.2", 1283 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1284 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1285 | }, 1286 | "uuid": { 1287 | "version": "3.3.2", 1288 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", 1289 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" 1290 | }, 1291 | "vows": { 1292 | "version": "0.6.1", 1293 | "resolved": "https://registry.npmjs.org/vows/-/vows-0.6.1.tgz", 1294 | "integrity": "sha1-DTzOx2eUt6yGALXHANaJhkpkCis=", 1295 | "dev": true, 1296 | "requires": { 1297 | "eyes": ">=0.1.6" 1298 | } 1299 | }, 1300 | "which": { 1301 | "version": "1.3.1", 1302 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1303 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1304 | "dev": true, 1305 | "requires": { 1306 | "isexe": "^2.0.0" 1307 | } 1308 | }, 1309 | "which-module": { 1310 | "version": "2.0.0", 1311 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 1312 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 1313 | "dev": true 1314 | }, 1315 | "wide-align": { 1316 | "version": "1.1.3", 1317 | "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", 1318 | "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", 1319 | "dev": true, 1320 | "requires": { 1321 | "string-width": "^1.0.2 || 2" 1322 | } 1323 | }, 1324 | "workerpool": { 1325 | "version": "6.0.2", 1326 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", 1327 | "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", 1328 | "dev": true 1329 | }, 1330 | "wrap-ansi": { 1331 | "version": "2.1.0", 1332 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", 1333 | "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", 1334 | "dev": true, 1335 | "requires": { 1336 | "string-width": "^1.0.1", 1337 | "strip-ansi": "^3.0.1" 1338 | }, 1339 | "dependencies": { 1340 | "ansi-regex": { 1341 | "version": "2.1.1", 1342 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 1343 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 1344 | "dev": true 1345 | }, 1346 | "is-fullwidth-code-point": { 1347 | "version": "1.0.0", 1348 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 1349 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 1350 | "dev": true, 1351 | "requires": { 1352 | "number-is-nan": "^1.0.0" 1353 | } 1354 | }, 1355 | "string-width": { 1356 | "version": "1.0.2", 1357 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 1358 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 1359 | "dev": true, 1360 | "requires": { 1361 | "code-point-at": "^1.0.0", 1362 | "is-fullwidth-code-point": "^1.0.0", 1363 | "strip-ansi": "^3.0.0" 1364 | } 1365 | }, 1366 | "strip-ansi": { 1367 | "version": "3.0.1", 1368 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1369 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1370 | "dev": true, 1371 | "requires": { 1372 | "ansi-regex": "^2.0.0" 1373 | } 1374 | } 1375 | } 1376 | }, 1377 | "wrappy": { 1378 | "version": "1.0.2", 1379 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1380 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1381 | "dev": true 1382 | }, 1383 | "xml2js": { 1384 | "version": "0.4.19", 1385 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", 1386 | "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", 1387 | "requires": { 1388 | "sax": ">=0.6.0", 1389 | "xmlbuilder": "~9.0.1" 1390 | } 1391 | }, 1392 | "xmlbuilder": { 1393 | "version": "9.0.7", 1394 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", 1395 | "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=" 1396 | }, 1397 | "y18n": { 1398 | "version": "4.0.1", 1399 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", 1400 | "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", 1401 | "dev": true 1402 | }, 1403 | "yargs": { 1404 | "version": "13.2.2", 1405 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", 1406 | "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", 1407 | "dev": true, 1408 | "requires": { 1409 | "cliui": "^4.0.0", 1410 | "find-up": "^3.0.0", 1411 | "get-caller-file": "^2.0.1", 1412 | "os-locale": "^3.1.0", 1413 | "require-directory": "^2.1.1", 1414 | "require-main-filename": "^2.0.0", 1415 | "set-blocking": "^2.0.0", 1416 | "string-width": "^3.0.0", 1417 | "which-module": "^2.0.0", 1418 | "y18n": "^4.0.0", 1419 | "yargs-parser": "^13.0.0" 1420 | }, 1421 | "dependencies": { 1422 | "ansi-regex": { 1423 | "version": "4.1.0", 1424 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 1425 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 1426 | "dev": true 1427 | }, 1428 | "string-width": { 1429 | "version": "3.1.0", 1430 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1431 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1432 | "dev": true, 1433 | "requires": { 1434 | "emoji-regex": "^7.0.1", 1435 | "is-fullwidth-code-point": "^2.0.0", 1436 | "strip-ansi": "^5.1.0" 1437 | } 1438 | }, 1439 | "strip-ansi": { 1440 | "version": "5.2.0", 1441 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1442 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1443 | "dev": true, 1444 | "requires": { 1445 | "ansi-regex": "^4.1.0" 1446 | } 1447 | } 1448 | } 1449 | }, 1450 | "yargs-parser": { 1451 | "version": "13.1.2", 1452 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", 1453 | "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", 1454 | "dev": true, 1455 | "requires": { 1456 | "camelcase": "^5.0.0", 1457 | "decamelize": "^1.2.0" 1458 | } 1459 | }, 1460 | "yargs-unparser": { 1461 | "version": "2.0.0", 1462 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 1463 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 1464 | "dev": true, 1465 | "requires": { 1466 | "camelcase": "^6.0.0", 1467 | "decamelize": "^4.0.0", 1468 | "flat": "^5.0.2", 1469 | "is-plain-obj": "^2.1.0" 1470 | }, 1471 | "dependencies": { 1472 | "camelcase": { 1473 | "version": "6.2.0", 1474 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", 1475 | "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", 1476 | "dev": true 1477 | }, 1478 | "decamelize": { 1479 | "version": "4.0.0", 1480 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 1481 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 1482 | "dev": true 1483 | } 1484 | } 1485 | } 1486 | } 1487 | } 1488 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "s3-streaming-upload", 3 | "description": "Streaming upload to S3", 4 | "version": "0.3.4", 5 | "author": "Apiary Inc ", 6 | "contributors": [ 7 | { 8 | "name": "Lukas Linhart", 9 | "email": "lukas@apiary.io" 10 | }, 11 | { 12 | "name": "Ladislav Prskavec", 13 | "email": "ladislav@apiary.io" 14 | } 15 | ], 16 | "dependencies": { 17 | "aws-sdk": "^2.814.0", 18 | "readable-stream": "^3.3.0" 19 | }, 20 | "devDependencies": { 21 | "async": "^2.6.2", 22 | "chai": "^4.2.0", 23 | "mocha": "^8.2.1", 24 | "sinon": "^7.3.2", 25 | "streamers": "^0.1.1", 26 | "yargs": "^13.2.2" 27 | }, 28 | "keywords": [ 29 | "aws", 30 | "s3", 31 | "stream", 32 | "aws stream", 33 | "aws s3 stream", 34 | "aws s3", 35 | "aws s3 streaming", 36 | "aws s3 streaming upload", 37 | "aws-sdk s3 streaming upload", 38 | "aws s3 upload", 39 | "s3 upload", 40 | "s3 stream upload", 41 | "s3 streaming", 42 | "streaming upload", 43 | "s3 streaming upload" 44 | ], 45 | "scripts": { 46 | "test": "./node_modules/.bin/mocha", 47 | "test:integration": "./node_modules/.bin/mocha test/integration", 48 | "test:integration:oci": "./node_modules/.bin/mocha test/oci-integration" 49 | }, 50 | "licenses": [ 51 | { 52 | "type": "MIT", 53 | "url": "https://github.com/apiaryio/s3-streaming-upload/blob/master/LICENSE" 54 | } 55 | ], 56 | "repository": { 57 | "type": "git", 58 | "url": "http://github.com/apiaryio/s3-streaming-upload" 59 | }, 60 | "bugs": { 61 | "url": "http://github.com/apiaryio/s3-streaming-upload/issues" 62 | }, 63 | "main": "src/index.js", 64 | "engines": { 65 | "node": ">= 12.13.0" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | const { EventEmitter } = require('events'); 2 | 3 | const aws = require('aws-sdk'); 4 | 5 | class Uploader extends EventEmitter { 6 | // Constructor 7 | constructor({ 8 | accessKey, 9 | secretKey, 10 | sessionToken, 11 | region, 12 | stream, 13 | objectName, 14 | objectParams, 15 | bucket, 16 | partSize, 17 | service, 18 | debug, 19 | }, cb) { 20 | super(); 21 | this.cb = cb; 22 | aws.config.update({ 23 | accessKeyId: accessKey, 24 | secretAccessKey: secretKey, 25 | sessionToken, 26 | region: region || undefined, 27 | }); 28 | 29 | const params = { 30 | Bucket: bucket, 31 | Key: objectName, 32 | Body: stream, 33 | }; 34 | 35 | for (const k in objectParams || {}) { 36 | if (!params[k]) { 37 | params[k] = objectParams[k]; 38 | } 39 | } 40 | 41 | this.objectName = objectName; 42 | this.objectParams = params; 43 | this.timeout = 300000; 44 | this.debug = debug || false; 45 | 46 | if (!this.objectParams.Bucket) { 47 | throw new Error('Bucket must be given'); 48 | } 49 | 50 | this.upload = new aws.S3.ManagedUpload({ 51 | partSize: partSize || 10 * 1024 * 1024, 52 | queueSize: 4, 53 | service, 54 | params, 55 | }); 56 | // Progress event 57 | this.upload.on('httpUploadProgress', (progress) => { 58 | if (this.debug) { 59 | console.log(`${progress.loaded} / ${progress.total}`); 60 | } 61 | }); 62 | } 63 | 64 | // Send stream 65 | send(callback) { 66 | this.upload.send((err, data) => { 67 | if (err) { 68 | console.log(err, data); 69 | } 70 | callback(err, data); 71 | }); 72 | } 73 | } 74 | 75 | module.exports = { Uploader }; 76 | -------------------------------------------------------------------------------- /test/integration/chunk-test.js: -------------------------------------------------------------------------------- 1 | const { assert } = require('chai'); 2 | const { Uploader } = require('../../src'); 3 | 4 | describe('AWS: 8MB file in parts upload @integration test', () => { 5 | let buf = ''; 6 | let source; 7 | let uploader; 8 | 9 | before((done) => { 10 | for (let i = 1; i <= 8388608; i++) { 11 | buf += '0'; 12 | } 13 | source = Buffer.from(buf); 14 | 15 | const actualDate = new Date(); 16 | const folder = `${actualDate.getUTCFullYear()}-${`0${actualDate.getUTCMonth()}`.slice(-2)}`; 17 | 18 | uploader = new Uploader({ 19 | accessKey: process.env.AWS_S3_ACCESS_KEY, 20 | secretKey: process.env.AWS_S3_SECRET_KEY, 21 | bucket: process.env.AWS_S3_TEST_BUCKET, 22 | objectName: `${folder}/testfile${new Date().getTime()}`, 23 | stream: source, 24 | debug: false, 25 | }); 26 | done(); 27 | }); 28 | 29 | describe(' and when I write a file and finish', () => { 30 | let data = null; 31 | 32 | before(function send(done) { 33 | this.timeout(parseInt(process.env.TEST_TIMEOUT, 10) || 300000); 34 | 35 | uploader.send((err, returnedData) => { 36 | data = returnedData; 37 | done(err); 38 | }); 39 | }); 40 | 41 | it('I have received ETag', () => assert.equal(data.ETag.length, 34)); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/integration/upload-test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * decaffeinate suggestions: 3 | * DS102: Remove unnecessary code created because of implicit returns 4 | * DS103: Rewrite code to no longer use __guard__ 5 | * DS207: Consider shorter variations of null checks 6 | * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md 7 | */ 8 | const { assert } = require('chai'); 9 | const aws = require('aws-sdk'); 10 | const async = require('async'); 11 | const { Uploader } = require('../../src'); 12 | 13 | const getLastFileInBucket = ({ accessKey, secretKey, region, bucket }, cb) => { 14 | aws.config.update({ 15 | accessKeyId: accessKey, 16 | secretAccessKey: secretKey, 17 | region: region || undefined, 18 | }); 19 | 20 | const client = new aws.S3(); 21 | if (client) { 22 | const params = { Bucket: bucket }; 23 | 24 | client.listObjects(params, (err, data) => { 25 | if (err) { 26 | cb(err); 27 | } 28 | 29 | if (!data || !data.Contents || !data.Contents.length) { 30 | cb(new Error(`No files in ${data ? data.Name : undefined} S3 bucket`)); 31 | } 32 | 33 | let prevDate = 0; 34 | let newestFile = null; 35 | 36 | async.each( 37 | data.Contents, 38 | (file, callback) => { 39 | const curDate = new Date(file.LastModified); 40 | 41 | if (curDate > prevDate) { 42 | newestFile = file.Key; 43 | prevDate = curDate; 44 | } 45 | 46 | callback(); 47 | }, 48 | asyncErr => cb(asyncErr, newestFile) 49 | ); 50 | }); 51 | } else { 52 | cb(new Error('Error aws client init')); 53 | } 54 | }; 55 | 56 | describe('AWS: Small file upload @integration test', () => { 57 | let source; 58 | let uploader; 59 | let filename; 60 | 61 | const actualDate = new Date(); 62 | const folder = `${actualDate.getUTCFullYear()}-${`0${actualDate.getUTCMonth()}`.slice(-2)}`; 63 | 64 | before((done) => { 65 | source = Buffer.from('key;value\ntest;1\nexample;2\n'); 66 | filename = `${folder}/testfileSmall${new Date().getTime()}`; 67 | uploader = new Uploader({ 68 | accessKey: process.env.AWS_S3_ACCESS_KEY, 69 | secretKey: process.env.AWS_S3_SECRET_KEY, 70 | bucket: process.env.AWS_S3_TEST_BUCKET, 71 | objectName: filename, 72 | stream: source, 73 | objectParams: { 74 | ContentType: 'text/csv', 75 | }, 76 | debug: true, 77 | }); 78 | done(); 79 | }); 80 | 81 | describe(' and When I write a file and finish', () => { 82 | let data = null; 83 | 84 | before(function send(done) { 85 | this.timeout(parseInt(process.env.TEST_TIMEOUT, 10) || 300000); 86 | 87 | uploader.send((err, returnedData) => { 88 | data = returnedData; 89 | done(err); 90 | }); 91 | }); 92 | 93 | it('I have received ETag', () => assert.equal(data.ETag.length, 34)); 94 | 95 | it('List last file in bucket', done => getLastFileInBucket( 96 | { 97 | accessKey: process.env.AWS_S3_ACCESS_KEY, 98 | secretKey: process.env.AWS_S3_SECRET_KEY, 99 | bucket: process.env.AWS_S3_TEST_BUCKET, 100 | }, 101 | (err, file) => { 102 | if (err) { 103 | console.error(`Error: ${err}`); 104 | } 105 | assert.equal(file, filename); 106 | done(err); 107 | } 108 | )); 109 | }); 110 | }); 111 | -------------------------------------------------------------------------------- /test/oci-integration/chunk-test.js: -------------------------------------------------------------------------------- 1 | const { assert } = require('chai'); 2 | const aws = require('aws-sdk'); 3 | const { Uploader } = require('../../src'); 4 | 5 | describe('OCI: 8MB file in parts upload @integration test', () => { 6 | let source; 7 | let uploader; 8 | 9 | before((done) => { 10 | source = Buffer.alloc(8388608, '0'); 11 | 12 | const actualDate = new Date(); 13 | const folder = `${actualDate.getUTCFullYear()}-${`0${actualDate.getUTCMonth()}`.slice(-2)}`; 14 | 15 | const region = process.env.OCI_REGION; 16 | const tenancy = process.env.OCI_TENANCY; 17 | 18 | const service = new aws.S3({ 19 | apiVersion: '2006-03-01', 20 | credentials: { 21 | accessKeyId: process.env.AWS_S3_ACCESS_KEY, 22 | secretAccessKey: process.env.AWS_S3_SECRET_KEY, 23 | }, 24 | params: { Bucket: process.env.AWS_S3_TEST_BUCKET }, 25 | endpoint: `${tenancy}.compat.objectstorage.${region}.oraclecloud.com`, 26 | region, 27 | signatureVersion: 'v4', 28 | s3ForcePathStyle: true, 29 | }); 30 | 31 | uploader = new Uploader({ 32 | accessKey: process.env.AWS_S3_ACCESS_KEY, 33 | secretKey: process.env.AWS_S3_SECRET_KEY, 34 | bucket: process.env.AWS_S3_TEST_BUCKET, 35 | objectName: `${folder}/testfile${new Date().getTime()}`, 36 | stream: source, 37 | service, 38 | debug: false, 39 | }); 40 | done(); 41 | }); 42 | 43 | describe(' and when I write a file and finish', () => { 44 | let data = null; 45 | 46 | before(function send(done) { 47 | this.timeout(parseInt(process.env.TEST_TIMEOUT, 10) || 300000); 48 | 49 | uploader.send((err, returnedData) => { 50 | data = returnedData; 51 | done(err); 52 | }); 53 | }); 54 | 55 | it('I have received ETag', () => assert.equal(data.ETag.length, 34)); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/oci-integration/upload-test.js: -------------------------------------------------------------------------------- 1 | const { assert } = require('chai'); 2 | const aws = require('aws-sdk'); 3 | const { Uploader } = require('../../src'); 4 | 5 | describe('OCI: Small file upload @integration test', () => { 6 | let source; 7 | let uploader; 8 | let filename; 9 | 10 | const actualDate = new Date(); 11 | const folder = `${actualDate.getUTCFullYear()}-${`0${actualDate.getUTCMonth()}`.slice(-2)}`; 12 | 13 | before((done) => { 14 | source = Buffer.from('key;value\ntest;1\nexample;2\n'); 15 | filename = `${folder}/testfileSmall${new Date().getTime()}`; 16 | const region = process.env.OCI_REGION; 17 | const tenancy = process.env.OCI_TENANCY; 18 | const service = new aws.S3({ 19 | apiVersion: '2006-03-01', 20 | credentials: { 21 | accessKeyId: process.env.AWS_S3_ACCESS_KEY, 22 | secretAccessKey: process.env.AWS_S3_SECRET_KEY, 23 | }, 24 | params: { Bucket: process.env.AWS_S3_TEST_BUCKET }, 25 | endpoint: `${tenancy}.compat.objectstorage.${region}.oraclecloud.com`, 26 | region, 27 | signatureVersion: 'v4', 28 | s3ForcePathStyle: true, 29 | }); 30 | 31 | uploader = new Uploader({ 32 | accessKey: process.env.AWS_S3_ACCESS_KEY, 33 | secretKey: process.env.AWS_S3_SECRET_KEY, 34 | bucket: process.env.AWS_S3_TEST_BUCKET, 35 | objectName: filename, 36 | stream: source, 37 | service, 38 | objectParams: { 39 | ContentType: 'text/csv', 40 | }, 41 | debug: true, 42 | }); 43 | done(); 44 | }); 45 | 46 | describe(' and When I write a file and finish', () => { 47 | let data = null; 48 | 49 | before(function send(done) { 50 | this.timeout(parseInt(process.env.TEST_TIMEOUT, 10) || 300000); 51 | 52 | uploader.send((err, returnedData) => { 53 | data = returnedData; 54 | done(err); 55 | }); 56 | }); 57 | 58 | it('I have received ETag', () => assert.equal(data.ETag.length, 34)); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /test/uploader-test.js: -------------------------------------------------------------------------------- 1 | const { assert } = require('chai'); 2 | const { Uploader } = require('../src'); 3 | 4 | describe('Setup file upload test', () => { 5 | let source; 6 | let uploader; 7 | 8 | const objectParams = { ContentType: 'text/csv' }; 9 | 10 | before(() => { 11 | source = Buffer.from('key;value\ntest;1\nexample;2\n'); 12 | 13 | uploader = new Uploader({ 14 | accessKey: 'test-accessKey', 15 | secretKey: 'test-secretKey', 16 | bucket: 'test-bucket', 17 | objectName: 'testfile1', 18 | objectParams, 19 | stream: source, 20 | debug: true, 21 | }); 22 | }); 23 | 24 | it('Should have set accessKey', () => assert.equal(uploader.upload.service.config.credentials.accessKeyId, 'test-accessKey')); 25 | 26 | it('Should have set bucket', () => assert.equal(uploader.objectParams.Bucket, 'test-bucket')); 27 | 28 | it('Should have set key', () => assert.equal(uploader.objectParams.Key, 'testfile1')); 29 | 30 | it('Should have set ContentType', () => assert.equal(uploader.objectParams.ContentType, 'text/csv')); 31 | 32 | it('Should have set debug', () => assert.ok(uploader.debug)); 33 | 34 | it('Should not create custom service', () => assert.isUndefined(uploader.service)); 35 | 36 | describe('Creating a second uploader', () => { 37 | let uploader2; 38 | 39 | before(() => { 40 | uploader2 = new Uploader({ 41 | bucket: 'test-bucket-2', 42 | stream: Buffer.from('...\n'), 43 | objectParams, 44 | }); 45 | }); 46 | 47 | it('Should have set bucket', () => assert.equal(uploader2.objectParams.Bucket, 'test-bucket-2')); 48 | 49 | it('Should have not unset original bucket', () => assert.equal(uploader.objectParams.Bucket, 'test-bucket')); 50 | }); 51 | }); 52 | --------------------------------------------------------------------------------