├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── index.js ├── package-lock.json ├── package.json └── test ├── case ├── contract.js ├── empty.js ├── error.js ├── grow.js └── test.txt ├── grow.js ├── grow.txt └── index.js /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset=utf-8 3 | end_of_line=lf 4 | insert_final_newline=true 5 | trim_trailing_whitespace=true 6 | indent_style=space 7 | indent_size=4 8 | 9 | [*.json] 10 | indent_size=2 11 | 12 | [*.ts] 13 | end_of_line = crlf 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | jsdoc2md/ 2 | samples/browser/ 3 | samples/fantasies/ 4 | samples/so-examples/ 5 | samples/tests/ 6 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["scramjet"] 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | CHANGELOG.md.orig 61 | 62 | samples/generated-data 63 | **/*.tmp -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "10" 4 | - "12" 5 | - "14" 6 | - "node" 7 | script: npm test 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 OpenAQ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rw-stream 2 | 3 | A stream that can substitute contents of a file in streaming fashion. 4 | 5 | The aim of this module is to expose a readable and writable stream connected to a single file at the same time. It works similarily to `fs.createReadStream` and `fs.createWriteStream`, but allows writing and reading simultanously, without creating a new file or move operations. 6 | 7 | This is achieved by disallowing any write operations to advance further than the current reading index. This module will then make sure that a byte of the file will be read before it's overwritten. 8 | 9 | ***Note:*** In any case, the file will be accessed and it's contents may be overwritten even if there's no actual read operation done (due to node.js streams buffering mechanisms). 10 | 11 | ## Usage: 12 | 13 | ```javascript 14 | const rw = require("../"); 15 | 16 | const {fd, readStream, writeStream} = await rw(path, options); 17 | ``` 18 | 19 | Arguments: 20 | 21 | * **path** `string` - the path of the file to access. 22 | * **options** `object` - options, currently none. 23 | 24 | Returns an `object` with the following properties: 25 | 26 | * **fd** `int` - file descriptor number (from `fs.open`) 27 | * **writeStream** `Writable` - Writable stream for new file contents. 28 | * **readStream** `Readable` - Readable stream containing previous contents. 29 | 30 | ## Samples 31 | 32 | A simple module that replaces the contents of a file while keeping a backup: 33 | 34 | ```javascript 35 | const replaceAndBackup = async (newContentStream) => { 36 | const {readStream, writeStream} = await rw(path); 37 | 38 | readStream.pipe(fs.createWriteStream(`${path}.bak`)); 39 | newContentStream.pipe(writeStream); 40 | 41 | return new Promise((res, rej) => writeStream.on('finish', res).on('error', rej)); 42 | } 43 | ``` 44 | 45 | ## Testing 46 | 47 | For now there's just: 48 | 49 | ```bash 50 | $ node test 51 | ``` 52 | 53 | Two tests will be executed: 54 | 55 | * one for file that's being grown. 56 | * one for file that's being shrinked. 57 | 58 | We're working on more and proper tests. 59 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const {promisify} = require("util"); 2 | 3 | const fs = require("fs"); 4 | const [open, close, read, write, ftruncate] = [ 5 | promisify(fs. open), 6 | promisify(fs. close), 7 | promisify(fs. read), 8 | promisify(fs. write), 9 | promisify(fs.ftruncate), 10 | ]; 11 | 12 | const {Readable, Writable} = require("stream"); 13 | const debug = process.env.DEBUG && process.env.DEBUG.match(/\brw-stream\b/); 14 | const log = (...data) => debug && console.error(...data); 15 | 16 | module.exports = (async (file, {readStart, writeStart} = {}) => { 17 | const fd = await open(file, "r+"); 18 | log(`File ${file} open`); 19 | 20 | let readIndex = +readStart || 0; 21 | let writeIndex = +writeStart || 0; 22 | 23 | let _updateReadPosition = () => 0; 24 | let _readPositonUpdated; 25 | function advanceReadPosition(pos) { 26 | const lastReadPromise = _updateReadPosition; 27 | if (pos > 0) { 28 | readIndex += pos; 29 | _readPositonUpdated = new Promise(res => _updateReadPosition = res); 30 | } else { 31 | readIndex = Infinity; 32 | } 33 | log(`Advance read position by ${pos}`); 34 | lastReadPromise(pos); 35 | } 36 | // advanceReadPosition(0); 37 | 38 | if (readStart < writeStart) throw new Error("Read index MUST come before write index."); 39 | 40 | const readStream = new Readable({async read(size) { 41 | try { 42 | const ret = Buffer.alloc(size); 43 | const {bytesRead} = await read(fd, ret, 0, size, readIndex); 44 | log(`Read ${bytesRead} from ${readIndex}`); 45 | advanceReadPosition(bytesRead); 46 | 47 | if (!bytesRead) 48 | return this.push(null); 49 | 50 | this.push(ret.slice(0, bytesRead)); 51 | } catch(e) { 52 | log(e); 53 | this.destroy(e); 54 | } 55 | }}); 56 | 57 | let _writePromise = { 58 | then (func) { 59 | func(); 60 | return this; 61 | } 62 | }; 63 | const writeStream = new Writable({ 64 | writev(chunks, callback) { 65 | return this._write( 66 | Buffer.concat( 67 | chunks.map(({chunk, encoding}) => Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding)) 68 | ), 69 | null, 70 | callback 71 | ); 72 | }, 73 | write(chunk, encoding, callback) { 74 | _writePromise = (async () => { 75 | try { 76 | const toWrite = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, encoding); 77 | let currentIndex = 0; 78 | while (true) { /* eslint-disable-line no-constant-condition */ 79 | const maxWrite = Math.min(readIndex - (writeIndex + currentIndex), toWrite.length - currentIndex); 80 | if (maxWrite === 0) { 81 | log(`Awaiting for advance of read position at ${writeIndex + currentIndex} wanting write ${toWrite}`); 82 | 83 | if (await _readPositonUpdated === 0 && toWrite.length === currentIndex) return; 84 | continue; 85 | } 86 | 87 | const {bytesWritten} = await write(fd, toWrite, currentIndex, maxWrite, writeIndex + currentIndex); 88 | log(`Wrote ${bytesWritten} at ${writeIndex + currentIndex}`); 89 | 90 | currentIndex += bytesWritten; 91 | if (currentIndex === toWrite.length) break; 92 | } 93 | 94 | writeIndex += currentIndex; 95 | 96 | callback(); 97 | } catch(e) { 98 | log(e); 99 | callback(e); 100 | } 101 | })(); 102 | }, 103 | final(callback) { 104 | _writePromise 105 | .then(() => ftruncate(fd, writeIndex)) 106 | .then(() => close(fd)) 107 | .then(callback); 108 | } 109 | }); 110 | 111 | return { 112 | fd, 113 | readStream, 114 | writeStream 115 | }; 116 | }); 117 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rw-stream", 3 | "version": "0.4.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.12.11", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", 10 | "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.10.4" 14 | } 15 | }, 16 | "@babel/helper-validator-identifier": { 17 | "version": "7.12.11", 18 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", 19 | "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", 20 | "dev": true 21 | }, 22 | "@babel/highlight": { 23 | "version": "7.10.4", 24 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", 25 | "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", 26 | "dev": true, 27 | "requires": { 28 | "@babel/helper-validator-identifier": "^7.10.4", 29 | "chalk": "^2.0.0", 30 | "js-tokens": "^4.0.0" 31 | }, 32 | "dependencies": { 33 | "chalk": { 34 | "version": "2.4.2", 35 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 36 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 37 | "dev": true, 38 | "requires": { 39 | "ansi-styles": "^3.2.1", 40 | "escape-string-regexp": "^1.0.5", 41 | "supports-color": "^5.3.0" 42 | } 43 | } 44 | } 45 | }, 46 | "@eslint/eslintrc": { 47 | "version": "0.3.0", 48 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", 49 | "integrity": "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==", 50 | "dev": true, 51 | "requires": { 52 | "ajv": "^6.12.4", 53 | "debug": "^4.1.1", 54 | "espree": "^7.3.0", 55 | "globals": "^12.1.0", 56 | "ignore": "^4.0.6", 57 | "import-fresh": "^3.2.1", 58 | "js-yaml": "^3.13.1", 59 | "lodash": "^4.17.20", 60 | "minimatch": "^3.0.4", 61 | "strip-json-comments": "^3.1.1" 62 | }, 63 | "dependencies": { 64 | "ignore": { 65 | "version": "4.0.6", 66 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 67 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 68 | "dev": true 69 | } 70 | } 71 | }, 72 | "acorn": { 73 | "version": "7.4.1", 74 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", 75 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", 76 | "dev": true 77 | }, 78 | "acorn-jsx": { 79 | "version": "5.3.1", 80 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", 81 | "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", 82 | "dev": true 83 | }, 84 | "ajv": { 85 | "version": "6.12.6", 86 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 87 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 88 | "dev": true, 89 | "requires": { 90 | "fast-deep-equal": "^3.1.1", 91 | "fast-json-stable-stringify": "^2.0.0", 92 | "json-schema-traverse": "^0.4.1", 93 | "uri-js": "^4.2.2" 94 | } 95 | }, 96 | "ansi-colors": { 97 | "version": "4.1.1", 98 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 99 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 100 | "dev": true 101 | }, 102 | "ansi-regex": { 103 | "version": "5.0.0", 104 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 105 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 106 | "dev": true 107 | }, 108 | "ansi-styles": { 109 | "version": "3.2.1", 110 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 111 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 112 | "dev": true, 113 | "requires": { 114 | "color-convert": "^1.9.0" 115 | } 116 | }, 117 | "argparse": { 118 | "version": "1.0.10", 119 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 120 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 121 | "dev": true, 122 | "requires": { 123 | "sprintf-js": "~1.0.2" 124 | } 125 | }, 126 | "astral-regex": { 127 | "version": "2.0.0", 128 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", 129 | "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", 130 | "dev": true 131 | }, 132 | "balanced-match": { 133 | "version": "1.0.0", 134 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 135 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 136 | "dev": true 137 | }, 138 | "brace-expansion": { 139 | "version": "1.1.11", 140 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 141 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 142 | "dev": true, 143 | "requires": { 144 | "balanced-match": "^1.0.0", 145 | "concat-map": "0.0.1" 146 | } 147 | }, 148 | "callsites": { 149 | "version": "3.1.0", 150 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 151 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 152 | "dev": true 153 | }, 154 | "chalk": { 155 | "version": "4.1.0", 156 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 157 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 158 | "dev": true, 159 | "requires": { 160 | "ansi-styles": "^4.1.0", 161 | "supports-color": "^7.1.0" 162 | }, 163 | "dependencies": { 164 | "ansi-styles": { 165 | "version": "4.3.0", 166 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 167 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 168 | "dev": true, 169 | "requires": { 170 | "color-convert": "^2.0.1" 171 | } 172 | }, 173 | "color-convert": { 174 | "version": "2.0.1", 175 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 176 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 177 | "dev": true, 178 | "requires": { 179 | "color-name": "~1.1.4" 180 | } 181 | }, 182 | "color-name": { 183 | "version": "1.1.4", 184 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 185 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 186 | "dev": true 187 | }, 188 | "has-flag": { 189 | "version": "4.0.0", 190 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 191 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 192 | "dev": true 193 | }, 194 | "supports-color": { 195 | "version": "7.2.0", 196 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 197 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 198 | "dev": true, 199 | "requires": { 200 | "has-flag": "^4.0.0" 201 | } 202 | } 203 | } 204 | }, 205 | "color-convert": { 206 | "version": "1.9.3", 207 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 208 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 209 | "dev": true, 210 | "requires": { 211 | "color-name": "1.1.3" 212 | } 213 | }, 214 | "color-name": { 215 | "version": "1.1.3", 216 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 217 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 218 | "dev": true 219 | }, 220 | "concat-map": { 221 | "version": "0.0.1", 222 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 223 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 224 | "dev": true 225 | }, 226 | "cross-spawn": { 227 | "version": "7.0.3", 228 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 229 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 230 | "dev": true, 231 | "requires": { 232 | "path-key": "^3.1.0", 233 | "shebang-command": "^2.0.0", 234 | "which": "^2.0.1" 235 | } 236 | }, 237 | "debug": { 238 | "version": "4.3.1", 239 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 240 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 241 | "dev": true, 242 | "requires": { 243 | "ms": "2.1.2" 244 | } 245 | }, 246 | "deep-is": { 247 | "version": "0.1.3", 248 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 249 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 250 | "dev": true 251 | }, 252 | "doctrine": { 253 | "version": "3.0.0", 254 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 255 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 256 | "dev": true, 257 | "requires": { 258 | "esutils": "^2.0.2" 259 | } 260 | }, 261 | "emoji-regex": { 262 | "version": "8.0.0", 263 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 264 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 265 | "dev": true 266 | }, 267 | "enquirer": { 268 | "version": "2.3.6", 269 | "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", 270 | "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", 271 | "dev": true, 272 | "requires": { 273 | "ansi-colors": "^4.1.1" 274 | } 275 | }, 276 | "escape-string-regexp": { 277 | "version": "1.0.5", 278 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 279 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 280 | "dev": true 281 | }, 282 | "eslint": { 283 | "version": "7.19.0", 284 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.19.0.tgz", 285 | "integrity": "sha512-CGlMgJY56JZ9ZSYhJuhow61lMPPjUzWmChFya71Z/jilVos7mR/jPgaEfVGgMBY5DshbKdG8Ezb8FDCHcoMEMg==", 286 | "dev": true, 287 | "requires": { 288 | "@babel/code-frame": "^7.0.0", 289 | "@eslint/eslintrc": "^0.3.0", 290 | "ajv": "^6.10.0", 291 | "chalk": "^4.0.0", 292 | "cross-spawn": "^7.0.2", 293 | "debug": "^4.0.1", 294 | "doctrine": "^3.0.0", 295 | "enquirer": "^2.3.5", 296 | "eslint-scope": "^5.1.1", 297 | "eslint-utils": "^2.1.0", 298 | "eslint-visitor-keys": "^2.0.0", 299 | "espree": "^7.3.1", 300 | "esquery": "^1.2.0", 301 | "esutils": "^2.0.2", 302 | "file-entry-cache": "^6.0.0", 303 | "functional-red-black-tree": "^1.0.1", 304 | "glob-parent": "^5.0.0", 305 | "globals": "^12.1.0", 306 | "ignore": "^4.0.6", 307 | "import-fresh": "^3.0.0", 308 | "imurmurhash": "^0.1.4", 309 | "is-glob": "^4.0.0", 310 | "js-yaml": "^3.13.1", 311 | "json-stable-stringify-without-jsonify": "^1.0.1", 312 | "levn": "^0.4.1", 313 | "lodash": "^4.17.20", 314 | "minimatch": "^3.0.4", 315 | "natural-compare": "^1.4.0", 316 | "optionator": "^0.9.1", 317 | "progress": "^2.0.0", 318 | "regexpp": "^3.1.0", 319 | "semver": "^7.2.1", 320 | "strip-ansi": "^6.0.0", 321 | "strip-json-comments": "^3.1.0", 322 | "table": "^6.0.4", 323 | "text-table": "^0.2.0", 324 | "v8-compile-cache": "^2.0.3" 325 | }, 326 | "dependencies": { 327 | "eslint-utils": { 328 | "version": "2.1.0", 329 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", 330 | "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", 331 | "dev": true, 332 | "requires": { 333 | "eslint-visitor-keys": "^1.1.0" 334 | }, 335 | "dependencies": { 336 | "eslint-visitor-keys": { 337 | "version": "1.3.0", 338 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 339 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 340 | "dev": true 341 | } 342 | } 343 | }, 344 | "ignore": { 345 | "version": "4.0.6", 346 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 347 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 348 | "dev": true 349 | }, 350 | "regexpp": { 351 | "version": "3.1.0", 352 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", 353 | "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", 354 | "dev": true 355 | }, 356 | "semver": { 357 | "version": "7.3.4", 358 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", 359 | "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", 360 | "dev": true, 361 | "requires": { 362 | "lru-cache": "^6.0.0" 363 | } 364 | } 365 | } 366 | }, 367 | "eslint-config-defaults": { 368 | "version": "9.0.0", 369 | "resolved": "https://registry.npmjs.org/eslint-config-defaults/-/eslint-config-defaults-9.0.0.tgz", 370 | "integrity": "sha1-oJCtwTspNeP0OzzQSKknAWVOWtU=", 371 | "dev": true 372 | }, 373 | "eslint-config-scramjet": { 374 | "version": "3.0.0", 375 | "resolved": "https://registry.npmjs.org/eslint-config-scramjet/-/eslint-config-scramjet-3.0.0.tgz", 376 | "integrity": "sha512-VPFRJEcZ1BXWCNxn/dY0GqBcyEJDJJy7gy+J35o0fH2F8Nw9MTd6WIIjTFDSpayTXg4ojOa596BKRSdVc4+IgA==", 377 | "dev": true, 378 | "requires": { 379 | "eslint-config-defaults": "^9.0.0", 380 | "eslint-plugin-node": "^11.1.0" 381 | } 382 | }, 383 | "eslint-plugin-es": { 384 | "version": "3.0.1", 385 | "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", 386 | "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", 387 | "dev": true, 388 | "requires": { 389 | "eslint-utils": "^2.0.0", 390 | "regexpp": "^3.0.0" 391 | } 392 | }, 393 | "eslint-plugin-node": { 394 | "version": "11.1.0", 395 | "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", 396 | "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", 397 | "dev": true, 398 | "requires": { 399 | "eslint-plugin-es": "^3.0.0", 400 | "eslint-utils": "^2.0.0", 401 | "ignore": "^5.1.1", 402 | "minimatch": "^3.0.4", 403 | "resolve": "^1.10.1", 404 | "semver": "^6.1.0" 405 | } 406 | }, 407 | "eslint-scope": { 408 | "version": "5.1.1", 409 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 410 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 411 | "dev": true, 412 | "requires": { 413 | "esrecurse": "^4.3.0", 414 | "estraverse": "^4.1.1" 415 | } 416 | }, 417 | "eslint-utils": { 418 | "version": "2.1.0", 419 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", 420 | "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", 421 | "dev": true, 422 | "requires": { 423 | "eslint-visitor-keys": "^1.1.0" 424 | }, 425 | "dependencies": { 426 | "eslint-visitor-keys": { 427 | "version": "1.3.0", 428 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 429 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 430 | "dev": true 431 | } 432 | } 433 | }, 434 | "eslint-visitor-keys": { 435 | "version": "2.0.0", 436 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", 437 | "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", 438 | "dev": true 439 | }, 440 | "espree": { 441 | "version": "7.3.1", 442 | "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", 443 | "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", 444 | "dev": true, 445 | "requires": { 446 | "acorn": "^7.4.0", 447 | "acorn-jsx": "^5.3.1", 448 | "eslint-visitor-keys": "^1.3.0" 449 | }, 450 | "dependencies": { 451 | "eslint-visitor-keys": { 452 | "version": "1.3.0", 453 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 454 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 455 | "dev": true 456 | } 457 | } 458 | }, 459 | "esprima": { 460 | "version": "4.0.1", 461 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 462 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 463 | "dev": true 464 | }, 465 | "esquery": { 466 | "version": "1.3.1", 467 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", 468 | "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", 469 | "dev": true, 470 | "requires": { 471 | "estraverse": "^5.1.0" 472 | }, 473 | "dependencies": { 474 | "estraverse": { 475 | "version": "5.2.0", 476 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", 477 | "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", 478 | "dev": true 479 | } 480 | } 481 | }, 482 | "esrecurse": { 483 | "version": "4.3.0", 484 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 485 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 486 | "dev": true, 487 | "requires": { 488 | "estraverse": "^5.2.0" 489 | }, 490 | "dependencies": { 491 | "estraverse": { 492 | "version": "5.2.0", 493 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", 494 | "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", 495 | "dev": true 496 | } 497 | } 498 | }, 499 | "estraverse": { 500 | "version": "4.3.0", 501 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 502 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 503 | "dev": true 504 | }, 505 | "esutils": { 506 | "version": "2.0.3", 507 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 508 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 509 | "dev": true 510 | }, 511 | "fast-deep-equal": { 512 | "version": "3.1.3", 513 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 514 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 515 | "dev": true 516 | }, 517 | "fast-json-stable-stringify": { 518 | "version": "2.1.0", 519 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 520 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 521 | "dev": true 522 | }, 523 | "fast-levenshtein": { 524 | "version": "2.0.6", 525 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 526 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 527 | "dev": true 528 | }, 529 | "file-entry-cache": { 530 | "version": "6.0.0", 531 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", 532 | "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", 533 | "dev": true, 534 | "requires": { 535 | "flat-cache": "^3.0.4" 536 | } 537 | }, 538 | "flat-cache": { 539 | "version": "3.0.4", 540 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 541 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 542 | "dev": true, 543 | "requires": { 544 | "flatted": "^3.1.0", 545 | "rimraf": "^3.0.2" 546 | } 547 | }, 548 | "flatted": { 549 | "version": "3.1.1", 550 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", 551 | "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", 552 | "dev": true 553 | }, 554 | "fs.realpath": { 555 | "version": "1.0.0", 556 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 557 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 558 | "dev": true 559 | }, 560 | "function-bind": { 561 | "version": "1.1.1", 562 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 563 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 564 | "dev": true 565 | }, 566 | "functional-red-black-tree": { 567 | "version": "1.0.1", 568 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 569 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 570 | "dev": true 571 | }, 572 | "glob": { 573 | "version": "7.1.6", 574 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 575 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 576 | "dev": true, 577 | "requires": { 578 | "fs.realpath": "^1.0.0", 579 | "inflight": "^1.0.4", 580 | "inherits": "2", 581 | "minimatch": "^3.0.4", 582 | "once": "^1.3.0", 583 | "path-is-absolute": "^1.0.0" 584 | } 585 | }, 586 | "glob-parent": { 587 | "version": "5.1.1", 588 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 589 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 590 | "dev": true, 591 | "requires": { 592 | "is-glob": "^4.0.1" 593 | } 594 | }, 595 | "globals": { 596 | "version": "12.4.0", 597 | "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", 598 | "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", 599 | "dev": true, 600 | "requires": { 601 | "type-fest": "^0.8.1" 602 | } 603 | }, 604 | "has": { 605 | "version": "1.0.3", 606 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 607 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 608 | "dev": true, 609 | "requires": { 610 | "function-bind": "^1.1.1" 611 | } 612 | }, 613 | "has-flag": { 614 | "version": "3.0.0", 615 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 616 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 617 | "dev": true 618 | }, 619 | "ignore": { 620 | "version": "5.1.8", 621 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", 622 | "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", 623 | "dev": true 624 | }, 625 | "import-fresh": { 626 | "version": "3.3.0", 627 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 628 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 629 | "dev": true, 630 | "requires": { 631 | "parent-module": "^1.0.0", 632 | "resolve-from": "^4.0.0" 633 | } 634 | }, 635 | "imurmurhash": { 636 | "version": "0.1.4", 637 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 638 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 639 | "dev": true 640 | }, 641 | "inflight": { 642 | "version": "1.0.6", 643 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 644 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 645 | "dev": true, 646 | "requires": { 647 | "once": "^1.3.0", 648 | "wrappy": "1" 649 | } 650 | }, 651 | "inherits": { 652 | "version": "2.0.4", 653 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 654 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 655 | "dev": true 656 | }, 657 | "is-core-module": { 658 | "version": "2.2.0", 659 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", 660 | "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", 661 | "dev": true, 662 | "requires": { 663 | "has": "^1.0.3" 664 | } 665 | }, 666 | "is-extglob": { 667 | "version": "2.1.1", 668 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 669 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 670 | "dev": true 671 | }, 672 | "is-fullwidth-code-point": { 673 | "version": "3.0.0", 674 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 675 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 676 | "dev": true 677 | }, 678 | "is-glob": { 679 | "version": "4.0.1", 680 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 681 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 682 | "dev": true, 683 | "requires": { 684 | "is-extglob": "^2.1.1" 685 | } 686 | }, 687 | "isexe": { 688 | "version": "2.0.0", 689 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 690 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 691 | "dev": true 692 | }, 693 | "js-tokens": { 694 | "version": "4.0.0", 695 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 696 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 697 | "dev": true 698 | }, 699 | "js-yaml": { 700 | "version": "3.14.1", 701 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", 702 | "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", 703 | "dev": true, 704 | "requires": { 705 | "argparse": "^1.0.7", 706 | "esprima": "^4.0.0" 707 | } 708 | }, 709 | "json-schema-traverse": { 710 | "version": "0.4.1", 711 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 712 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 713 | "dev": true 714 | }, 715 | "json-stable-stringify-without-jsonify": { 716 | "version": "1.0.1", 717 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 718 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 719 | "dev": true 720 | }, 721 | "levn": { 722 | "version": "0.4.1", 723 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 724 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 725 | "dev": true, 726 | "requires": { 727 | "prelude-ls": "^1.2.1", 728 | "type-check": "~0.4.0" 729 | } 730 | }, 731 | "lodash": { 732 | "version": "4.17.20", 733 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 734 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", 735 | "dev": true 736 | }, 737 | "lru-cache": { 738 | "version": "6.0.0", 739 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 740 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 741 | "dev": true, 742 | "requires": { 743 | "yallist": "^4.0.0" 744 | } 745 | }, 746 | "minimatch": { 747 | "version": "3.0.4", 748 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 749 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 750 | "dev": true, 751 | "requires": { 752 | "brace-expansion": "^1.1.7" 753 | } 754 | }, 755 | "ms": { 756 | "version": "2.1.2", 757 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 758 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 759 | "dev": true 760 | }, 761 | "natural-compare": { 762 | "version": "1.4.0", 763 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 764 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 765 | "dev": true 766 | }, 767 | "once": { 768 | "version": "1.4.0", 769 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 770 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 771 | "dev": true, 772 | "requires": { 773 | "wrappy": "1" 774 | } 775 | }, 776 | "optionator": { 777 | "version": "0.9.1", 778 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 779 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 780 | "dev": true, 781 | "requires": { 782 | "deep-is": "^0.1.3", 783 | "fast-levenshtein": "^2.0.6", 784 | "levn": "^0.4.1", 785 | "prelude-ls": "^1.2.1", 786 | "type-check": "^0.4.0", 787 | "word-wrap": "^1.2.3" 788 | } 789 | }, 790 | "papaparse": { 791 | "version": "5.3.0", 792 | "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.3.0.tgz", 793 | "integrity": "sha512-Lb7jN/4bTpiuGPrYy4tkKoUS8sTki8zacB5ke1p5zolhcSE4TlWgrlsxjrDTbG/dFVh07ck7X36hUf/b5V68pg==", 794 | "dev": true 795 | }, 796 | "parent-module": { 797 | "version": "1.0.1", 798 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 799 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 800 | "dev": true, 801 | "requires": { 802 | "callsites": "^3.0.0" 803 | } 804 | }, 805 | "path-is-absolute": { 806 | "version": "1.0.1", 807 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 808 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 809 | "dev": true 810 | }, 811 | "path-key": { 812 | "version": "3.1.1", 813 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 814 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 815 | "dev": true 816 | }, 817 | "path-parse": { 818 | "version": "1.0.6", 819 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 820 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 821 | "dev": true 822 | }, 823 | "prelude-ls": { 824 | "version": "1.2.1", 825 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 826 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 827 | "dev": true 828 | }, 829 | "progress": { 830 | "version": "2.0.3", 831 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 832 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 833 | "dev": true 834 | }, 835 | "punycode": { 836 | "version": "2.1.1", 837 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 838 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 839 | "dev": true 840 | }, 841 | "regexpp": { 842 | "version": "3.1.0", 843 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", 844 | "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", 845 | "dev": true 846 | }, 847 | "require-from-string": { 848 | "version": "2.0.2", 849 | "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", 850 | "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", 851 | "dev": true 852 | }, 853 | "rereadable-stream": { 854 | "version": "1.4.5", 855 | "resolved": "https://registry.npmjs.org/rereadable-stream/-/rereadable-stream-1.4.5.tgz", 856 | "integrity": "sha512-hgVjbKq65Ynx4FAYTZaNjy0Oy9z+VPEmSYE1087k+P0dGbKUK+ZtFmIoMHXZ7TdjnR8u5y8/ecaDVbpypD6X1w==", 857 | "dev": true 858 | }, 859 | "resolve": { 860 | "version": "1.19.0", 861 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz", 862 | "integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==", 863 | "dev": true, 864 | "requires": { 865 | "is-core-module": "^2.1.0", 866 | "path-parse": "^1.0.6" 867 | } 868 | }, 869 | "resolve-from": { 870 | "version": "4.0.0", 871 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 872 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 873 | "dev": true 874 | }, 875 | "rimraf": { 876 | "version": "3.0.2", 877 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 878 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 879 | "dev": true, 880 | "requires": { 881 | "glob": "^7.1.3" 882 | } 883 | }, 884 | "scramjet": { 885 | "version": "4.35.11", 886 | "resolved": "https://registry.npmjs.org/scramjet/-/scramjet-4.35.11.tgz", 887 | "integrity": "sha512-bVWetDhj0FNmUZpvMpNhikSzjfOe6kKpSTu6E4lhbqQvnYiataRnWwgFeGcYtfRSCz0QmMiQcTjNbriAYI7xZg==", 888 | "dev": true, 889 | "requires": { 890 | "papaparse": "^5.3.0", 891 | "rereadable-stream": "^1.4.5", 892 | "scramjet-core": "^4.31.9" 893 | } 894 | }, 895 | "scramjet-core": { 896 | "version": "4.31.11", 897 | "resolved": "https://registry.npmjs.org/scramjet-core/-/scramjet-core-4.31.11.tgz", 898 | "integrity": "sha512-hKEZKc+WR1N0RGTLAtYes+9w4jJIzE+DWV9oGXpd5RcpO+KFMzCotj8KXbc89PRBi2EKAsHRpOXoWBWZDhJc6A==", 899 | "dev": true 900 | }, 901 | "semver": { 902 | "version": "6.3.0", 903 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 904 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 905 | "dev": true 906 | }, 907 | "shebang-command": { 908 | "version": "2.0.0", 909 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 910 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 911 | "dev": true, 912 | "requires": { 913 | "shebang-regex": "^3.0.0" 914 | } 915 | }, 916 | "shebang-regex": { 917 | "version": "3.0.0", 918 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 919 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 920 | "dev": true 921 | }, 922 | "slice-ansi": { 923 | "version": "4.0.0", 924 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", 925 | "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", 926 | "dev": true, 927 | "requires": { 928 | "ansi-styles": "^4.0.0", 929 | "astral-regex": "^2.0.0", 930 | "is-fullwidth-code-point": "^3.0.0" 931 | }, 932 | "dependencies": { 933 | "ansi-styles": { 934 | "version": "4.3.0", 935 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 936 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 937 | "dev": true, 938 | "requires": { 939 | "color-convert": "^2.0.1" 940 | } 941 | }, 942 | "color-convert": { 943 | "version": "2.0.1", 944 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 945 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 946 | "dev": true, 947 | "requires": { 948 | "color-name": "~1.1.4" 949 | } 950 | }, 951 | "color-name": { 952 | "version": "1.1.4", 953 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 954 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 955 | "dev": true 956 | } 957 | } 958 | }, 959 | "sprintf-js": { 960 | "version": "1.0.3", 961 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 962 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 963 | "dev": true 964 | }, 965 | "string-width": { 966 | "version": "4.2.0", 967 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 968 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 969 | "dev": true, 970 | "requires": { 971 | "emoji-regex": "^8.0.0", 972 | "is-fullwidth-code-point": "^3.0.0", 973 | "strip-ansi": "^6.0.0" 974 | } 975 | }, 976 | "strip-ansi": { 977 | "version": "6.0.0", 978 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 979 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 980 | "dev": true, 981 | "requires": { 982 | "ansi-regex": "^5.0.0" 983 | } 984 | }, 985 | "strip-json-comments": { 986 | "version": "3.1.1", 987 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 988 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 989 | "dev": true 990 | }, 991 | "supports-color": { 992 | "version": "5.5.0", 993 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 994 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 995 | "dev": true, 996 | "requires": { 997 | "has-flag": "^3.0.0" 998 | } 999 | }, 1000 | "table": { 1001 | "version": "6.0.7", 1002 | "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", 1003 | "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", 1004 | "dev": true, 1005 | "requires": { 1006 | "ajv": "^7.0.2", 1007 | "lodash": "^4.17.20", 1008 | "slice-ansi": "^4.0.0", 1009 | "string-width": "^4.2.0" 1010 | }, 1011 | "dependencies": { 1012 | "ajv": { 1013 | "version": "7.0.4", 1014 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.4.tgz", 1015 | "integrity": "sha512-xzzzaqgEQfmuhbhAoqjJ8T/1okb6gAzXn/eQRNpAN1AEUoHJTNF9xCDRTtf/s3SKldtZfa+RJeTs+BQq+eZ/sw==", 1016 | "dev": true, 1017 | "requires": { 1018 | "fast-deep-equal": "^3.1.1", 1019 | "json-schema-traverse": "^1.0.0", 1020 | "require-from-string": "^2.0.2", 1021 | "uri-js": "^4.2.2" 1022 | } 1023 | }, 1024 | "json-schema-traverse": { 1025 | "version": "1.0.0", 1026 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", 1027 | "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", 1028 | "dev": true 1029 | } 1030 | } 1031 | }, 1032 | "text-table": { 1033 | "version": "0.2.0", 1034 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1035 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1036 | "dev": true 1037 | }, 1038 | "type-check": { 1039 | "version": "0.4.0", 1040 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 1041 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 1042 | "dev": true, 1043 | "requires": { 1044 | "prelude-ls": "^1.2.1" 1045 | } 1046 | }, 1047 | "type-fest": { 1048 | "version": "0.8.1", 1049 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", 1050 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", 1051 | "dev": true 1052 | }, 1053 | "uri-js": { 1054 | "version": "4.4.1", 1055 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1056 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1057 | "dev": true, 1058 | "requires": { 1059 | "punycode": "^2.1.0" 1060 | } 1061 | }, 1062 | "v8-compile-cache": { 1063 | "version": "2.2.0", 1064 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", 1065 | "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", 1066 | "dev": true 1067 | }, 1068 | "which": { 1069 | "version": "2.0.2", 1070 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1071 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1072 | "dev": true, 1073 | "requires": { 1074 | "isexe": "^2.0.0" 1075 | } 1076 | }, 1077 | "word-wrap": { 1078 | "version": "1.2.3", 1079 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 1080 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 1081 | "dev": true 1082 | }, 1083 | "wrappy": { 1084 | "version": "1.0.2", 1085 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1086 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1087 | "dev": true 1088 | }, 1089 | "yallist": { 1090 | "version": "4.0.0", 1091 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1092 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 1093 | "dev": true 1094 | } 1095 | } 1096 | } 1097 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rw-stream", 3 | "version": "0.4.0", 4 | "description": "A simple stream that allows reading and writing to the same file at the same time.\u001b[H\u001b[C\u001b[F", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node test" 8 | }, 9 | "author": "Signicode ", 10 | "license": "MIT", 11 | "homepage": "https://github.com/signicode/rw-stream", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/signicode/rw-stream.git" 15 | }, 16 | "engines": { 17 | "node": ">=8.6.0" 18 | }, 19 | "keywords": [ 20 | "stream", 21 | "streams", 22 | "async", 23 | "await", 24 | "transform", 25 | "replace", 26 | "fs", 27 | "write", 28 | "pipe" 29 | ], 30 | "devDependencies": { 31 | "eslint": "^7.19.0", 32 | "eslint-config-scramjet": "^3.0.0", 33 | "scramjet": "^4.35.11" 34 | }, 35 | "dependencies": {} 36 | } 37 | -------------------------------------------------------------------------------- /test/case/contract.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable node/no-unpublished-require */ 2 | const {promisify} = require("util"); 3 | const {StringStream} = require("scramjet"); 4 | const rw = require("../../"); 5 | const {copyFile, readFile} = require("fs"); 6 | 7 | module.exports = async (assert) => { 8 | const testFile = `${__dirname}/test.contract.tmp`; 9 | await promisify(copyFile)(`${__dirname}/test.txt`, testFile); 10 | const {readStream, writeStream} = await rw(testFile); 11 | 12 | const out = StringStream.from(readStream) 13 | .lines() 14 | .filter(x => !isNaN(+x) && +x % 2) 15 | .map(x => `${+x+10}\n`); 16 | 17 | out.pipe(writeStream); 18 | 19 | const fin = new Promise(res => writeStream.on("finish", res)); 20 | 21 | await out.whenEnd(); 22 | await fin; 23 | 24 | const contents = await promisify(readFile)(testFile, {encoding: "utf-8"}); 25 | assert.strictEqual(contents, "11\n13\n15\n17\n19\n"); 26 | 27 | console.log("contract test done"); 28 | }; 29 | -------------------------------------------------------------------------------- /test/case/empty.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable node/no-unpublished-require */ 2 | const {promisify} = require("util"); 3 | const {Transform} = require("stream"); 4 | const rw = require("../../"); 5 | const {copyFile, readFile} = require("fs"); 6 | 7 | module.exports = async (assert) => { 8 | const testFile = `${__dirname}/test.empty.tmp`; 9 | await promisify(copyFile)(`${__dirname}/test.txt`, testFile); 10 | const {readStream, writeStream} = await rw(testFile); 11 | 12 | await new Promise((resolve, reject) => { 13 | readStream 14 | .pipe(new Transform({ 15 | transform(chunk, encoding, cb) { 16 | return cb(); 17 | }, 18 | flush (cb) { 19 | return cb(null, ""); 20 | } 21 | })) 22 | .pipe(writeStream) 23 | .on("finish", resolve) 24 | .on("error", reject) 25 | }); 26 | 27 | const contents = await promisify(readFile)(testFile, {encoding: "utf-8"}); 28 | assert.strictEqual(contents, ""); 29 | 30 | console.log("empty test done"); 31 | }; 32 | -------------------------------------------------------------------------------- /test/case/error.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable node/no-unpublished-require */ 2 | const {promisify} = require("util"); 3 | const {Transform} = require("stream"); 4 | const rw = require("../../"); 5 | const {writeFile, unlink} = require("fs"); 6 | 7 | module.exports = async (assert) => { 8 | const testFile = `${__dirname}/test.error.tmp`; 9 | await promisify(writeFile)( 10 | testFile, "test".split("").join("\n").repeat(40000000) 11 | ); 12 | const {readStream, writeStream} = await rw(testFile); 13 | 14 | let counter = 0; 15 | const transformStream = ( 16 | new Transform({ 17 | transform(chunk, encoding, cb) { 18 | if(counter++ > 1) { 19 | readStream.push = () => {throw new Error("sth")}; 20 | } 21 | return cb(null, chunk); 22 | } 23 | }) 24 | ); 25 | 26 | await assert.rejects( 27 | () => new Promise((resolve, reject) => { 28 | readStream 29 | .on("error", err => { 30 | transformStream.destroy(); 31 | writeStream.destroy(); 32 | return reject(err); 33 | }) 34 | .pipe(transformStream) 35 | .on("error", err => { 36 | readStream.destroy(); 37 | writeStream.destroy(); 38 | return reject(err); 39 | }) 40 | .pipe(writeStream) 41 | .on("finish", resolve) 42 | }), 43 | err => { 44 | return ( 45 | readStream.destroyed 46 | && 47 | transformStream.destroyed 48 | && 49 | writeStream.destroyed 50 | ); 51 | }, 52 | "Undestroyed stream(s) detected. Memory leaks may occur" 53 | ) 54 | 55 | unlink(testFile, () => console.log("error test done")); 56 | }; 57 | -------------------------------------------------------------------------------- /test/case/grow.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable node/no-unpublished-require */ 2 | const {promisify} = require("util"); 3 | const {StringStream} = require("scramjet"); 4 | const rw = require("../../"); 5 | const {copyFile, readFile} = require("fs"); 6 | 7 | module.exports = async (assert) => { 8 | const testFile = `${__dirname}/test.grow.tmp`; 9 | await promisify(copyFile)(`${__dirname}/test.txt`, testFile); 10 | const {readStream, writeStream} = await rw(testFile); 11 | 12 | const out = StringStream.from(readStream) 13 | .lines() 14 | .map(x => +x + 1) 15 | .endWith("1") 16 | .map(x => `${x+10}\n`); 17 | 18 | out.pipe(writeStream); 19 | 20 | const fin = new Promise(res => writeStream.on("finish", res)); 21 | 22 | await out.whenEnd(); 23 | 24 | await fin; 25 | 26 | const contents = await promisify(readFile)(testFile, {encoding: "utf-8"}); 27 | assert.strictEqual(contents, "12\n13\n14\n15\n16\n17\n18\n19\n20\n21\n11\n"); 28 | 29 | console.log("grow test done"); 30 | }; 31 | -------------------------------------------------------------------------------- /test/case/test.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 10 | 10 11 | -------------------------------------------------------------------------------- /test/grow.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable node/no-unpublished-require */ 2 | const {StringStream} = require("scramjet"); 3 | const rw = require("../"); 4 | 5 | (async () => { 6 | const {readStream, writeStream} = await rw(`${__dirname}/grow.txt`); 7 | 8 | const out = StringStream.from(readStream) 9 | .lines() 10 | .map(x => +x + 1) 11 | .endWith("1") 12 | .map(x => `${3*x}\n${x+10}\n`); 13 | 14 | out.pipe(writeStream); 15 | 16 | await out.whenEnd(); 17 | console.log("read all"); 18 | 19 | })(); 20 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable node/no-unpublished-require */ 2 | const assert = require("assert"); 3 | 4 | (async () => { 5 | console.log("Testing"); 6 | await require("./case/grow")(assert); 7 | await require("./case/contract")(assert); 8 | await require("./case/empty")(assert); 9 | await require("./case/error")(assert); 10 | console.log("Tests done"); 11 | })().catch(e => { 12 | console.error(e.stack); 13 | process.exit(e.exitCode || 31); 14 | }); 15 | --------------------------------------------------------------------------------