├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── test.yml ├── .gitignore ├── .npmignore ├── .prettierrc ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── example.js ├── package-lock.json ├── package.json └── utilities.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | end_of_line = lf 6 | charset = utf-8 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [{*.js,*.mjs,*.ts,*.json,*.yml}] 11 | indent_size = 2 12 | indent_style = space 13 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["metarhia", "plugin:prettier/recommended"], 3 | "env": { 4 | "browser": true, 5 | "es6": true, 6 | "node": true 7 | }, 8 | "parserOptions": { 9 | "ecmaVersion": 2020 10 | }, 11 | "rules": { 12 | "arrow-parens": "off", 13 | "comma-dangle": "off", 14 | "handle-callback-err": "off", 15 | "consistent-return": "off", 16 | "no-invalid-this": "off" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * -text 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: tshemsedinov 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: usage example or test. 14 | 15 | **Expected behavior** 16 | A clear and concise description of what you expected. 17 | 18 | **Screenshots** 19 | If applicable, add screenshots to help explain your problem. 20 | 21 | **Desktop (please complete the following information):** 22 | 23 | - OS: [e.g. Fedora 30 64-bit] 24 | - Node.js version [e.g. 14.15.1] 25 | - MySQL version 26 | 27 | **Additional context** 28 | Add any other context about the problem here. 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | - [ ] tests and linter show no problems (`npm t`) 8 | - [ ] tests are added/updated for bug fixes and new features 9 | - [ ] code is properly formatted (`npm run fmt`) 10 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Testing CI 2 | 3 | on: pull_request 4 | 5 | jobs: 6 | build: 7 | runs-on: ${{ matrix.os }} 8 | 9 | strategy: 10 | matrix: 11 | node: 12 | - 14 13 | - 16 14 | - 18 15 | - 19 16 | os: 17 | - ubuntu-latest 18 | - windows-latest 19 | - macos-latest 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - name: Use Node.js ${{ matrix.node }} 24 | uses: actions/setup-node@v1 25 | with: 26 | node-version: ${{ matrix.node }} 27 | - uses: actions/cache@v2 28 | with: 29 | path: ~/.npm 30 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} 31 | restore-keys: | 32 | ${{ runner.os }}-node- 33 | - run: npm ci 34 | - run: npm test 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "es5", 4 | "overrides": [ 5 | { 6 | "files": ".prettierrc", 7 | "options": { "parser": "json" } 8 | } 9 | ], 10 | "arrowParens": "avoid" 11 | } 12 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | - [Issues](#issues) 4 | - [Pull Requests](#pull-requests) 5 | 6 | ## Issues 7 | 8 | There are two reasons to open an issue: 9 | 10 | - Bug report 11 | - Feature request 12 | 13 | For bug reports please describe the bug with a clear and concise description, 14 | steps to reproduce the behavior (usage example or test), expected behavior, 15 | provide OS and Node.js version, you can upload screenshots and any additional 16 | context for better understanding. 17 | 18 | Please don't open an issue to ask questions. 19 | 20 | Issues on GitHub are intended to be related to problems and feature requests 21 | so we recommend not using this medium to ask them here grin. Thanks for 22 | understanding! 23 | 24 | If you have a question, please check out our support groups and channels for 25 | developers community: 26 | 27 | Telegram: 28 | 29 | - Channel for Metarhia community: https://t.me/metarhia 30 | - Group for Metarhia technology stack community: https://t.me/metaserverless 31 | - Group for NodeUA community: https://t.me/nodeua 32 | 33 | ## Pull Requests 34 | 35 | Before open pull request please follow checklist: 36 | 37 | - [ ] tests and linter show no problems (`npm t`) 38 | - [ ] tests are added/updated for bug fixes and new features 39 | - [ ] code is properly formatted (`npm run fmt`) 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2013-2023 Impress Application Server contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node MySql Utilities 2 | 3 | [Utilities](https://github.com/tshemsedinov/node-mysql-utilities) for 4 | [node-mysql driver](https://github.com/felixge/node-mysql) with specialized 5 | result types, introspection and other helpful functionality for 6 | [node.js](http://nodejs.org). Initially this utilities were part of 7 | [Impress](https://npmjs.org/package/impress) Application Server and 8 | extracted separately for use with other frameworks. 9 | 10 | [![CI Status](https://github.com/tshemsedinov/node-mysql-utilities/workflows/Testing%20CI/badge.svg)](https://github.com/tshemsedinov/node-mysql-utilities/actions?query=workflow%3A%22Testing+CI%22+branch%3Amaster) 11 | [![NPM Version](https://badge.fury.io/js/mysql-utilities.svg)](https://badge.fury.io/js/mysql-utilities) 12 | [![NPM Downloads/Month](https://img.shields.io/npm/dm/mysql-utilities.svg)](https://www.npmjs.com/package/mysql-utilities) 13 | [![NPM Downloads](https://img.shields.io/npm/dt/mysql-utilities.svg)](https://www.npmjs.com/package/mysql-utilities) 14 | 15 | ![impress logo](http://habrastorage.org/storage3/747/830/b17/747830b1782bd95f28b8d05eff8e05d9.jpg) 16 | 17 | ## Installation 18 | 19 | ```bash 20 | $ npm install mysql-utilities 21 | ``` 22 | 23 | ## Features 24 | 25 | - MySQL Data Access Methods 26 | - Query selecting single row: connection.queryRow(sql, values, callback) 27 | - Query selecting scalar (single value): connection.queryValue(sql, values, callback) 28 | - Query selecting column into array: connection.queryCol(sql, values, callback) 29 | - Query selecting hash of records: connection.queryHash(sql, values, callback) 30 | - Query selecting key/value hash: connection.queryKeyValue(sql, values, callback) 31 | - MySQL Introspection Methods 32 | - Get primary key metadata: connection.primary(table, callback) 33 | - Get foreign key metadata: connection.foreign(table, callback) 34 | - Get table constraints metadata: connection.constraints(table, callback) 35 | - Get table fields metadata: connection.fields(table, callback) 36 | - Get connection databases array: connection.databases(callback) 37 | - Get database tables list for current db: connection.tables(callback) 38 | - Get database tables list for given db: connection.databaseTables(database, callback) 39 | - Get table metadata: connection.tableInfo(table, callback) 40 | - Get table indexes metadata: connection.indexes(table, callback) 41 | - Get server process list: connection.processes(callback) 42 | - Get server global variables: connection.globalVariables(callback) 43 | - Get server global status: connection.globalStatus(callback) 44 | - Get database users: connection.users(callback) 45 | - MySQL SQL Statements Autogenerating Methods 46 | - Selecting record(s): connection.select(table, whereFilter, callback) 47 | - Inserting record: connection.insert(table, row, callback) 48 | - Updating record: connection.update(table, row, where, callback) 49 | - Inserting or selecting record: connection.upsert(table, row, callback) 50 | - Count records with filter: connection.count(table, whereFilter, callback) 51 | - Delete record(s): connection.delete(table, whereFilter, callback) 52 | - Events 53 | - Catch any query execution: connection.on('query', function(err, res, fields, query) {}); 54 | - Catch errors: connection.on('error', function(err, query) {}); 55 | - Catch slow query execution: connection.on('slow', function(err, res, fields, query, executionTime) {}); 56 | 57 | ## Initialization 58 | 59 | Utilities can be attached to connection using mix-ins: 60 | 61 | ```js 62 | // Library dependencies 63 | const mysql = require('mysql'); 64 | const mysqlUtilities = require('mysql-utilities'); 65 | 66 | const connection = mysql.createConnection({ 67 | host: 'localhost', 68 | user: 'userName', 69 | password: 'secret', 70 | database: 'databaseName', 71 | }); 72 | 73 | connection.connect(); 74 | 75 | // Mix-in for Data Access Methods and SQL Autogenerating Methods 76 | mysqlUtilities.upgrade(connection); 77 | 78 | // Mix-in for Introspection Methods 79 | mysqlUtilities.introspection(connection); 80 | 81 | // Do something using utilities 82 | connection.queryRow( 83 | 'SELECT * FROM _Language where LanguageId=?', 84 | [3], 85 | (err, row) => { 86 | console.dir({ queryRow: row }); 87 | } 88 | ); 89 | 90 | // Release connection 91 | connection.end(); 92 | ``` 93 | 94 | ## Examples 95 | 96 | Single row selection: connection.queryRow(sql, values, callback) returns hash as callback second parameter, field names becomes hash keys. 97 | 98 | ```js 99 | connection.queryRow( 100 | 'SELECT * FROM Language where LanguageId=?', 101 | [3], 102 | (err, row) => { 103 | console.dir({ queryRow: row }); 104 | } 105 | ); 106 | ``` 107 | 108 | Output: 109 | 110 | ```js 111 | queryRow: { 112 | LanguageId: 3, 113 | LanguageName: 'Russian', 114 | LanguageSign: 'ru', 115 | LanguageISO: 'ru', 116 | Caption: 'Русский' 117 | } 118 | ``` 119 | 120 | Single value selection: connection.queryValue(sql, values, callback) returns single value as callback second parameter (instead of array in array). For example, for Id selection by name with LIMIT 1 or count(\*), max(field) etc. 121 | 122 | ```js 123 | connection.queryValue( 124 | 'SELECT LanguageName FROM Language where LanguageId=?', 125 | [8], 126 | (err, name) => { 127 | console.dir({ queryValue: name }); 128 | } 129 | ); 130 | ``` 131 | 132 | Output: 133 | 134 | ```js 135 | { 136 | queryValue: 'Italiano'; 137 | } 138 | ``` 139 | 140 | Single column selection: connection.queryCol(sql, values, callback) returns array as callback second parameter. 141 | 142 | ```js 143 | connection.queryCol('SELECT LanguageSign FROM Language', [], (err, result) => { 144 | console.dir({ queryCal: result }); 145 | }); 146 | ``` 147 | 148 | Output: 149 | 150 | ```js 151 | queryArray: ['de', 'en', 'es', 'fr', 'it', 'pl', 'ru', 'ua']; 152 | ``` 153 | 154 | Hash selection: connection.queryHash(sql, values, callback) returns hash as callback second parameter, hash keyed by first field values from SQL statement. 155 | 156 | ```js 157 | connection.queryHash( 158 | 'SELECT LanguageSign, LanguageId, LanguageName, Caption, LanguageISO FROM Language', 159 | [], 160 | (err, result) => { 161 | console.dir({ queryHash: result }); 162 | } 163 | ); 164 | ``` 165 | 166 | Output: 167 | 168 | ```js 169 | queryHash: { 170 | en: { 171 | LanguageSign: 'en', 172 | LanguageId: 2, 173 | LanguageName: 'English', 174 | Caption: 'Английский', 175 | LanguageISO: 'en' }, 176 | ru: { 177 | LanguageSign: 'ru', 178 | LanguageId: 3, 179 | LanguageName: 'Russian', 180 | Caption: 'Русский', 181 | LanguageISO: 'ru' }, 182 | de: { 183 | LanguageSign: 'de', 184 | LanguageId: 7, 185 | LanguageName: 'Deutsch', 186 | Caption: 'Немецкий', 187 | LanguageISO: 'de' }, 188 | it: { 189 | LanguageSign: 'it', 190 | LanguageId: 8, 191 | LanguageName: 'Italiano', 192 | Caption: 'Итальянский', 193 | LanguageISO: 'it' 194 | } 195 | } 196 | ``` 197 | 198 | Key/value pair selection: connection.queryKeyValue(sql, values, callback) returns hash as callback second parameter, hash keyed by first field, values filled by second field. 199 | 200 | ```js 201 | connection.queryKeyValue( 202 | 'SELECT LanguageISO, LanguageName FROM Language', 203 | [], 204 | (err, keyValue) => { 205 | console.dir({ queryKeyValue: keyValue }); 206 | } 207 | ); 208 | ``` 209 | 210 | Output: 211 | 212 | ```js 213 | keyValue: { 214 | en: 'English', 215 | ru: 'Russian', 216 | uk: 'Ukrainian', 217 | es: 'Espanol', 218 | fr: 'Francais', 219 | de: 'Deutsch', 220 | it: 'Italiano', 221 | pl: 'Poliski' 222 | } 223 | ``` 224 | 225 | Get primary key list with metadata: connection.primary(table, callback) returns metadata as callback second parameter. 226 | 227 | ```js 228 | connection.primary('Language', (err, primary) => { 229 | console.dir({ primary }); 230 | }); 231 | ``` 232 | 233 | Output: 234 | 235 | ```js 236 | primary: { 237 | Table: 'language', 238 | Non_unique: 0, 239 | Key_name: 'PRIMARY', 240 | Seq_in_index: 1, 241 | Column_name: 'LanguageId', 242 | Collation: 'A', 243 | Cardinality: 9, 244 | Sub_part: null, 245 | Packed: null, 246 | Null: '', 247 | Index_type: 'BTREE', 248 | Comment: '', 249 | Index_comment: '' 250 | } 251 | ``` 252 | 253 | Get foreign key list with metadata: connection.foreign(table, callback) returns metadata as callback second parameter. 254 | 255 | ```js 256 | connection.foreign('TemplateCaption', (err, foreign) => { 257 | console.dir({ foreign }); 258 | }); 259 | ``` 260 | 261 | Output: 262 | 263 | ```js 264 | foreign: { 265 | fkTemplateCaptionLanguage: { 266 | CONSTRAINT_NAME: 'fkTemplateCaptionLanguage', 267 | COLUMN_NAME: 'LanguageId', 268 | ORDINAL_POSITION: 1, 269 | POSITION_IN_UNIQUE_CONSTRAINT: 1, 270 | REFERENCED_TABLE_NAME: 'language', 271 | REFERENCED_COLUMN_NAME: 'LanguageId' }, 272 | fkTemplateCaptionTemplate: { 273 | CONSTRAINT_NAME: 'fkTemplateCaptionTemplate', 274 | COLUMN_NAME: 'TemplateId', 275 | ORDINAL_POSITION: 1, 276 | POSITION_IN_UNIQUE_CONSTRAINT: 1, 277 | REFERENCED_TABLE_NAME: 'template', 278 | REFERENCED_COLUMN_NAME: 'TemplateId' 279 | } 280 | } 281 | ``` 282 | 283 | Referential constraints list with metadata: connection.constraints(table, callback). 284 | 285 | ```js 286 | connection.constraints('TemplateCaption', (err, constraints) => { 287 | console.dir({ constraints }); 288 | }); 289 | ``` 290 | 291 | Output: 292 | 293 | ```js 294 | constraints: { 295 | fkTemplateCaptionLanguage: { 296 | CONSTRAINT_NAME: 'fkTemplateCaptionLanguage', 297 | UNIQUE_CONSTRAINT_NAME: 'PRIMARY', 298 | REFERENCED_TABLE_NAME: 'Language', 299 | MATCH_OPTION: 'NONE', 300 | UPDATE_RULE: 'RESTRICT', 301 | DELETE_RULE: 'CASCADE' }, 302 | fkTemplateCaptionTemplate: { 303 | CONSTRAINT_NAME: 'fkTemplateCaptionTemplate', 304 | UNIQUE_CONSTRAINT_NAME: 'PRIMARY', 305 | REFERENCED_TABLE_NAME: 'Template', 306 | MATCH_OPTION: 'NONE', 307 | UPDATE_RULE: 'RESTRICT', 308 | DELETE_RULE: 'CASCADE' 309 | } 310 | } 311 | ``` 312 | 313 | Get table fields with metadata: connection.fields(table, callback). 314 | 315 | ```js 316 | connection.fields('Language', (err, fields) => { 317 | console.dir({ fields }); 318 | }); 319 | ``` 320 | 321 | Output: 322 | 323 | ```js 324 | fields: { 325 | LanguageId: { 326 | Field: 'LanguageId', 327 | Type: 'int(10) unsigned', 328 | Collation: null, 329 | Null: 'NO', 330 | Key: 'PRI', 331 | Default: null, 332 | Extra: 'auto_increment', 333 | Privileges: 'select,insert,update,references', 334 | Comment: 'Id(EN),Код(RU)' }, 335 | LanguageName: { 336 | Field: 'LanguageName', 337 | Type: 'varchar(32)', 338 | Collation: 'utf8_general_ci', 339 | Null: 'NO', 340 | Key: 'UNI', 341 | Default: null, 342 | Extra: '', 343 | Privileges: 'select,insert,update,references', 344 | Comment: 'Name(EN),Имя(RU)' 345 | }, ... 346 | } 347 | ``` 348 | 349 | Get database list for current connection: connection.databases(callback). 350 | 351 | ```js 352 | connection.databases((err, databases) => { 353 | console.dir({ databases }); 354 | }); 355 | ``` 356 | 357 | Output: 358 | 359 | ```js 360 | databases: [ 361 | 'information_schema', 362 | 'mezha', 363 | 'mysql', 364 | 'performance_schema', 365 | 'test', 366 | ]; 367 | ``` 368 | 369 | Get table list for current database: connection.tables(callback). 370 | 371 | ```js 372 | connection.tables((err, tables) => { 373 | console.dir({ tables }); 374 | }); 375 | ``` 376 | 377 | Output: 378 | 379 | ```js 380 | tables: { 381 | Language: { 382 | TABLE_NAME: 'Language', 383 | TABLE_TYPE: 'BASE TABLE', 384 | ENGINE: 'InnoDB', 385 | VERSION: 10, 386 | ROW_FORMAT: 'Compact', 387 | TABLE_ROWS: 9, 388 | AVG_ROW_LENGTH: 1820, 389 | DATA_LENGTH: 16384, 390 | MAX_DATA_LENGTH: 0, 391 | INDEX_LENGTH: 49152, 392 | DATA_FREE: 8388608, 393 | AUTO_INCREMENT: 10, 394 | CREATE_TIME: Mon Jul 15 2013 03:06:08 GMT+0300 (Финляндия (лето)), 395 | UPDATE_TIME: null, 396 | CHECK_TIME: null, 397 | TABLE_COLLATION: 'utf8_general_ci', 398 | CHECKSUM: null, 399 | CREATE_OPTIONS: '', 400 | TABLE_COMMENT: '_Language:Languages(EN),Языки(RU)' 401 | }, ... 402 | } 403 | ``` 404 | 405 | Get table list for specified database: connection.databaseTables(database, callback). 406 | 407 | ```js 408 | connection.databaseTables('databaseName', (err, tables) => { 409 | console.dir({ databaseTables: tables }); 410 | }); 411 | ``` 412 | 413 | Output: 414 | 415 | ```js 416 | tables: { 417 | Language: { 418 | TABLE_NAME: 'Language', 419 | TABLE_TYPE: 'BASE TABLE', 420 | ENGINE: 'InnoDB', 421 | VERSION: 10, 422 | ROW_FORMAT: 'Compact', 423 | TABLE_ROWS: 9, 424 | AVG_ROW_LENGTH: 1820, 425 | DATA_LENGTH: 16384, 426 | MAX_DATA_LENGTH: 0, 427 | INDEX_LENGTH: 49152, 428 | DATA_FREE: 8388608, 429 | AUTO_INCREMENT: 10, 430 | CREATE_TIME: Mon Jul 15 2013 03:06:08 GMT+0300 (Финляндия (лето)), 431 | UPDATE_TIME: null, 432 | CHECK_TIME: null, 433 | TABLE_COLLATION: 'utf8_general_ci', 434 | CHECKSUM: null, 435 | CREATE_OPTIONS: '', 436 | TABLE_COMMENT: '_Language:Languages(EN),Языки(RU)' 437 | }, ... 438 | } 439 | ``` 440 | 441 | Get table metadata: connection.tableInfo(table, callback). 442 | 443 | ```js 444 | connection.tableInfo('Language', (err, info) => { 445 | console.dir({ tableInfo: info }); 446 | }); 447 | ``` 448 | 449 | Output: 450 | 451 | ```js 452 | tableInfo: { 453 | Name: 'language', 454 | Engine: 'InnoDB', 455 | Version: 10, 456 | Row_format: 'Compact', 457 | Rows: 9, 458 | Avg_row_length: 1820, 459 | Data_length: 16384, 460 | Max_data_length: 0, 461 | Index_length: 49152, 462 | Data_free: 9437184, 463 | Auto_increment: 10, 464 | Create_time: Mon Jul 15 2013 03:06:08 GMT+0300 (Финляндия (лето)), 465 | Update_time: null, 466 | Check_time: null, 467 | Collation: 'utf8_general_ci', 468 | Checksum: null, 469 | Create_options: '', 470 | Comment: '' 471 | } 472 | ``` 473 | 474 | Get table indexes metadata: connection.indexes(table, callback). 475 | 476 | ```js 477 | connection.indexes('Language', function (err, info) { 478 | console.dir({ tableInfo: info }); 479 | }); 480 | ``` 481 | 482 | Output: 483 | 484 | ```js 485 | indexes: { 486 | PRIMARY: { 487 | Table: 'language', 488 | Non_unique: 0, 489 | Key_name: 'PRIMARY', 490 | Seq_in_index: 1, 491 | Column_name: 'LanguageId', 492 | Collation: 'A', 493 | Cardinality: 9, 494 | Sub_part: null, 495 | Packed: null, 496 | Null: '', 497 | Index_type: 'BTREE', 498 | Comment: '', 499 | Index_comment: '' }, 500 | akLanguage: { 501 | Table: 'language', 502 | Non_unique: 0, 503 | Key_name: 'akLanguage', 504 | Seq_in_index: 1, 505 | Column_name: 'LanguageName', 506 | Collation: 'A', 507 | Cardinality: 9, 508 | Sub_part: null, 509 | Packed: null, 510 | Null: '', 511 | Index_type: 'BTREE', 512 | Comment: '', 513 | Index_comment: '' 514 | } 515 | } 516 | ``` 517 | 518 | Get MySQL process list: connection.processes(callback). 519 | 520 | ```js 521 | connection.processes(function (err, processes) { 522 | console.dir({ processes }); 523 | }); 524 | ``` 525 | 526 | Output: 527 | 528 | ```js 529 | processes: [ 530 | { 531 | ID: 62, 532 | USER: 'mezha', 533 | HOST: 'localhost:14188', 534 | DB: 'mezha', 535 | COMMAND: 'Query', 536 | TIME: 0, 537 | STATE: 'executing', 538 | INFO: 'SELECT * FROM information_schema.PROCESSLIST', 539 | }, 540 | { 541 | ID: 33, 542 | USER: 'root', 543 | HOST: 'localhost:39589', 544 | DB: null, 545 | COMMAND: 'Sleep', 546 | TIME: 1, 547 | STATE: '', 548 | INFO: null, 549 | }, 550 | ]; 551 | ``` 552 | 553 | Get MySQL global variables: connection.globalVariables(callback) 554 | 555 | ```js 556 | connection.globalVariables((err, globalVariables) => { 557 | console.dir({ globalVariables }); 558 | }); 559 | ``` 560 | 561 | Output: 562 | 563 | ```js 564 | globalVariables: { 565 | MAX_PREPARED_STMT_COUNT: '16382', 566 | MAX_JOIN_SIZE: '18446744073709551615', 567 | HAVE_CRYPT: 'NO', 568 | PERFORMANCE_SCHEMA_EVENTS_WAITS_HISTORY_LONG_SIZE: '10000', 569 | INNODB_VERSION: '5.5.32', 570 | FLUSH_TIME: '1800', 571 | MAX_ERROR_COUNT: '64', 572 | ... 573 | } 574 | ``` 575 | 576 | Get MySQL global status: connection.globalStatus(callback) 577 | 578 | ```js 579 | connection.globalStatus((err, globalStatus) => { 580 | console.dir({ globalStatus }); 581 | }); 582 | ``` 583 | 584 | Output: 585 | 586 | ```js 587 | globalStatus: { 588 | ABORTED_CLIENTS: '54', 589 | ABORTED_CONNECTS: '2', 590 | BINLOG_CACHE_DISK_USE: '0', 591 | BINLOG_CACHE_USE: '0', 592 | BINLOG_STMT_CACHE_DISK_USE: '0', 593 | BINLOG_STMT_CACHE_USE: '0', 594 | BYTES_RECEIVED: '654871', 595 | BYTES_SENT: '212454927', 596 | COM_ADMIN_COMMANDS: '594', 597 | ... 598 | } 599 | ``` 600 | 601 | Get MySQL user list: connection.users(callback) 602 | 603 | ```js 604 | connection.users((err, users) => { 605 | console.dir({ users }); 606 | }); 607 | ``` 608 | 609 | Output: 610 | 611 | ```js 612 | users: [ 613 | { 614 | Host: 'localhost', 615 | User: 'root', 616 | Password: '*90E462C37378CED12064BB3388827D2BA3A9B689', 617 | Select_priv: 'Y', 618 | Insert_priv: 'Y', 619 | Update_priv: 'Y', 620 | Delete_priv: 'Y', 621 | Create_priv: 'Y', 622 | Drop_priv: 'Y', 623 | Reload_priv: 'Y', 624 | Shutdown_priv: 'Y', 625 | Process_priv: 'Y', 626 | File_priv: 'Y', 627 | Grant_priv: 'Y', 628 | References_priv: 'Y', 629 | Index_priv: 'Y', 630 | Alter_priv: 'Y', 631 | Show_db_priv: 'Y', 632 | Super_priv: 'Y', 633 | Create_tmp_table_priv: 'Y', 634 | Lock_tables_priv: 'Y', 635 | Execute_priv: 'Y', 636 | Repl_slave_priv: 'Y', 637 | Repl_client_priv: 'Y', 638 | Create_view_priv: 'Y', 639 | Show_view_priv: 'Y', 640 | Create_routine_priv: 'Y', 641 | Alter_routine_priv: 'Y', 642 | Create_user_priv: 'Y', 643 | Event_priv: 'Y', 644 | Trigger_priv: 'Y', 645 | Create_tablespace_priv: 'Y', 646 | ssl_type: '', 647 | ssl_cipher: , 648 | x509_issuer: , 649 | x509_subject: , 650 | max_questions: 0, 651 | max_updates: 0, 652 | max_connections: 0, 653 | max_user_connections: 0, 654 | plugin: '', 655 | authentication_string: '' 656 | }, ... 657 | ] 658 | ``` 659 | 660 | Generate MySQL WHERE statement: connection.where(conditions), works synchronously, no callback. Returns WHERE statement for given JSON-style conditions. 661 | 662 | ```js 663 | const where = connection.where({ 664 | id: 5, 665 | year: '>2010', 666 | price: '100..200', 667 | level: '<=3', 668 | sn: '*str?', 669 | label: 'str', 670 | code: '(1,2,4,10,11)', 671 | }); 672 | console.dir(where); 673 | // Output: "id = 5 AND year > '2010' AND (price BETWEEN '100' AND '200') AND 674 | // level <= '3' AND sn LIKE '%str_' AND label = 'str' AND code IN (1,2,4,10,11)" 675 | ``` 676 | 677 | Generate SELECT statement: connection.select(table, whereFilter, orderBy, callback) 678 | 679 | ```js 680 | connection.select( 681 | 'Language', 682 | '*', 683 | { LanguageId: '1..3' }, 684 | { LanguageId: 'desc' }, 685 | (err, results) => { 686 | console.dir({ select: results }); 687 | } 688 | ); 689 | ``` 690 | 691 | Generate INSERT statement: connection.insert(table, row, callback) 692 | 693 | ```js 694 | connection.insert( 695 | 'Language', 696 | { 697 | LanguageName: 'Tatar', 698 | LanguageSign: 'TT', 699 | LanguageISO: 'TT', 700 | Caption: 'Tatar', 701 | }, 702 | (err, recordId) => { 703 | console.dir({ insert: recordId }); 704 | } 705 | ); 706 | ``` 707 | 708 | Generate UPDATE statement: connection.update(table, row, callback) 709 | 710 | ```js 711 | connection.update( 712 | 'Language', 713 | { 714 | LanguageId: 25, 715 | LanguageName: 'Tatarca', 716 | LanguageSign: 'TT', 717 | LanguageISO: 'TT', 718 | Caption: 'Tatarca', 719 | }, 720 | (err, affectedRows) => { 721 | console.dir({ update: affectedRows }); 722 | } 723 | ); 724 | ``` 725 | 726 | Generate UPDATE statement with "where": connection.update(table, row, where, callback) 727 | 728 | ```js 729 | connection.update( 730 | 'Language', 731 | { LanguageSign: 'TT' }, 732 | { LanguageId: 1 }, 733 | (err, affectedRows) => { 734 | console.dir({ update: affectedRows }); 735 | } 736 | ); 737 | ``` 738 | 739 | Generate INSERT statement if record not exists or UPDATE if it exists: connection.upsert(table, row, callback) 740 | 741 | ```js 742 | connection.upsert( 743 | 'Language', 744 | { 745 | LanguageId: 25, 746 | LanguageName: 'Tatarca', 747 | LanguageSign: 'TT', 748 | LanguageISO: 'TT', 749 | Caption: 'Tatarca', 750 | }, 751 | (err, affectedRows) => { 752 | console.dir({ upsert: affectedRows }); 753 | } 754 | ); 755 | ``` 756 | 757 | Get record count: connection.count(table, whereFilter, callback) 758 | 759 | ```js 760 | connection.count('Language', { LanguageId: '>3' }, (err, count) => { 761 | console.dir({ count }); 762 | // count: 9 763 | }); 764 | ``` 765 | 766 | Generate DELETE statement: connection.delete(table, whereFilter, callback) 767 | 768 | ```js 769 | connection.delete('Language', { LanguageSign: 'TT' }, (err, affectedRows) => { 770 | console.dir({ delete: affectedRows }); 771 | }); 772 | ``` 773 | 774 | ## License & Contributors 775 | 776 | Copyright (c) 2012-2023 Metarhia <timur.shemsedinov@gmail.com> 777 | See github for full [contributors list](https://github.com/tshemsedinov/node-mysql-utilities/graphs/contributors). 778 | Node MySql Utilities is [MIT licensed](./LICENSE). 779 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 0.x | :x: | 8 | | 1.0.x | :x: | 9 | | 1.1.x | :white_check_mark: | 10 | 11 | ## Reporting a Vulnerability 12 | 13 | If you believe you have found a security vulnerability, let us know by sending 14 | email to [timur.shemsedinov@gmail.com](mailto:timur.shemsedinov@gmail.com) 15 | We will investigate that and do our best to quickly fix the problem. 16 | 17 | Please don't open an issue to or discuss this security vulnerability in a public 18 | place. Thanks for understanding! 19 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const mysql = require('mysql'); 4 | const mysqlUtilities = require('./utilities'); 5 | 6 | const connection = mysql.createConnection({ 7 | host: 'localhost', 8 | user: 'travis', 9 | password: '', 10 | database: 'db', 11 | }); 12 | 13 | connection.connect(); 14 | 15 | mysqlUtilities.upgrade(connection); 16 | mysqlUtilities.introspection(connection); 17 | 18 | connection.slowTime = 100; // ms 19 | 20 | connection.on('query', (err, res, fields, query) => { 21 | console.dir({ onQuery: { err, query: query.sql } }); 22 | }); 23 | 24 | connection.on('slow', (err, res, fields, query, executionTime) => { 25 | console.dir({ 26 | onSlow: { err, executionTime, query: query.sql }, 27 | }); 28 | }); 29 | 30 | console.log({ 31 | where: connection.where({ 32 | id: 5, 33 | year: '>2010', 34 | price: '100..200', 35 | level: '<=3', 36 | sn: '*str?', 37 | label: 'str', 38 | code: '(1,2,4,10,11)', 39 | }), 40 | }); 41 | 42 | connection.select('_Language', '*', { LanguageId: '1..3' }, (err, results) => { 43 | console.dir({ select: results, err }); 44 | }); 45 | 46 | connection.insert( 47 | '_Language', 48 | { 49 | LanguageName: 'Uygurian', 50 | LanguageSign: 'UY', 51 | LanguageISO: 'UY', 52 | Caption: 'Uygurian', 53 | }, 54 | (err, results) => { 55 | console.dir({ insert: results, err }); 56 | } 57 | ); 58 | 59 | connection.update( 60 | '_Language', 61 | { 62 | LanguageId: 1, 63 | LanguageName: 'Qwertian', 64 | LanguageSign: 'QW', 65 | LanguageISO: 'QW', 66 | Caption: 'Qwertian', 67 | }, 68 | (err, results) => { 69 | console.dir({ update: results, err }); 70 | } 71 | ); 72 | 73 | connection.update( 74 | '_Language', 75 | { LanguageName: 'QwertianA', LanguageSign: 'QA' }, 76 | { LanguageId: 1 }, 77 | (err, results) => { 78 | console.dir({ update: results, err }); 79 | } 80 | ); 81 | 82 | connection.upsert( 83 | '_Language', 84 | { 85 | LanguageId: 1, 86 | LanguageName: 'Qwertianian', 87 | LanguageSign: 'QW', 88 | LanguageISO: 'QW', 89 | Caption: 'Qwertianian', 90 | }, 91 | (err, results) => { 92 | console.dir({ upsert: results, err }); 93 | } 94 | ); 95 | 96 | connection.delete('_Language', { LanguageSign: 'UY' }, (err, results) => { 97 | console.dir({ delete: results, err }); 98 | }); 99 | 100 | connection.query( 101 | 'SELECT * FROM _Language where LanguageId > ?', 102 | [2], 103 | (err, results) => { 104 | console.dir({ query: results }); 105 | } 106 | ); 107 | 108 | connection.queryRow( 109 | 'SELECT * FROM _Language where LanguageId = ?', 110 | [3], 111 | (err, row) => { 112 | console.dir({ queryRow: row }); 113 | } 114 | ); 115 | 116 | connection.queryValue( 117 | 'SELECT LanguageName FROM _Language where LanguageId = ?', 118 | [8], 119 | (err, name) => { 120 | console.dir({ queryValue: name }); 121 | } 122 | ); 123 | 124 | connection.queryHash( 125 | 'SELECT LanguageSign, LanguageId, LanguageName, Caption, LanguageISO ' + 126 | 'FROM _Language', 127 | [], 128 | (err, arr) => { 129 | console.dir({ queryHash: arr }); 130 | } 131 | ); 132 | 133 | connection.queryCol('SELECT LanguageSign FROM _Language', [], (err, arr) => { 134 | console.dir({ queryCol: arr }); 135 | }); 136 | 137 | connection.queryKeyValue( 138 | 'SELECT LanguageISO, LanguageName FROM _Language', 139 | [], 140 | (err, keyValue) => { 141 | console.dir({ queryKeyValue: keyValue }); 142 | } 143 | ); 144 | 145 | connection.count('_Language', { LanguageId: '>3' }, (err, count) => { 146 | console.dir({ count }); 147 | }); 148 | 149 | connection.primary('_Language', (err, primary) => { 150 | console.dir({ primary }); 151 | }); 152 | 153 | connection.foreign('_TemplateCaption', (err, foreign) => { 154 | console.dir({ foreign }); 155 | }); 156 | 157 | connection.constraints('_TemplateCaption', (err, constraints) => { 158 | console.dir({ constraints }); 159 | }); 160 | 161 | connection.fields('_Language', (err, fields) => { 162 | console.dir({ fields }); 163 | }); 164 | 165 | connection.databases((err, databases) => { 166 | console.dir({ databases }); 167 | }); 168 | 169 | connection.tables((err, tables) => { 170 | console.dir({ tables }); 171 | }); 172 | 173 | connection.databaseTables('mezha', (err, tables) => { 174 | console.dir({ tables }); 175 | }); 176 | 177 | connection.tableInfo('_Language', (err, info) => { 178 | console.dir({ tableInfo: info }); 179 | }); 180 | 181 | connection.indexes('_Language', (err, indexes) => { 182 | console.dir({ indexes }); 183 | }); 184 | 185 | connection.processes((err, processes) => { 186 | console.dir({ processes }); 187 | }); 188 | 189 | connection.globalVariables((err, globalVariables) => { 190 | console.dir({ globalVariables }); 191 | }); 192 | 193 | connection.globalStatus((err, globalStatus) => { 194 | console.dir({ globalStatus }); 195 | }); 196 | 197 | connection.users((err, users) => { 198 | console.dir({ users }); 199 | }); 200 | 201 | setTimeout(() => { 202 | connection.end(); 203 | }, 2000); 204 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mysql-utilities", 3 | "version": "1.1.5", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@eslint/eslintrc": { 8 | "version": "1.4.1", 9 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", 10 | "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", 11 | "dev": true, 12 | "requires": { 13 | "ajv": "^6.12.4", 14 | "debug": "^4.3.2", 15 | "espree": "^9.4.0", 16 | "globals": "^13.19.0", 17 | "ignore": "^5.2.0", 18 | "import-fresh": "^3.2.1", 19 | "js-yaml": "^4.1.0", 20 | "minimatch": "^3.1.2", 21 | "strip-json-comments": "^3.1.1" 22 | } 23 | }, 24 | "@humanwhocodes/config-array": { 25 | "version": "0.11.8", 26 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", 27 | "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", 28 | "dev": true, 29 | "requires": { 30 | "@humanwhocodes/object-schema": "^1.2.1", 31 | "debug": "^4.1.1", 32 | "minimatch": "^3.0.5" 33 | } 34 | }, 35 | "@humanwhocodes/module-importer": { 36 | "version": "1.0.1", 37 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", 38 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", 39 | "dev": true 40 | }, 41 | "@humanwhocodes/object-schema": { 42 | "version": "1.2.1", 43 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", 44 | "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", 45 | "dev": true 46 | }, 47 | "@nodelib/fs.scandir": { 48 | "version": "2.1.5", 49 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 50 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 51 | "dev": true, 52 | "requires": { 53 | "@nodelib/fs.stat": "2.0.5", 54 | "run-parallel": "^1.1.9" 55 | } 56 | }, 57 | "@nodelib/fs.stat": { 58 | "version": "2.0.5", 59 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 60 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 61 | "dev": true 62 | }, 63 | "@nodelib/fs.walk": { 64 | "version": "1.2.8", 65 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 66 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 67 | "dev": true, 68 | "requires": { 69 | "@nodelib/fs.scandir": "2.1.5", 70 | "fastq": "^1.6.0" 71 | } 72 | }, 73 | "@types/json5": { 74 | "version": "0.0.29", 75 | "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", 76 | "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", 77 | "dev": true 78 | }, 79 | "acorn": { 80 | "version": "8.8.2", 81 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", 82 | "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", 83 | "dev": true 84 | }, 85 | "acorn-jsx": { 86 | "version": "5.3.2", 87 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 88 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 89 | "dev": true 90 | }, 91 | "ajv": { 92 | "version": "6.12.6", 93 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 94 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 95 | "dev": true, 96 | "requires": { 97 | "fast-deep-equal": "^3.1.1", 98 | "fast-json-stable-stringify": "^2.0.0", 99 | "json-schema-traverse": "^0.4.1", 100 | "uri-js": "^4.2.2" 101 | } 102 | }, 103 | "ansi-regex": { 104 | "version": "5.0.1", 105 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 106 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 107 | "dev": true 108 | }, 109 | "ansi-styles": { 110 | "version": "4.3.0", 111 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 112 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 113 | "dev": true, 114 | "requires": { 115 | "color-convert": "^2.0.1" 116 | } 117 | }, 118 | "argparse": { 119 | "version": "2.0.1", 120 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 121 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 122 | "dev": true 123 | }, 124 | "array-includes": { 125 | "version": "3.1.6", 126 | "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", 127 | "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", 128 | "dev": true, 129 | "requires": { 130 | "call-bind": "^1.0.2", 131 | "define-properties": "^1.1.4", 132 | "es-abstract": "^1.20.4", 133 | "get-intrinsic": "^1.1.3", 134 | "is-string": "^1.0.7" 135 | } 136 | }, 137 | "array.prototype.flat": { 138 | "version": "1.3.1", 139 | "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", 140 | "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", 141 | "dev": true, 142 | "requires": { 143 | "call-bind": "^1.0.2", 144 | "define-properties": "^1.1.4", 145 | "es-abstract": "^1.20.4", 146 | "es-shim-unscopables": "^1.0.0" 147 | } 148 | }, 149 | "array.prototype.flatmap": { 150 | "version": "1.3.1", 151 | "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", 152 | "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", 153 | "dev": true, 154 | "requires": { 155 | "call-bind": "^1.0.2", 156 | "define-properties": "^1.1.4", 157 | "es-abstract": "^1.20.4", 158 | "es-shim-unscopables": "^1.0.0" 159 | } 160 | }, 161 | "available-typed-arrays": { 162 | "version": "1.0.5", 163 | "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", 164 | "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", 165 | "dev": true 166 | }, 167 | "balanced-match": { 168 | "version": "1.0.2", 169 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 170 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 171 | "dev": true 172 | }, 173 | "bignumber.js": { 174 | "version": "9.0.0", 175 | "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", 176 | "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" 177 | }, 178 | "brace-expansion": { 179 | "version": "1.1.11", 180 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 181 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 182 | "dev": true, 183 | "requires": { 184 | "balanced-match": "^1.0.0", 185 | "concat-map": "0.0.1" 186 | } 187 | }, 188 | "call-bind": { 189 | "version": "1.0.2", 190 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 191 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 192 | "dev": true, 193 | "requires": { 194 | "function-bind": "^1.1.1", 195 | "get-intrinsic": "^1.0.2" 196 | } 197 | }, 198 | "callsites": { 199 | "version": "3.1.0", 200 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 201 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 202 | "dev": true 203 | }, 204 | "chalk": { 205 | "version": "4.1.2", 206 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 207 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 208 | "dev": true, 209 | "requires": { 210 | "ansi-styles": "^4.1.0", 211 | "supports-color": "^7.1.0" 212 | } 213 | }, 214 | "color-convert": { 215 | "version": "2.0.1", 216 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 217 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 218 | "dev": true, 219 | "requires": { 220 | "color-name": "~1.1.4" 221 | } 222 | }, 223 | "color-name": { 224 | "version": "1.1.4", 225 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 226 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 227 | "dev": true 228 | }, 229 | "concat-map": { 230 | "version": "0.0.1", 231 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 232 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", 233 | "dev": true 234 | }, 235 | "core-util-is": { 236 | "version": "1.0.3", 237 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", 238 | "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" 239 | }, 240 | "cross-spawn": { 241 | "version": "7.0.3", 242 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 243 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 244 | "dev": true, 245 | "requires": { 246 | "path-key": "^3.1.0", 247 | "shebang-command": "^2.0.0", 248 | "which": "^2.0.1" 249 | } 250 | }, 251 | "debug": { 252 | "version": "4.3.4", 253 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 254 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 255 | "dev": true, 256 | "requires": { 257 | "ms": "2.1.2" 258 | } 259 | }, 260 | "deep-is": { 261 | "version": "0.1.4", 262 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", 263 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", 264 | "dev": true 265 | }, 266 | "define-properties": { 267 | "version": "1.2.0", 268 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", 269 | "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", 270 | "dev": true, 271 | "requires": { 272 | "has-property-descriptors": "^1.0.0", 273 | "object-keys": "^1.1.1" 274 | } 275 | }, 276 | "doctrine": { 277 | "version": "3.0.0", 278 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 279 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 280 | "dev": true, 281 | "requires": { 282 | "esutils": "^2.0.2" 283 | } 284 | }, 285 | "es-abstract": { 286 | "version": "1.21.1", 287 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.1.tgz", 288 | "integrity": "sha512-QudMsPOz86xYz/1dG1OuGBKOELjCh99IIWHLzy5znUB6j8xG2yMA7bfTV86VSqKF+Y/H08vQPR+9jyXpuC6hfg==", 289 | "dev": true, 290 | "requires": { 291 | "available-typed-arrays": "^1.0.5", 292 | "call-bind": "^1.0.2", 293 | "es-set-tostringtag": "^2.0.1", 294 | "es-to-primitive": "^1.2.1", 295 | "function-bind": "^1.1.1", 296 | "function.prototype.name": "^1.1.5", 297 | "get-intrinsic": "^1.1.3", 298 | "get-symbol-description": "^1.0.0", 299 | "globalthis": "^1.0.3", 300 | "gopd": "^1.0.1", 301 | "has": "^1.0.3", 302 | "has-property-descriptors": "^1.0.0", 303 | "has-proto": "^1.0.1", 304 | "has-symbols": "^1.0.3", 305 | "internal-slot": "^1.0.4", 306 | "is-array-buffer": "^3.0.1", 307 | "is-callable": "^1.2.7", 308 | "is-negative-zero": "^2.0.2", 309 | "is-regex": "^1.1.4", 310 | "is-shared-array-buffer": "^1.0.2", 311 | "is-string": "^1.0.7", 312 | "is-typed-array": "^1.1.10", 313 | "is-weakref": "^1.0.2", 314 | "object-inspect": "^1.12.2", 315 | "object-keys": "^1.1.1", 316 | "object.assign": "^4.1.4", 317 | "regexp.prototype.flags": "^1.4.3", 318 | "safe-regex-test": "^1.0.0", 319 | "string.prototype.trimend": "^1.0.6", 320 | "string.prototype.trimstart": "^1.0.6", 321 | "typed-array-length": "^1.0.4", 322 | "unbox-primitive": "^1.0.2", 323 | "which-typed-array": "^1.1.9" 324 | } 325 | }, 326 | "es-set-tostringtag": { 327 | "version": "2.0.1", 328 | "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", 329 | "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", 330 | "dev": true, 331 | "requires": { 332 | "get-intrinsic": "^1.1.3", 333 | "has": "^1.0.3", 334 | "has-tostringtag": "^1.0.0" 335 | } 336 | }, 337 | "es-shim-unscopables": { 338 | "version": "1.0.0", 339 | "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", 340 | "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", 341 | "dev": true, 342 | "requires": { 343 | "has": "^1.0.3" 344 | } 345 | }, 346 | "es-to-primitive": { 347 | "version": "1.2.1", 348 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 349 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 350 | "dev": true, 351 | "requires": { 352 | "is-callable": "^1.1.4", 353 | "is-date-object": "^1.0.1", 354 | "is-symbol": "^1.0.2" 355 | } 356 | }, 357 | "escape-string-regexp": { 358 | "version": "4.0.0", 359 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 360 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 361 | "dev": true 362 | }, 363 | "eslint": { 364 | "version": "8.34.0", 365 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.34.0.tgz", 366 | "integrity": "sha512-1Z8iFsucw+7kSqXNZVslXS8Ioa4u2KM7GPwuKtkTFAqZ/cHMcEaR+1+Br0wLlot49cNxIiZk5wp8EAbPcYZxTg==", 367 | "dev": true, 368 | "requires": { 369 | "@eslint/eslintrc": "^1.4.1", 370 | "@humanwhocodes/config-array": "^0.11.8", 371 | "@humanwhocodes/module-importer": "^1.0.1", 372 | "@nodelib/fs.walk": "^1.2.8", 373 | "ajv": "^6.10.0", 374 | "chalk": "^4.0.0", 375 | "cross-spawn": "^7.0.2", 376 | "debug": "^4.3.2", 377 | "doctrine": "^3.0.0", 378 | "escape-string-regexp": "^4.0.0", 379 | "eslint-scope": "^7.1.1", 380 | "eslint-utils": "^3.0.0", 381 | "eslint-visitor-keys": "^3.3.0", 382 | "espree": "^9.4.0", 383 | "esquery": "^1.4.0", 384 | "esutils": "^2.0.2", 385 | "fast-deep-equal": "^3.1.3", 386 | "file-entry-cache": "^6.0.1", 387 | "find-up": "^5.0.0", 388 | "glob-parent": "^6.0.2", 389 | "globals": "^13.19.0", 390 | "grapheme-splitter": "^1.0.4", 391 | "ignore": "^5.2.0", 392 | "import-fresh": "^3.0.0", 393 | "imurmurhash": "^0.1.4", 394 | "is-glob": "^4.0.0", 395 | "is-path-inside": "^3.0.3", 396 | "js-sdsl": "^4.1.4", 397 | "js-yaml": "^4.1.0", 398 | "json-stable-stringify-without-jsonify": "^1.0.1", 399 | "levn": "^0.4.1", 400 | "lodash.merge": "^4.6.2", 401 | "minimatch": "^3.1.2", 402 | "natural-compare": "^1.4.0", 403 | "optionator": "^0.9.1", 404 | "regexpp": "^3.2.0", 405 | "strip-ansi": "^6.0.1", 406 | "strip-json-comments": "^3.1.0", 407 | "text-table": "^0.2.0" 408 | } 409 | }, 410 | "eslint-config-metarhia": { 411 | "version": "8.1.0", 412 | "resolved": "https://registry.npmjs.org/eslint-config-metarhia/-/eslint-config-metarhia-8.1.0.tgz", 413 | "integrity": "sha512-uU21zF1i6+o+pH+MD2Y1KKoJBuQ4IKIS7WcOUYK/NtPuM1YYgScrDLNtrCG/kkJOUoOgCd4xl0Wyf2OO2PE2xQ==", 414 | "dev": true 415 | }, 416 | "eslint-config-prettier": { 417 | "version": "8.6.0", 418 | "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", 419 | "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", 420 | "dev": true 421 | }, 422 | "eslint-import-resolver-node": { 423 | "version": "0.3.7", 424 | "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", 425 | "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", 426 | "dev": true, 427 | "requires": { 428 | "debug": "^3.2.7", 429 | "is-core-module": "^2.11.0", 430 | "resolve": "^1.22.1" 431 | }, 432 | "dependencies": { 433 | "debug": { 434 | "version": "3.2.7", 435 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 436 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 437 | "dev": true, 438 | "requires": { 439 | "ms": "^2.1.1" 440 | } 441 | } 442 | } 443 | }, 444 | "eslint-module-utils": { 445 | "version": "2.7.4", 446 | "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", 447 | "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", 448 | "dev": true, 449 | "requires": { 450 | "debug": "^3.2.7" 451 | }, 452 | "dependencies": { 453 | "debug": { 454 | "version": "3.2.7", 455 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 456 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 457 | "dev": true, 458 | "requires": { 459 | "ms": "^2.1.1" 460 | } 461 | } 462 | } 463 | }, 464 | "eslint-plugin-import": { 465 | "version": "2.27.5", 466 | "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", 467 | "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", 468 | "dev": true, 469 | "requires": { 470 | "array-includes": "^3.1.6", 471 | "array.prototype.flat": "^1.3.1", 472 | "array.prototype.flatmap": "^1.3.1", 473 | "debug": "^3.2.7", 474 | "doctrine": "^2.1.0", 475 | "eslint-import-resolver-node": "^0.3.7", 476 | "eslint-module-utils": "^2.7.4", 477 | "has": "^1.0.3", 478 | "is-core-module": "^2.11.0", 479 | "is-glob": "^4.0.3", 480 | "minimatch": "^3.1.2", 481 | "object.values": "^1.1.6", 482 | "resolve": "^1.22.1", 483 | "semver": "^6.3.0", 484 | "tsconfig-paths": "^3.14.1" 485 | }, 486 | "dependencies": { 487 | "debug": { 488 | "version": "3.2.7", 489 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 490 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 491 | "dev": true, 492 | "requires": { 493 | "ms": "^2.1.1" 494 | } 495 | }, 496 | "doctrine": { 497 | "version": "2.1.0", 498 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 499 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 500 | "dev": true, 501 | "requires": { 502 | "esutils": "^2.0.2" 503 | } 504 | } 505 | } 506 | }, 507 | "eslint-plugin-prettier": { 508 | "version": "4.2.1", 509 | "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", 510 | "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", 511 | "dev": true, 512 | "requires": { 513 | "prettier-linter-helpers": "^1.0.0" 514 | } 515 | }, 516 | "eslint-scope": { 517 | "version": "7.1.1", 518 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", 519 | "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", 520 | "dev": true, 521 | "requires": { 522 | "esrecurse": "^4.3.0", 523 | "estraverse": "^5.2.0" 524 | } 525 | }, 526 | "eslint-utils": { 527 | "version": "3.0.0", 528 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", 529 | "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", 530 | "dev": true, 531 | "requires": { 532 | "eslint-visitor-keys": "^2.0.0" 533 | }, 534 | "dependencies": { 535 | "eslint-visitor-keys": { 536 | "version": "2.1.0", 537 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 538 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 539 | "dev": true 540 | } 541 | } 542 | }, 543 | "eslint-visitor-keys": { 544 | "version": "3.3.0", 545 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", 546 | "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", 547 | "dev": true 548 | }, 549 | "espree": { 550 | "version": "9.4.1", 551 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", 552 | "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", 553 | "dev": true, 554 | "requires": { 555 | "acorn": "^8.8.0", 556 | "acorn-jsx": "^5.3.2", 557 | "eslint-visitor-keys": "^3.3.0" 558 | } 559 | }, 560 | "esquery": { 561 | "version": "1.4.2", 562 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", 563 | "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", 564 | "dev": true, 565 | "requires": { 566 | "estraverse": "^5.1.0" 567 | } 568 | }, 569 | "esrecurse": { 570 | "version": "4.3.0", 571 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 572 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 573 | "dev": true, 574 | "requires": { 575 | "estraverse": "^5.2.0" 576 | } 577 | }, 578 | "estraverse": { 579 | "version": "5.3.0", 580 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", 581 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", 582 | "dev": true 583 | }, 584 | "esutils": { 585 | "version": "2.0.3", 586 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 587 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 588 | "dev": true 589 | }, 590 | "fast-deep-equal": { 591 | "version": "3.1.3", 592 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 593 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 594 | "dev": true 595 | }, 596 | "fast-diff": { 597 | "version": "1.2.0", 598 | "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", 599 | "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", 600 | "dev": true 601 | }, 602 | "fast-json-stable-stringify": { 603 | "version": "2.1.0", 604 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 605 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 606 | "dev": true 607 | }, 608 | "fast-levenshtein": { 609 | "version": "2.0.6", 610 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 611 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", 612 | "dev": true 613 | }, 614 | "fastq": { 615 | "version": "1.15.0", 616 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", 617 | "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", 618 | "dev": true, 619 | "requires": { 620 | "reusify": "^1.0.4" 621 | } 622 | }, 623 | "file-entry-cache": { 624 | "version": "6.0.1", 625 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 626 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 627 | "dev": true, 628 | "requires": { 629 | "flat-cache": "^3.0.4" 630 | } 631 | }, 632 | "find-up": { 633 | "version": "5.0.0", 634 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 635 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 636 | "dev": true, 637 | "requires": { 638 | "locate-path": "^6.0.0", 639 | "path-exists": "^4.0.0" 640 | } 641 | }, 642 | "flat-cache": { 643 | "version": "3.0.4", 644 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 645 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 646 | "dev": true, 647 | "requires": { 648 | "flatted": "^3.1.0", 649 | "rimraf": "^3.0.2" 650 | } 651 | }, 652 | "flatted": { 653 | "version": "3.2.7", 654 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", 655 | "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", 656 | "dev": true 657 | }, 658 | "for-each": { 659 | "version": "0.3.3", 660 | "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", 661 | "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", 662 | "dev": true, 663 | "requires": { 664 | "is-callable": "^1.1.3" 665 | } 666 | }, 667 | "fs.realpath": { 668 | "version": "1.0.0", 669 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 670 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", 671 | "dev": true 672 | }, 673 | "function-bind": { 674 | "version": "1.1.1", 675 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 676 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 677 | "dev": true 678 | }, 679 | "function.prototype.name": { 680 | "version": "1.1.5", 681 | "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", 682 | "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", 683 | "dev": true, 684 | "requires": { 685 | "call-bind": "^1.0.2", 686 | "define-properties": "^1.1.3", 687 | "es-abstract": "^1.19.0", 688 | "functions-have-names": "^1.2.2" 689 | } 690 | }, 691 | "functions-have-names": { 692 | "version": "1.2.3", 693 | "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", 694 | "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", 695 | "dev": true 696 | }, 697 | "get-intrinsic": { 698 | "version": "1.2.0", 699 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 700 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 701 | "dev": true, 702 | "requires": { 703 | "function-bind": "^1.1.1", 704 | "has": "^1.0.3", 705 | "has-symbols": "^1.0.3" 706 | } 707 | }, 708 | "get-symbol-description": { 709 | "version": "1.0.0", 710 | "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", 711 | "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", 712 | "dev": true, 713 | "requires": { 714 | "call-bind": "^1.0.2", 715 | "get-intrinsic": "^1.1.1" 716 | } 717 | }, 718 | "glob": { 719 | "version": "7.2.3", 720 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", 721 | "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", 722 | "dev": true, 723 | "requires": { 724 | "fs.realpath": "^1.0.0", 725 | "inflight": "^1.0.4", 726 | "inherits": "2", 727 | "minimatch": "^3.1.1", 728 | "once": "^1.3.0", 729 | "path-is-absolute": "^1.0.0" 730 | } 731 | }, 732 | "glob-parent": { 733 | "version": "6.0.2", 734 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", 735 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", 736 | "dev": true, 737 | "requires": { 738 | "is-glob": "^4.0.3" 739 | } 740 | }, 741 | "globals": { 742 | "version": "13.20.0", 743 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", 744 | "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", 745 | "dev": true, 746 | "requires": { 747 | "type-fest": "^0.20.2" 748 | } 749 | }, 750 | "globalthis": { 751 | "version": "1.0.3", 752 | "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", 753 | "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", 754 | "dev": true, 755 | "requires": { 756 | "define-properties": "^1.1.3" 757 | } 758 | }, 759 | "gopd": { 760 | "version": "1.0.1", 761 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 762 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 763 | "dev": true, 764 | "requires": { 765 | "get-intrinsic": "^1.1.3" 766 | } 767 | }, 768 | "grapheme-splitter": { 769 | "version": "1.0.4", 770 | "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", 771 | "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", 772 | "dev": true 773 | }, 774 | "has": { 775 | "version": "1.0.3", 776 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 777 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 778 | "dev": true, 779 | "requires": { 780 | "function-bind": "^1.1.1" 781 | } 782 | }, 783 | "has-bigints": { 784 | "version": "1.0.2", 785 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", 786 | "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", 787 | "dev": true 788 | }, 789 | "has-flag": { 790 | "version": "4.0.0", 791 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 792 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 793 | "dev": true 794 | }, 795 | "has-property-descriptors": { 796 | "version": "1.0.0", 797 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", 798 | "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", 799 | "dev": true, 800 | "requires": { 801 | "get-intrinsic": "^1.1.1" 802 | } 803 | }, 804 | "has-proto": { 805 | "version": "1.0.1", 806 | "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", 807 | "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", 808 | "dev": true 809 | }, 810 | "has-symbols": { 811 | "version": "1.0.3", 812 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 813 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 814 | "dev": true 815 | }, 816 | "has-tostringtag": { 817 | "version": "1.0.0", 818 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", 819 | "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", 820 | "dev": true, 821 | "requires": { 822 | "has-symbols": "^1.0.2" 823 | } 824 | }, 825 | "ignore": { 826 | "version": "5.2.4", 827 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", 828 | "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", 829 | "dev": true 830 | }, 831 | "import-fresh": { 832 | "version": "3.3.0", 833 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 834 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 835 | "dev": true, 836 | "requires": { 837 | "parent-module": "^1.0.0", 838 | "resolve-from": "^4.0.0" 839 | } 840 | }, 841 | "imurmurhash": { 842 | "version": "0.1.4", 843 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 844 | "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", 845 | "dev": true 846 | }, 847 | "inflight": { 848 | "version": "1.0.6", 849 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 850 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", 851 | "dev": true, 852 | "requires": { 853 | "once": "^1.3.0", 854 | "wrappy": "1" 855 | } 856 | }, 857 | "inherits": { 858 | "version": "2.0.4", 859 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 860 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 861 | }, 862 | "internal-slot": { 863 | "version": "1.0.5", 864 | "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", 865 | "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", 866 | "dev": true, 867 | "requires": { 868 | "get-intrinsic": "^1.2.0", 869 | "has": "^1.0.3", 870 | "side-channel": "^1.0.4" 871 | } 872 | }, 873 | "is-array-buffer": { 874 | "version": "3.0.1", 875 | "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", 876 | "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", 877 | "dev": true, 878 | "requires": { 879 | "call-bind": "^1.0.2", 880 | "get-intrinsic": "^1.1.3", 881 | "is-typed-array": "^1.1.10" 882 | } 883 | }, 884 | "is-bigint": { 885 | "version": "1.0.4", 886 | "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", 887 | "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", 888 | "dev": true, 889 | "requires": { 890 | "has-bigints": "^1.0.1" 891 | } 892 | }, 893 | "is-boolean-object": { 894 | "version": "1.1.2", 895 | "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", 896 | "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", 897 | "dev": true, 898 | "requires": { 899 | "call-bind": "^1.0.2", 900 | "has-tostringtag": "^1.0.0" 901 | } 902 | }, 903 | "is-callable": { 904 | "version": "1.2.7", 905 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", 906 | "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", 907 | "dev": true 908 | }, 909 | "is-core-module": { 910 | "version": "2.11.0", 911 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", 912 | "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", 913 | "dev": true, 914 | "requires": { 915 | "has": "^1.0.3" 916 | } 917 | }, 918 | "is-date-object": { 919 | "version": "1.0.5", 920 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", 921 | "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", 922 | "dev": true, 923 | "requires": { 924 | "has-tostringtag": "^1.0.0" 925 | } 926 | }, 927 | "is-extglob": { 928 | "version": "2.1.1", 929 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 930 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 931 | "dev": true 932 | }, 933 | "is-glob": { 934 | "version": "4.0.3", 935 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 936 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 937 | "dev": true, 938 | "requires": { 939 | "is-extglob": "^2.1.1" 940 | } 941 | }, 942 | "is-negative-zero": { 943 | "version": "2.0.2", 944 | "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", 945 | "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", 946 | "dev": true 947 | }, 948 | "is-number-object": { 949 | "version": "1.0.7", 950 | "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", 951 | "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", 952 | "dev": true, 953 | "requires": { 954 | "has-tostringtag": "^1.0.0" 955 | } 956 | }, 957 | "is-path-inside": { 958 | "version": "3.0.3", 959 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", 960 | "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", 961 | "dev": true 962 | }, 963 | "is-regex": { 964 | "version": "1.1.4", 965 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", 966 | "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", 967 | "dev": true, 968 | "requires": { 969 | "call-bind": "^1.0.2", 970 | "has-tostringtag": "^1.0.0" 971 | } 972 | }, 973 | "is-shared-array-buffer": { 974 | "version": "1.0.2", 975 | "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", 976 | "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", 977 | "dev": true, 978 | "requires": { 979 | "call-bind": "^1.0.2" 980 | } 981 | }, 982 | "is-string": { 983 | "version": "1.0.7", 984 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", 985 | "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", 986 | "dev": true, 987 | "requires": { 988 | "has-tostringtag": "^1.0.0" 989 | } 990 | }, 991 | "is-symbol": { 992 | "version": "1.0.4", 993 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", 994 | "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", 995 | "dev": true, 996 | "requires": { 997 | "has-symbols": "^1.0.2" 998 | } 999 | }, 1000 | "is-typed-array": { 1001 | "version": "1.1.10", 1002 | "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", 1003 | "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", 1004 | "dev": true, 1005 | "requires": { 1006 | "available-typed-arrays": "^1.0.5", 1007 | "call-bind": "^1.0.2", 1008 | "for-each": "^0.3.3", 1009 | "gopd": "^1.0.1", 1010 | "has-tostringtag": "^1.0.0" 1011 | } 1012 | }, 1013 | "is-weakref": { 1014 | "version": "1.0.2", 1015 | "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", 1016 | "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", 1017 | "dev": true, 1018 | "requires": { 1019 | "call-bind": "^1.0.2" 1020 | } 1021 | }, 1022 | "isarray": { 1023 | "version": "1.0.0", 1024 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1025 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 1026 | }, 1027 | "isexe": { 1028 | "version": "2.0.0", 1029 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1030 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 1031 | "dev": true 1032 | }, 1033 | "js-sdsl": { 1034 | "version": "4.3.0", 1035 | "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", 1036 | "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", 1037 | "dev": true 1038 | }, 1039 | "js-yaml": { 1040 | "version": "4.1.0", 1041 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1042 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1043 | "dev": true, 1044 | "requires": { 1045 | "argparse": "^2.0.1" 1046 | } 1047 | }, 1048 | "json-schema-traverse": { 1049 | "version": "0.4.1", 1050 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1051 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1052 | "dev": true 1053 | }, 1054 | "json-stable-stringify-without-jsonify": { 1055 | "version": "1.0.1", 1056 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1057 | "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", 1058 | "dev": true 1059 | }, 1060 | "json5": { 1061 | "version": "1.0.2", 1062 | "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", 1063 | "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", 1064 | "dev": true, 1065 | "requires": { 1066 | "minimist": "^1.2.0" 1067 | } 1068 | }, 1069 | "levn": { 1070 | "version": "0.4.1", 1071 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1072 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1073 | "dev": true, 1074 | "requires": { 1075 | "prelude-ls": "^1.2.1", 1076 | "type-check": "~0.4.0" 1077 | } 1078 | }, 1079 | "locate-path": { 1080 | "version": "6.0.0", 1081 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 1082 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 1083 | "dev": true, 1084 | "requires": { 1085 | "p-locate": "^5.0.0" 1086 | } 1087 | }, 1088 | "lodash.merge": { 1089 | "version": "4.6.2", 1090 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1091 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1092 | "dev": true 1093 | }, 1094 | "minimatch": { 1095 | "version": "3.1.2", 1096 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1097 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1098 | "dev": true, 1099 | "requires": { 1100 | "brace-expansion": "^1.1.7" 1101 | } 1102 | }, 1103 | "minimist": { 1104 | "version": "1.2.8", 1105 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 1106 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 1107 | "dev": true 1108 | }, 1109 | "ms": { 1110 | "version": "2.1.2", 1111 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1112 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1113 | "dev": true 1114 | }, 1115 | "mysql": { 1116 | "version": "2.18.1", 1117 | "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", 1118 | "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", 1119 | "requires": { 1120 | "bignumber.js": "9.0.0", 1121 | "readable-stream": "2.3.7", 1122 | "safe-buffer": "5.1.2", 1123 | "sqlstring": "2.3.1" 1124 | } 1125 | }, 1126 | "natural-compare": { 1127 | "version": "1.4.0", 1128 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1129 | "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", 1130 | "dev": true 1131 | }, 1132 | "object-inspect": { 1133 | "version": "1.12.3", 1134 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 1135 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", 1136 | "dev": true 1137 | }, 1138 | "object-keys": { 1139 | "version": "1.1.1", 1140 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1141 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 1142 | "dev": true 1143 | }, 1144 | "object.assign": { 1145 | "version": "4.1.4", 1146 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", 1147 | "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", 1148 | "dev": true, 1149 | "requires": { 1150 | "call-bind": "^1.0.2", 1151 | "define-properties": "^1.1.4", 1152 | "has-symbols": "^1.0.3", 1153 | "object-keys": "^1.1.1" 1154 | } 1155 | }, 1156 | "object.values": { 1157 | "version": "1.1.6", 1158 | "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", 1159 | "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", 1160 | "dev": true, 1161 | "requires": { 1162 | "call-bind": "^1.0.2", 1163 | "define-properties": "^1.1.4", 1164 | "es-abstract": "^1.20.4" 1165 | } 1166 | }, 1167 | "once": { 1168 | "version": "1.4.0", 1169 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1170 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", 1171 | "dev": true, 1172 | "requires": { 1173 | "wrappy": "1" 1174 | } 1175 | }, 1176 | "optionator": { 1177 | "version": "0.9.1", 1178 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 1179 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 1180 | "dev": true, 1181 | "requires": { 1182 | "deep-is": "^0.1.3", 1183 | "fast-levenshtein": "^2.0.6", 1184 | "levn": "^0.4.1", 1185 | "prelude-ls": "^1.2.1", 1186 | "type-check": "^0.4.0", 1187 | "word-wrap": "^1.2.3" 1188 | } 1189 | }, 1190 | "p-limit": { 1191 | "version": "3.1.0", 1192 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1193 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1194 | "dev": true, 1195 | "requires": { 1196 | "yocto-queue": "^0.1.0" 1197 | } 1198 | }, 1199 | "p-locate": { 1200 | "version": "5.0.0", 1201 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1202 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1203 | "dev": true, 1204 | "requires": { 1205 | "p-limit": "^3.0.2" 1206 | } 1207 | }, 1208 | "parent-module": { 1209 | "version": "1.0.1", 1210 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1211 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1212 | "dev": true, 1213 | "requires": { 1214 | "callsites": "^3.0.0" 1215 | } 1216 | }, 1217 | "path-exists": { 1218 | "version": "4.0.0", 1219 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1220 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1221 | "dev": true 1222 | }, 1223 | "path-is-absolute": { 1224 | "version": "1.0.1", 1225 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1226 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", 1227 | "dev": true 1228 | }, 1229 | "path-key": { 1230 | "version": "3.1.1", 1231 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1232 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1233 | "dev": true 1234 | }, 1235 | "path-parse": { 1236 | "version": "1.0.7", 1237 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1238 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1239 | "dev": true 1240 | }, 1241 | "prelude-ls": { 1242 | "version": "1.2.1", 1243 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 1244 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 1245 | "dev": true 1246 | }, 1247 | "prettier": { 1248 | "version": "2.8.4", 1249 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.4.tgz", 1250 | "integrity": "sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==", 1251 | "dev": true 1252 | }, 1253 | "prettier-linter-helpers": { 1254 | "version": "1.0.0", 1255 | "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", 1256 | "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", 1257 | "dev": true, 1258 | "requires": { 1259 | "fast-diff": "^1.1.2" 1260 | } 1261 | }, 1262 | "process-nextick-args": { 1263 | "version": "2.0.1", 1264 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1265 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 1266 | }, 1267 | "punycode": { 1268 | "version": "2.3.0", 1269 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", 1270 | "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", 1271 | "dev": true 1272 | }, 1273 | "queue-microtask": { 1274 | "version": "1.2.3", 1275 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1276 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1277 | "dev": true 1278 | }, 1279 | "readable-stream": { 1280 | "version": "2.3.7", 1281 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 1282 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 1283 | "requires": { 1284 | "core-util-is": "~1.0.0", 1285 | "inherits": "~2.0.3", 1286 | "isarray": "~1.0.0", 1287 | "process-nextick-args": "~2.0.0", 1288 | "safe-buffer": "~5.1.1", 1289 | "string_decoder": "~1.1.1", 1290 | "util-deprecate": "~1.0.1" 1291 | } 1292 | }, 1293 | "regexp.prototype.flags": { 1294 | "version": "1.4.3", 1295 | "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", 1296 | "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", 1297 | "dev": true, 1298 | "requires": { 1299 | "call-bind": "^1.0.2", 1300 | "define-properties": "^1.1.3", 1301 | "functions-have-names": "^1.2.2" 1302 | } 1303 | }, 1304 | "regexpp": { 1305 | "version": "3.2.0", 1306 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", 1307 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 1308 | "dev": true 1309 | }, 1310 | "resolve": { 1311 | "version": "1.22.1", 1312 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", 1313 | "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", 1314 | "dev": true, 1315 | "requires": { 1316 | "is-core-module": "^2.9.0", 1317 | "path-parse": "^1.0.7", 1318 | "supports-preserve-symlinks-flag": "^1.0.0" 1319 | } 1320 | }, 1321 | "resolve-from": { 1322 | "version": "4.0.0", 1323 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1324 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1325 | "dev": true 1326 | }, 1327 | "reusify": { 1328 | "version": "1.0.4", 1329 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1330 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1331 | "dev": true 1332 | }, 1333 | "rimraf": { 1334 | "version": "3.0.2", 1335 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1336 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1337 | "dev": true, 1338 | "requires": { 1339 | "glob": "^7.1.3" 1340 | } 1341 | }, 1342 | "run-parallel": { 1343 | "version": "1.2.0", 1344 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1345 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1346 | "dev": true, 1347 | "requires": { 1348 | "queue-microtask": "^1.2.2" 1349 | } 1350 | }, 1351 | "safe-buffer": { 1352 | "version": "5.1.2", 1353 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1354 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1355 | }, 1356 | "safe-regex-test": { 1357 | "version": "1.0.0", 1358 | "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", 1359 | "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", 1360 | "dev": true, 1361 | "requires": { 1362 | "call-bind": "^1.0.2", 1363 | "get-intrinsic": "^1.1.3", 1364 | "is-regex": "^1.1.4" 1365 | } 1366 | }, 1367 | "semver": { 1368 | "version": "6.3.0", 1369 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1370 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1371 | "dev": true 1372 | }, 1373 | "shebang-command": { 1374 | "version": "2.0.0", 1375 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1376 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1377 | "dev": true, 1378 | "requires": { 1379 | "shebang-regex": "^3.0.0" 1380 | } 1381 | }, 1382 | "shebang-regex": { 1383 | "version": "3.0.0", 1384 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1385 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1386 | "dev": true 1387 | }, 1388 | "side-channel": { 1389 | "version": "1.0.4", 1390 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1391 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1392 | "dev": true, 1393 | "requires": { 1394 | "call-bind": "^1.0.0", 1395 | "get-intrinsic": "^1.0.2", 1396 | "object-inspect": "^1.9.0" 1397 | } 1398 | }, 1399 | "sqlstring": { 1400 | "version": "2.3.1", 1401 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", 1402 | "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" 1403 | }, 1404 | "string.prototype.trimend": { 1405 | "version": "1.0.6", 1406 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", 1407 | "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", 1408 | "dev": true, 1409 | "requires": { 1410 | "call-bind": "^1.0.2", 1411 | "define-properties": "^1.1.4", 1412 | "es-abstract": "^1.20.4" 1413 | } 1414 | }, 1415 | "string.prototype.trimstart": { 1416 | "version": "1.0.6", 1417 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", 1418 | "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", 1419 | "dev": true, 1420 | "requires": { 1421 | "call-bind": "^1.0.2", 1422 | "define-properties": "^1.1.4", 1423 | "es-abstract": "^1.20.4" 1424 | } 1425 | }, 1426 | "string_decoder": { 1427 | "version": "1.1.1", 1428 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1429 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1430 | "requires": { 1431 | "safe-buffer": "~5.1.0" 1432 | } 1433 | }, 1434 | "strip-ansi": { 1435 | "version": "6.0.1", 1436 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1437 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1438 | "dev": true, 1439 | "requires": { 1440 | "ansi-regex": "^5.0.1" 1441 | } 1442 | }, 1443 | "strip-bom": { 1444 | "version": "3.0.0", 1445 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 1446 | "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", 1447 | "dev": true 1448 | }, 1449 | "strip-json-comments": { 1450 | "version": "3.1.1", 1451 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 1452 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 1453 | "dev": true 1454 | }, 1455 | "supports-color": { 1456 | "version": "7.2.0", 1457 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1458 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1459 | "dev": true, 1460 | "requires": { 1461 | "has-flag": "^4.0.0" 1462 | } 1463 | }, 1464 | "supports-preserve-symlinks-flag": { 1465 | "version": "1.0.0", 1466 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 1467 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 1468 | "dev": true 1469 | }, 1470 | "text-table": { 1471 | "version": "0.2.0", 1472 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1473 | "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", 1474 | "dev": true 1475 | }, 1476 | "tsconfig-paths": { 1477 | "version": "3.14.1", 1478 | "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", 1479 | "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", 1480 | "dev": true, 1481 | "requires": { 1482 | "@types/json5": "^0.0.29", 1483 | "json5": "^1.0.1", 1484 | "minimist": "^1.2.6", 1485 | "strip-bom": "^3.0.0" 1486 | } 1487 | }, 1488 | "type-check": { 1489 | "version": "0.4.0", 1490 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 1491 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 1492 | "dev": true, 1493 | "requires": { 1494 | "prelude-ls": "^1.2.1" 1495 | } 1496 | }, 1497 | "type-fest": { 1498 | "version": "0.20.2", 1499 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 1500 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 1501 | "dev": true 1502 | }, 1503 | "typed-array-length": { 1504 | "version": "1.0.4", 1505 | "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", 1506 | "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", 1507 | "dev": true, 1508 | "requires": { 1509 | "call-bind": "^1.0.2", 1510 | "for-each": "^0.3.3", 1511 | "is-typed-array": "^1.1.9" 1512 | } 1513 | }, 1514 | "unbox-primitive": { 1515 | "version": "1.0.2", 1516 | "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", 1517 | "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", 1518 | "dev": true, 1519 | "requires": { 1520 | "call-bind": "^1.0.2", 1521 | "has-bigints": "^1.0.2", 1522 | "has-symbols": "^1.0.3", 1523 | "which-boxed-primitive": "^1.0.2" 1524 | } 1525 | }, 1526 | "uri-js": { 1527 | "version": "4.4.1", 1528 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 1529 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 1530 | "dev": true, 1531 | "requires": { 1532 | "punycode": "^2.1.0" 1533 | } 1534 | }, 1535 | "util-deprecate": { 1536 | "version": "1.0.2", 1537 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1538 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1539 | }, 1540 | "which": { 1541 | "version": "2.0.2", 1542 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1543 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1544 | "dev": true, 1545 | "requires": { 1546 | "isexe": "^2.0.0" 1547 | } 1548 | }, 1549 | "which-boxed-primitive": { 1550 | "version": "1.0.2", 1551 | "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", 1552 | "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", 1553 | "dev": true, 1554 | "requires": { 1555 | "is-bigint": "^1.0.1", 1556 | "is-boolean-object": "^1.1.0", 1557 | "is-number-object": "^1.0.4", 1558 | "is-string": "^1.0.5", 1559 | "is-symbol": "^1.0.3" 1560 | } 1561 | }, 1562 | "which-typed-array": { 1563 | "version": "1.1.9", 1564 | "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", 1565 | "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", 1566 | "dev": true, 1567 | "requires": { 1568 | "available-typed-arrays": "^1.0.5", 1569 | "call-bind": "^1.0.2", 1570 | "for-each": "^0.3.3", 1571 | "gopd": "^1.0.1", 1572 | "has-tostringtag": "^1.0.0", 1573 | "is-typed-array": "^1.1.10" 1574 | } 1575 | }, 1576 | "word-wrap": { 1577 | "version": "1.2.3", 1578 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 1579 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 1580 | "dev": true 1581 | }, 1582 | "wrappy": { 1583 | "version": "1.0.2", 1584 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1585 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", 1586 | "dev": true 1587 | }, 1588 | "yocto-queue": { 1589 | "version": "0.1.0", 1590 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 1591 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 1592 | "dev": true 1593 | } 1594 | } 1595 | } 1596 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mysql-utilities", 3 | "version": "1.1.5", 4 | "author": "Timur Shemsedinov ", 5 | "description": "Utilities for node-mysql driver with specialized result types, introspection and other helpful functionality.", 6 | "license": "MIT", 7 | "keywords": [ 8 | "mysql", 9 | "utilities", 10 | "introspection", 11 | "impress" 12 | ], 13 | "readmeFilename": "README.md", 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/tshemsedinov/node-mysql-utilities" 17 | }, 18 | "main": "utilities.js", 19 | "files": [], 20 | "scripts": { 21 | "test": "npm run lint && node example", 22 | "lint": "eslint . && prettier -c \"**/*.js\" \"**/*.json\" \"**/*.md\" \"**/*.yml\"", 23 | "fmt": "prettier --write \"**/*.js\" \"**/*.json\" \"**/*.md\" \"**/*.yml\"" 24 | }, 25 | "engines": { 26 | "node": ">= 6.0.0" 27 | }, 28 | "dependencies": { 29 | "mysql": "^2.18.1" 30 | }, 31 | "devDependencies": { 32 | "eslint": "^8.34.0", 33 | "eslint-config-metarhia": "^8.1.0", 34 | "eslint-config-prettier": "^8.6.0", 35 | "eslint-plugin-import": "^2.27.5", 36 | "eslint-plugin-prettier": "^4.2.1", 37 | "prettier": "^2.8.4" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /utilities.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const identifierRegexp = /^[0-9,a-z,A-Z_.]*$/; 4 | 5 | const escapeIdentifier = (str, quote) => { 6 | quote = quote || '`'; 7 | if (identifierRegexp.test(str)) return str; 8 | return quote + str + quote; 9 | }; 10 | 11 | if (typeof Function.prototype.override !== 'function') { 12 | Function.prototype.override = function (fn) { 13 | const superFunction = this; 14 | return function (...args) { 15 | this.inherited = superFunction; 16 | return fn.apply(this, args); 17 | }; 18 | }; 19 | } 20 | 21 | const buildCondition = (key, value, esc) => { 22 | for (const operator of ['>=', '<=', '<>', '>', '<']) { 23 | if (value.startsWith(operator)) { 24 | const s = value.substring(operator.length); 25 | return `${key} ${operator} ${esc(s)}`; 26 | } 27 | } 28 | if (value.startsWith('(')) { 29 | const list = value.substr(1, value.length - 2).split(','); 30 | const set = list.map(s => esc(s)).join(','); 31 | return `${key} IN (${set})`; 32 | } 33 | if (value.includes('..')) { 34 | const [begin, end] = value.split('..'); 35 | return `(${key} BETWEEN ${begin} AND ${end})`; 36 | } 37 | if (value.includes('*') || value.includes('?')) { 38 | const val = value.replace(/\*/g, '%').replace(/\?/g, '_'); 39 | return `${key} LIKE ${esc(val)}`; 40 | } 41 | return `${key} = ${esc(value)}`; 42 | }; 43 | 44 | const upgrade = connection => { 45 | if (!connection._mixedUpgrade) { 46 | connection._mixedUpgrade = true; 47 | connection.slowTime = 2000; 48 | 49 | connection.query = connection.query.override(function ( 50 | sql, 51 | values, 52 | callback 53 | ) { 54 | const startTime = new Date().getTime(); 55 | if (typeof values === 'function') { 56 | callback = values; 57 | values = []; 58 | } 59 | const query = this.inherited(sql, values, (err, res, fields) => { 60 | const endTime = new Date().getTime(); 61 | const executionTime = endTime - startTime; 62 | connection.emit('query', err, res, fields, query); 63 | if (connection.slowTime && executionTime >= connection.slowTime) { 64 | connection.emit('slow', err, res, fields, query, executionTime); 65 | } 66 | if (callback) callback(err, res, fields); 67 | }); 68 | return query; 69 | }); 70 | 71 | // Where clause builder 72 | // Example: { 73 | // id: 5, year: '>2010', price: '100..200', 74 | // level: '<=3', sn: '*str?', label: 'str', 75 | // code: '(1,2,4,10,11)' } 76 | // Returns: 'id = 5 AND year > '2010' AND (price BETWEEN '100' AND '200') 77 | // AND level <= '3' AND sn LIKE '%str_' 78 | // AND label = 'str' AND code IN (1,2,4,10,11)' 79 | // 80 | connection.where = function (where) { 81 | const result = []; 82 | for (const key in where) { 83 | const value = where[key]; 84 | if (typeof value === 'number') { 85 | result.push(`${key} = ${value.toString()}`); 86 | } else if (typeof value === 'string') { 87 | result.push(buildCondition(key, value, s => this.escape(s))); 88 | } 89 | } 90 | return result.join(' AND '); 91 | }; 92 | 93 | // Order builder 94 | // Example: { id: 'asc', name: 'desc' } 95 | // Returns: 'id asc, name desc' 96 | // 97 | connection.order = function (order) { 98 | const result = []; 99 | let key, val, clause; 100 | for (key in order) { 101 | val = order[key]; 102 | clause = key; 103 | result.push(clause + ' ' + val); 104 | } 105 | if (result.length) return result.join(); 106 | return ''; 107 | }; 108 | 109 | // Record count 110 | // 111 | connection.count = function (table, where, callback) { 112 | where = this.where(where); 113 | let sql = 'SELECT count(*) FROM ' + escapeIdentifier(table); 114 | if (where) sql = sql + ' WHERE ' + where; 115 | return this.queryValue(sql, [], (err, res) => { 116 | callback(err, res); 117 | }); 118 | }; 119 | 120 | // Returns single row as associative array of fields 121 | // 122 | connection.queryRow = function (sql, values, callback) { 123 | if (typeof values === 'function') { 124 | callback = values; 125 | values = []; 126 | } 127 | return this.query(sql, values, (err, res, fields) => { 128 | if (err) return callback(err); 129 | res = res[0] ? res[0] : false; 130 | callback(err, res, fields); 131 | }); 132 | }; 133 | 134 | // Returns single value (scalar) 135 | // 136 | connection.queryValue = function (sql, values, callback) { 137 | if (typeof values === 'function') { 138 | callback = values; 139 | values = []; 140 | } 141 | return this.queryRow(sql, values, (err, res, fields) => { 142 | if (err) return callback(err); 143 | const value = res[Object.keys(res)[0]]; 144 | callback(err, value, fields); 145 | }); 146 | }; 147 | 148 | // Query returning array of column field values 149 | // 150 | connection.queryCol = function (sql, values, callback) { 151 | if (typeof values === 'function') { 152 | callback = values; 153 | values = []; 154 | } 155 | return this.query(sql, values, (err, res, fields) => { 156 | if (err) return callback(err); 157 | const result = []; 158 | let i, row, keys; 159 | for (i in res) { 160 | row = res[i]; 161 | keys = Object.keys(row); 162 | result.push(row[keys[0]]); 163 | } 164 | callback(err, result, fields); 165 | }); 166 | }; 167 | 168 | // Query returning hash (associative array), first field will be array key 169 | // 170 | connection.queryHash = function (sql, values, callback) { 171 | if (typeof values === 'function') { 172 | callback = values; 173 | values = []; 174 | } 175 | return this.query(sql, values, (err, res, fields) => { 176 | if (err) return callback(err); 177 | const result = {}; 178 | let i, row, keys; 179 | for (i in res) { 180 | row = res[i]; 181 | keys = Object.keys(row); 182 | result[row[keys[0]]] = row; 183 | } 184 | callback(err, result, fields); 185 | }); 186 | }; 187 | 188 | // Query returning key-value array, 189 | // first field of query will be key and second will be value 190 | // 191 | connection.queryKeyValue = function (sql, values, callback) { 192 | if (typeof values === 'function') { 193 | callback = values; 194 | values = []; 195 | } 196 | return this.query(sql, values, (err, res, fields) => { 197 | if (err) return callback(err); 198 | const result = {}; 199 | let i, row, keys; 200 | for (i in res) { 201 | row = res[i]; 202 | keys = Object.keys(row); 203 | result[row[keys[0]]] = row[keys[1]]; 204 | } 205 | callback(err, result, fields); 206 | }); 207 | }; 208 | 209 | // SELECT SQL statement generator 210 | // 211 | connection.select = function (table, fields, where, order, callback) { 212 | where = this.where(where); 213 | if (typeof order === 'function') { 214 | callback = order; 215 | order = {}; 216 | } 217 | order = this.order(order); 218 | let sql = 'SELECT ' + fields + ' FROM ' + escapeIdentifier(table); 219 | if (where) sql = sql + ' WHERE ' + where; 220 | if (order) sql = sql + ' ORDER BY ' + order; 221 | const query = this.query(sql, [], (err, res) => { 222 | callback(err, res, query); 223 | }); 224 | }; 225 | 226 | // SELECT SQL statement generator by LIMIT 227 | // 228 | connection.selectLimit = function ( 229 | table, 230 | fields, 231 | limit, 232 | where, 233 | order, 234 | callback 235 | ) { 236 | where = this.where(where); 237 | if (typeof order === 'function') { 238 | callback = order; 239 | order = {}; 240 | } 241 | order = this.order(order); 242 | let sql = 'SELECT ' + fields + ' FROM ' + escapeIdentifier(table); 243 | if (where) sql = sql + ' WHERE ' + where; 244 | if (order) sql = sql + ' ORDER BY ' + order; 245 | sql = sql + ' LIMIT ' + limit.join(); 246 | const query = this.query(sql, [], (err, res) => { 247 | callback(err, res, query); 248 | }); 249 | }; 250 | 251 | // INSERT SQL statement generator 252 | // callback(err, id or false) 253 | // 254 | connection.insert = function (table, row, callback) { 255 | this.fields(table, (err, fields) => { 256 | if (err) { 257 | return callback( 258 | new Error('Error: Table "' + table + '" not found'), 259 | false 260 | ); 261 | } 262 | fields = Object.keys(fields); 263 | const rowKeys = Object.keys(row); 264 | const values = []; 265 | const columns = []; 266 | let i, field; 267 | for (i in fields) { 268 | field = fields[i]; 269 | if (rowKeys.includes(field)) { 270 | columns.push(field); 271 | values.push(this.escape(row[field])); 272 | } 273 | } 274 | const query = this.query( 275 | 'INSERT INTO ' + 276 | escapeIdentifier(table) + 277 | ' (' + 278 | columns.join(', ') + 279 | ') VALUES (' + 280 | values.join(', ') + 281 | ')', 282 | [], 283 | (err, res) => { 284 | callback(err, res ? res.insertId : false, query); 285 | } 286 | ); 287 | }); 288 | }; 289 | 290 | // UPDATE SQL statement generator 291 | // 292 | connection.update = function (table, row, where, callback) { 293 | if (typeof where === 'function') { 294 | callback = where; 295 | this.fields(table, (err, fields) => { 296 | if (err) { 297 | const error = new Error('Error: Table "' + table + '" not found'); 298 | return callback(error); 299 | } 300 | let where = ''; 301 | const data = []; 302 | const rowKeys = Object.keys(row); 303 | let i, field, fieldName; 304 | for (i in fields) { 305 | field = fields[i]; 306 | fieldName = field.Field; 307 | if (rowKeys.includes(fieldName)) { 308 | if (!where && (field.Key === 'PRI' || field.Key === 'UNI')) { 309 | where = fieldName + '=' + this.escape(row[fieldName]); 310 | } else { 311 | data.push(fieldName + '=' + this.escape(row[fieldName])); 312 | } 313 | } 314 | } 315 | if (where) { 316 | const query = this.query( 317 | 'UPDATE ' + 318 | escapeIdentifier(table) + 319 | ' SET ' + 320 | data.join(', ') + 321 | ' WHERE ' + 322 | where, 323 | [], 324 | (err, res) => { 325 | callback(err, res ? res.changedRows : false, query); 326 | } 327 | ); 328 | } else { 329 | const e = new Error( 330 | 'Error: can not insert into "' + 331 | table + 332 | '" because there is no primary or unique key specified' 333 | ); 334 | this.emit('error', e); 335 | callback(e, false); 336 | } 337 | }); 338 | } else { 339 | where = this.where(where); 340 | if (where) { 341 | const data = []; 342 | let i; 343 | for (i in row) data.push(i + '=' + this.escape(row[i])); 344 | const query = this.query( 345 | 'UPDATE ' + 346 | escapeIdentifier(table) + 347 | ' SET ' + 348 | data.join(', ') + 349 | ' WHERE ' + 350 | where, 351 | [], 352 | (err, res) => { 353 | callback(err, res ? res.changedRows : false, query); 354 | } 355 | ); 356 | } else { 357 | const e = new Error( 358 | 'Error: can update "' + 359 | table + 360 | '", because "where" parameter is empty' 361 | ); 362 | this.emit('error', e); 363 | callback(e, false); 364 | } 365 | } 366 | }; 367 | 368 | // INSERT OR UPDATE SQL statement generator 369 | // 370 | connection.upsert = function (table, row, callback) { 371 | this.fields(table, (err, fields) => { 372 | if (err) { 373 | const error = new Error('Error: Table "' + table + '" not found'); 374 | return callback(error); 375 | } 376 | const rowKeys = Object.keys(row); 377 | let uniqueKey = ''; 378 | let i, field, fieldName; 379 | for (i in fields) { 380 | field = fields[i]; 381 | fieldName = field.Field; 382 | if ( 383 | !uniqueKey && 384 | (field.Key === 'PRI' || field.Key === 'UNI') && 385 | rowKeys.includes(fieldName) 386 | ) { 387 | uniqueKey = fieldName; 388 | } 389 | } 390 | if (rowKeys.includes(uniqueKey)) { 391 | this.queryValue( 392 | 'SELECT count(*) FROM ' + 393 | escapeIdentifier(table) + 394 | ' WHERE ' + 395 | uniqueKey + 396 | '=' + 397 | this.escape(row[uniqueKey]), 398 | [], 399 | (err, count) => { 400 | if (count === 1) this.update(table, row, callback); 401 | else this.insert(table, row, callback); 402 | } 403 | ); 404 | } else { 405 | const e = new Error( 406 | 'Error: can not insert or update table "' + 407 | table + 408 | '", primary or unique key is not specified' 409 | ); 410 | this.emit('error', e); 411 | callback(e, false); 412 | } 413 | }); 414 | }; 415 | 416 | // DELETE SQL statement generator 417 | // callback(err, rowCount or false) 418 | // 419 | connection.delete = function (table, where, callback) { 420 | where = this.where(where); 421 | if (where) { 422 | const query = this.query( 423 | 'DELETE FROM ' + escapeIdentifier(table) + ' WHERE ' + where, 424 | [], 425 | (err, res) => { 426 | callback(err, res ? res.affectedRows : false, query); 427 | } 428 | ); 429 | } else { 430 | const e = new Error( 431 | 'Error: can not delete from "' + 432 | table + 433 | '", because "where" parameter is empty' 434 | ); 435 | this.emit('error', e); 436 | callback(e, false); 437 | } 438 | }; 439 | } 440 | }; 441 | 442 | const introspection = connection => { 443 | if (!connection._mixedIntrospection) { 444 | connection._mixedIntrospection = true; 445 | 446 | // Get primary key metadata 447 | // callback(err, row) 448 | // 449 | connection.primary = function (table, callback) { 450 | this.queryRow( 451 | 'SHOW KEYS FROM ' + 452 | escapeIdentifier(table) + 453 | ' WHERE Key_name = "PRIMARY"', 454 | [], 455 | (err, res) => { 456 | if (err) res = false; 457 | callback(err, res); 458 | } 459 | ); 460 | }; 461 | 462 | // Get foreign key metadata 463 | // callback(err, foreign) 464 | // 465 | connection.foreign = function (table, callback) { 466 | this.queryHash( 467 | 'SELECT CONSTRAINT_NAME, COLUMN_NAME, ORDINAL_POSITION, ' + 468 | 'POSITION_IN_UNIQUE_CONSTRAINT, REFERENCED_TABLE_NAME, ' + 469 | 'REFERENCED_COLUMN_NAME FROM information_schema.KEY_COLUMN_USAGE ' + 470 | 'WHERE REFERENCED_TABLE_NAME IS NOT NULL AND ' + 471 | 'CONSTRAINT_SCHEMA = DATABASE() AND TABLE_NAME = ? ' + 472 | 'ORDER BY REFERENCED_TABLE_NAME', 473 | [table], 474 | (err, res) => { 475 | if (err) res = false; 476 | callback(err, res); 477 | } 478 | ); 479 | }; 480 | 481 | // Get table constraints metadata 482 | // callback(err, constraints) 483 | // 484 | connection.constraints = function (table, callback) { 485 | this.queryHash( 486 | 'SELECT CONSTRAINT_NAME, UNIQUE_CONSTRAINT_NAME, ' + 487 | 'REFERENCED_TABLE_NAME, MATCH_OPTION, UPDATE_RULE, DELETE_RULE ' + 488 | 'FROM information_schema.REFERENTIAL_CONSTRAINTS ' + 489 | 'WHERE TABLE_NAME = ? ' + 490 | 'ORDER BY CONSTRAINT_NAME', 491 | [table], 492 | (err, res) => { 493 | if (err) res = false; 494 | callback(err, res); 495 | } 496 | ); 497 | }; 498 | 499 | // Get table fields metadata 500 | // callback(err, fields) 501 | // 502 | connection.fields = function (table, callback) { 503 | this.queryHash( 504 | 'SHOW FULL COLUMNS FROM ' + escapeIdentifier(table), 505 | [], 506 | (err, res) => { 507 | if (err) res = false; 508 | callback(err, res); 509 | } 510 | ); 511 | }; 512 | 513 | // Get connection databases array 514 | // callback(err, databases) 515 | // 516 | connection.databases = function (callback) { 517 | this.queryCol('SHOW DATABASES', [], (err, res) => { 518 | if (err) res = false; 519 | callback(err, res); 520 | }); 521 | }; 522 | 523 | // Get database tables list 524 | // callback(err, tables) 525 | // 526 | connection.databaseTables = function (database, callback) { 527 | this.queryHash( 528 | 'SELECT TABLE_NAME, TABLE_TYPE, ENGINE, VERSION, ROW_FORMAT, ' + 529 | 'TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH, MAX_DATA_LENGTH, ' + 530 | 'INDEX_LENGTH, DATA_FREE, AUTO_INCREMENT, CREATE_TIME, ' + 531 | 'UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, CHECKSUM, ' + 532 | 'CREATE_OPTIONS, TABLE_COMMENT ' + 533 | 'FROM information_schema.TABLES WHERE TABLE_SCHEMA = ?', 534 | [database], 535 | (err, res) => { 536 | if (err) res = false; 537 | callback(err, res); 538 | } 539 | ); 540 | }; 541 | 542 | // Get current database table metadata 543 | // callback(err, tables) 544 | // 545 | connection.tables = function (callback) { 546 | this.queryHash( 547 | 'SELECT TABLE_NAME, TABLE_TYPE, ENGINE, VERSION, ROW_FORMAT, ' + 548 | 'TABLE_ROWS, AVG_ROW_LENGTH, DATA_LENGTH, MAX_DATA_LENGTH, ' + 549 | 'INDEX_LENGTH, DATA_FREE, AUTO_INCREMENT, CREATE_TIME, ' + 550 | 'UPDATE_TIME, CHECK_TIME, TABLE_COLLATION, CHECKSUM, ' + 551 | 'CREATE_OPTIONS, TABLE_COMMENT ' + 552 | 'FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()', 553 | [], 554 | (err, res) => { 555 | if (err) res = false; 556 | callback(err, res); 557 | } 558 | ); 559 | }; 560 | 561 | // Get table metadata info 562 | // callback(err, metadata) 563 | // 564 | connection.tableInfo = function (table, callback) { 565 | this.queryRow('SHOW TABLE STATUS LIKE ?', [table], (err, res) => { 566 | if (err) res = false; 567 | callback(err, res); 568 | }); 569 | }; 570 | 571 | // Get table indexes metadata 572 | // callback(err, indexes) 573 | // 574 | connection.indexes = function (table, callback) { 575 | this.query( 576 | 'SHOW INDEX FROM ' + escapeIdentifier(table), 577 | [], 578 | (err, res) => { 579 | const result = {}; 580 | if (err) { 581 | callback(err, false); 582 | return; 583 | } 584 | let i, row; 585 | for (i in res) { 586 | row = res[i]; 587 | result[row.Key_name] = row; 588 | } 589 | callback(err, result); 590 | } 591 | ); 592 | }; 593 | 594 | // Get server process list 595 | // callback(err, processes) 596 | // 597 | connection.processes = function (callback) { 598 | this.query( 599 | 'SELECT * FROM information_schema.PROCESSLIST', 600 | [], 601 | (err, res) => { 602 | if (err) res = false; 603 | callback(err, res); 604 | } 605 | ); 606 | }; 607 | 608 | // Get server global variables 609 | // callback(err, variables) 610 | // 611 | connection.globalVariables = function (callback) { 612 | this.queryKeyValue( 613 | 'SELECT * FROM information_schema.GLOBAL_VARIABLES', 614 | [], 615 | (err, res) => { 616 | if (err) res = false; 617 | callback(err, res); 618 | } 619 | ); 620 | }; 621 | 622 | // Get server global status 623 | // callback(err, status) 624 | // 625 | connection.globalStatus = function (callback) { 626 | this.queryKeyValue( 627 | 'SELECT * FROM information_schema.GLOBAL_STATUS', 628 | [], 629 | (err, res) => { 630 | if (err) res = false; 631 | callback(err, res); 632 | } 633 | ); 634 | }; 635 | 636 | // Get database users 637 | // callback(err, users) 638 | // 639 | connection.users = function (callback) { 640 | this.query('SELECT * FROM mysql.user', [], (err, res) => { 641 | if (err) res = false; 642 | callback(err, res); 643 | }); 644 | }; 645 | } 646 | }; 647 | 648 | module.exports = { 649 | upgrade, 650 | introspection, 651 | }; 652 | --------------------------------------------------------------------------------