├── .eslintrc.json ├── .gitignore ├── API_DOCUMENTATION.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENCE.md ├── README.md ├── nodemon.json ├── package-lock.json ├── package.json ├── src ├── _types │ ├── Contracts.ts │ ├── NucleoListType.ts │ ├── NucleoObjectType.ts │ ├── NucleoPrimitiveType.ts │ ├── State.ts │ └── Update.ts ├── executeListeners.ts ├── index.ts ├── indexSearch.ts ├── nucleoTypes │ ├── NucleoList.ts │ ├── NucleoObject.ts │ └── primitive.ts ├── save.ts ├── store.ts └── subscribe.ts ├── tests ├── cloneState.spec.ts ├── nucleoTypes │ ├── NucleoFunction.spec.ts │ ├── NucleoList.spec.ts │ ├── NucleoNumberAssertion.spec.ts │ └── NucleoStringAssertion.spec.ts ├── store.spec.ts ├── subscribe.spec.ts └── update.spec.ts └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | "plugin:@typescript-eslint/recommended" 9 | ], 10 | "parser": "@typescript-eslint/parser", 11 | "parserOptions": { 12 | "ecmaVersion": 12, 13 | "sourceType": "module" 14 | }, 15 | "plugins": [ 16 | "@typescript-eslint" 17 | ], 18 | "rules": { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | npm-debug.log 4 | 5 | # compiled files folder 6 | dist 7 | -------------------------------------------------------------------------------- /API_DOCUMENTATION.md: -------------------------------------------------------------------------------- 1 | - [Installation](#installation) 2 | - [Usage](#usage) 3 | - [Contracts](#contracts) 4 | - [Types](#types) 5 | - [NucleoObject](#creating-nucleoobject) 6 | - [Anatomy](#nucleoobject-anatomy) 7 | - [Usage](#nucleoobject-usage) 8 | - [NucleoList](#creating-nucleolist) 9 | - [Anatomy](#nucleolist-anatomy) 10 | - [Usage](#nucleolist-usage) 11 | - [NucleoString](#creating-nucleostring) 12 | - [NucleoNumber](#creating-nucleonumber) 13 | - [NucleoBoolean](#creating-nucleoboolean) 14 | - [NucleoStringAssertion](#creating-nucleostringassertion) 15 | - [Anatomy](#nucleostringassertion-anatomy) 16 | - [Usage](#nucleostringassertion-usage) 17 | - [NucleoNumberAssertion](#creating-nucleonumberassertion) 18 | - [Anatomy](#nucleonumberassertion-anatomy) 19 | - [Usage](#nucleonumberassertion-usage) 20 | - [Creating the store](#creating-the-store) 21 | - [Dispatching and updating the store](#dispatching-and-updating-the-store) 22 | - [Update and Dispatch function signature](#Update-and-Dispatch-function-signature) 23 | - [Get contracts in store](#get-contracts-in-store) 24 | - [Subscribing to changes](#subscribing-to-changes) 25 | - [Error management](#error-management) 26 | 27 | ## Installation 28 | 29 | Using NPM: 30 | 31 | ``` 32 | npm install nucleojs --save 33 | ``` 34 | 35 | Using Yarn: 36 | 37 | ``` 38 | yarn add nucleojs 39 | ``` 40 | 41 | ## Usage 42 | 43 | ```javascript 44 | import { 45 | NucleoString, 46 | NucleoNumber, 47 | NucleoBoolean, 48 | NucleoObject, 49 | createStore 50 | } from 'nucleojs'; 51 | 52 | const fullNameContract = new NucleoObject({ 53 | name: 'fullName', 54 | fields: { 55 | firstName: NucleoString, 56 | lastName: NucleoString 57 | } 58 | }); 59 | 60 | const userContract = new NucleoObject({ 61 | name: 'user', 62 | fields: { 63 | name: fullNameContract, 64 | age: NucleoNumber, 65 | disabled: NucleoBoolean 66 | } 67 | }); 68 | 69 | const productsContract = new NucleoObject({ 70 | name: 'products', 71 | fields: { 72 | title: NucleoString, 73 | price: NucleoNumber 74 | } 75 | }); 76 | 77 | const contracts = { 78 | user: userContract, 79 | products: productsContract 80 | }; 81 | 82 | const store = createStore(contracts); 83 | const { dispatch, update, cloneState, subscribe } = store; 84 | 85 | const user = dispatch('user')({ name: { firstName: 'John', lastName: 'Nor' }, age: 27 }); 86 | // it'll save the data to store properly 87 | 88 | console.log(user); 89 | /* 90 | { 91 | status: 'OK', 92 | errors: [], 93 | data: { 94 | name: { 95 | firstName: 'John', 96 | lastName: 'Nor' 97 | }, 98 | age: 27 99 | }, 100 | } 101 | */ 102 | ``` 103 | 104 | ## Contracts 105 | 106 | Contracts are how your data is defined inside Nucleo. Basically contracts is how you define your `NucleoObject`s: 107 | 108 | ```javascript 109 | const userContract = new NucleoObject({ 110 | name: 'user', 111 | fields: { 112 | name: NucleoString, 113 | age: NucleoNumber, 114 | taxId: NucleoString 115 | } 116 | }); 117 | ``` 118 | 119 | The example below we defined a contract named as `user` and data in this contract will look like this: 120 | 121 | ```javascript 122 | { 123 | name: 'Joseph Nor', 124 | age: 28, 125 | taxId: '987611654967' 126 | } 127 | ``` 128 | 129 | Contracts are organized in a tree structure to be sent to Nucleo and create the store. Let's say you created the user contract above and a few more, they would behave like this to create the store: 130 | 131 | ``` 132 | const contracts = { 133 | user: userContract, 134 | products: productsContract, 135 | highlights: highlightsContract 136 | }; 137 | ``` 138 | 139 | `userContract`, `productsContract` and `highlightsContract` are instances of `NucleoObject`. Note that contracts are always instances of `NucleoObject`, if you try to create a store differently, it'll fail. 140 | 141 | You can think in Nucleo contracts as data model contracts, as it is. 142 | 143 | ## Types 144 | 145 | ### Creating NucleoObject 146 | 147 | #### NucleoObject Anatomy 148 | 149 | ```javascript 150 | NucleoObject({ 151 | name: String, 152 | fields: Object 153 | }); 154 | ``` 155 | 156 | Inside NucleoObject are expected two keys: 157 | 158 | - `name`: every NucleoObject contract must have an unique name and this field is used to create and identify your item in your store. 159 | - `fields`: is a plain object for the expected fields in this NucleoObject. Inside `fields` must have first level keys with Nucleo types values. If it's necessary to nest, you may create another NucleoObject inside this one. 160 | 161 | #### NucleoObject Usage 162 | 163 | ```javascript 164 | import { 165 | NucleoString, 166 | NucleoNumber, 167 | NucleoBoolean, 168 | NucleoObject 169 | } from 'nucleojs' 170 | 171 | const fullNameContract = new NucleoObject({ 172 | name: 'fullName', 173 | fields: { 174 | firstName: NucleoString, 175 | lastName: NucleoString 176 | } 177 | }); 178 | 179 | const userContract = new NucleoObject({ 180 | name: 'user', 181 | fields: { 182 | name: fullNameContract, 183 | age: NucleoNumber, 184 | disabled: NucleoBoolean 185 | } 186 | }); 187 | 188 | const productsContract = new NucleoObject({ 189 | name: 'products', 190 | fields: { 191 | title: NucleoString, 192 | price: NucleoNumber 193 | } 194 | }); 195 | 196 | const contracts = { 197 | user: userContract, 198 | products: productsContract 199 | }; 200 | ``` 201 | 202 | ### Creating NucleoList 203 | 204 | #### NucleoList Anatomy 205 | 206 | ```javascript 207 | NucleoList(NucleoType); 208 | ``` 209 | 210 | Inside Nucleo you can create lists of Nucleo types in your contracts. `NucleoList` accepts one argument which is expected a Nucleo type (`NucleoObject` or any Nucleo primitive are accepted). If you try to commit a new `NucleoList` with argument different from a Nucleo type it'll throw. 211 | 212 | #### NucleoList Usage 213 | 214 | ```javascript 215 | import { 216 | NucleoString, 217 | NucleoNumber, 218 | NucleoBoolean, 219 | NucleoObject, 220 | NucleoList 221 | } from 'nucleojs' 222 | 223 | const fullNameContract = new NucleoObject({ 224 | name: 'fullName', 225 | fields: { 226 | firstName: NucleoString, 227 | lastName: NucleoString 228 | } 229 | }); 230 | 231 | const userContract = new NucleoObject({ 232 | name: 'user', 233 | fields: { 234 | name: fullNameContract, 235 | age: NucleoNumber, 236 | disabled: NucleoBoolean, 237 | } 238 | }); 239 | 240 | const usersContract = new NucleoObject({ 241 | name: 'users', 242 | fields: { 243 | data: new NucleoList(userContract) 244 | } 245 | }); 246 | 247 | const contracts = { 248 | users: usersContract 249 | }; 250 | ``` 251 | 252 | ### Creating NucleoString 253 | 254 | ```javascript 255 | NucleoString: String; 256 | ``` 257 | 258 | **Usage** 259 | 260 | ```javascript 261 | const personalInfoType = new NucleoObject({ 262 | name: 'personalInfo', 263 | fields: { 264 | firstName: NucleoString, 265 | lastName: NucleoString 266 | } 267 | }); 268 | ``` 269 | 270 | ### Creating NucleoNumber 271 | 272 | ```javascript 273 | NucleoNumber: Number; 274 | ``` 275 | 276 | **Usage** 277 | 278 | ```javascript 279 | const personalInfoType = new NucleoObject({ 280 | name: 'personalInfo', 281 | fields: { 282 | firstName: NucleoString, 283 | lastName: NucleoString, 284 | age: NucleoNumber 285 | } 286 | }); 287 | ``` 288 | 289 | ### Creating NucleoBoolean 290 | 291 | ```javascript 292 | NucleoBoolean: Boolean; 293 | ``` 294 | 295 | **Usage** 296 | 297 | ```javascript 298 | const userStatusType = new NucleoObject({ 299 | name: 'userStatus', 300 | fields: { 301 | disabled: NucleoBoolean 302 | } 303 | }); 304 | ``` 305 | 306 | ### Creating NucleoStringAssertion 307 | 308 | #### NucleoStringAssertion Anatomy 309 | 310 | `NucleoStringAssertion` receives a function as argument and execute it for validation and serialization in attempts to save data to its item. Nucleo validate the value type already and there is no need to check if it's a `string`. 311 | 312 | ```javascript 313 | myFunc = value => Boolean 314 | 315 | NucleoStringAssertion(myFunc) 316 | ``` 317 | 318 | - `myFunc`: a function declaration under your control, you declare it for be used as rule for validating that field. It must return a boolean according to following rules: 319 | - `true`: the assertion is as expected and can be saved in store; 320 | - `false`: the assertion is not what's expected and it'll make Nucleo avoid saving data. 321 | - `value`: value that is being validated to be saved in store; 322 | 323 | #### NucleoStringAssertion Usage 324 | 325 | ```javascript 326 | function taxIdValidation(value:string) { 327 | return value.length === 11; 328 | } 329 | 330 | const userType = new NucleoObject({ 331 | name: 'user', 332 | fields: { 333 | name: NucleoString, 334 | taxId: new NucleoStringAssertion(taxIdValidation) 335 | } 336 | }); 337 | ``` 338 | 339 | ### Creating NucleoNumberAssertion 340 | 341 | #### NucleoNumberAssertion Anatomy 342 | 343 | `NucleoNumberAssertion` receives a function as argument and execute it for validation and serialization in attempts to save data to its item. Nucleo validate the value type already and there is no need to check if it's a `number`. 344 | 345 | ```javascript 346 | myFunc = value => Boolean 347 | 348 | NucleoNumberAssertion(myFunc) 349 | ``` 350 | 351 | - `myFunc`: a function declaration under your control, you declare it for be used as rule for validating that field. It must return a boolean according to following rules: 352 | - `true`: the assertion is as expected and can be saved in store; 353 | - `false`: the assertion is not what's expected and it'll make Nucleo avoid saving data. 354 | - `value`: value that is being validated to be saved in store; 355 | 356 | #### NucleoNumberAssertion Usage 357 | 358 | ```javascript 359 | function ageValidation(value:number) { 360 | return value < 100; 361 | } 362 | 363 | const userType = new NucleoObject({ 364 | name: 'user', 365 | fields: { 366 | name: NucleoString, 367 | age: new NucleoNumberAssertion(ageValidation) 368 | } 369 | }); 370 | ``` 371 | 372 | ## Creating the store 373 | 374 | ```javascript 375 | import { createStore } from 'nucleojs'; 376 | import * as contracts from './contracts'; 377 | 378 | const store = createStore(contracts); // send contracts to create the store 379 | const { dispatch, update, cloneState, subscribe } = store; // these 4 functions are returned from store creation 380 | ``` 381 | 382 | ## Dispatching and updating the store 383 | 384 | Nucleo provides two methods of saving data, used for different approaches. 385 | 386 | **dispatch:** works for saving data according to the full contract, used to save the very first contract state in the store or to update the whole contract in the store; 387 | 388 | **update:** works for updating parts of data, it performs a index search in the object and save it. `update` will fail if you try to first save a contract to the store using it. 389 | 390 | --- 391 | 392 | Dispatch function, considering user contract above: 393 | 394 | ```javascript 395 | 396 | let user = dispatch('user')({ name: { firstName: 'John', lastName: 'Nor' } }); 397 | // it'll fail because it's missing age field 398 | 399 | user = dispatch('user')({ name: { firstName: 'John', lastName: 'Nor' }, age: 27 }); 400 | // it'll save the data to store properly 401 | 402 | console.log(user); 403 | /* 404 | { 405 | status: 'OK', 406 | errors: [], 407 | data: { 408 | name: { 409 | firstName: 'John', 410 | lastName: 'Nor' 411 | }, 412 | age: 27 413 | }, 414 | } 415 | */ 416 | ``` 417 | 418 | Update function, considering user contract above: 419 | 420 | ```javascript 421 | const user = update('user')({ name: { firstName: 'Robert' }}); 422 | // it'll update only the user first name and only if this item has been already created in the store before 423 | 424 | console.log(user); 425 | /* 426 | { 427 | status: 'OK', 428 | errors: [], 429 | data: { 430 | name: { 431 | firstName: 'Robert', 432 | }, 433 | }, 434 | } 435 | 436 | It'll return the data you asked to save. To receive the new store, you will have to clone this state or subscribe to Nucleo changes through subscribe function 437 | Check documentation for cloneState in the next section 438 | */ 439 | const newUser = cloneState('user'); 440 | console.log(newUser); 441 | /* 442 | { 443 | name: { 444 | firstName: 'Robert', 445 | lastName: 'Nor', 446 | }, 447 | age: 27, 448 | } 449 | */ 450 | ``` 451 | 452 | #### Update and Dispatch function signature 453 | 454 | `update` and `dispatch` functions have the same signature albeit a discrete behavioral difference (you can find this difference in . 455 | 456 | **Both are curried functions:** 457 | 458 | - `update()()`; 459 | - `dispatch()()`. 460 | 461 | ``: a `string` for the contract name you want to update or dispatch. It's the `name` field for every new `NucleoObject` in the contracts definition. Those must be unique. You can find more information about contracts in API_DOCUMENTATION.md. 462 | 463 | ``: must follow its contract model. For understanding how to use `update` and `dispatch` for saving data, check API_DOCUMENTATION.md in "Dispatching and updating the store" section. 464 | 465 | **Both return the same object interface:** 466 | 467 | ```javascript 468 | { 469 | status: 'OK' | 'NOK', // a string return 'OK' for success cases and 'NOK' for errors 470 | errors: [], // in case of errors, it will return the list of errors 471 | data: { ... } // the data you just tried to save in store 472 | } 473 | ``` 474 | 475 | - `status`: a string return 'OK' for success cases and 'NOK' for errors; 476 | - `errors`: a list of objects containing the errors in this operation. Usually related to contract violations. You can find more details in API_DOCUMENTATION.md at "Error management" area. 477 | - `data`: This is the exactly same object you tried to save at store for comparison reasons in cases of errors. 478 | 479 | ## Getting a state clone from store 480 | 481 | The `cloneState` function receives one argument which is the contract name in store, performs a deep clone using the contracts data model as a map to predict the key/values of that contract and be able to return it with great performance. 482 | 483 | ```javascript 484 | const user = cloneState('user'); 485 | console.log(user); 486 | /* 487 | { 488 | name: { 489 | firstName: 'Robert', 490 | lastName: 'Nor' 491 | }, 492 | age: 27 493 | } 494 | */ 495 | ``` 496 | 497 | ## Subscribing to changes 498 | 499 | The `subscribe` function receives as argument a function and for each update in the store, Nucleo executes the listener passing as parameter an object containing `contractName` and `data`: 500 | 501 | - `contractName`: `string` containing the updated contract name; 502 | - `data`: `Object` containing a deep clone of the data saved in store. 503 | 504 | ```javascript 505 | const listener = ({ contractName, data }) => { 506 | console.log(data); 507 | /* 508 | { 509 | name: { 510 | firstName: 'Robert', 511 | lastName: 'Nor' 512 | }, 513 | age: 26 514 | } 515 | */ 516 | } 517 | subscribe(listener); // if it's not a function, Nucleo will throw an error 518 | update('user')({ age: 26 }); 519 | ``` 520 | 521 | And inside Nucleo, your listener will be executed like this: 522 | 523 | ```javascript 524 | listener({ contractName, data }); // This way you can understand better what was updated and consult Nucleo store as you wish 525 | ``` 526 | 527 | ## Unsubscribing 528 | 529 | Subscribe function returns a `unsubscribe` function that can understand context and properly unsubscribe the right listener. 530 | 531 | ```javascript 532 | const unsubscribe = subscribe(func); 533 | 534 | // when you need to unsubscribe is just call its function 535 | unsubscribe(); // done :) 536 | ``` 537 | 538 | ## Subscribing multiple listeners 539 | 540 | Nucleo provides only one way of subscribing to changes, but saves the listeners as a list of functions inside of it. You can execute multiple times `subscribe` with all your listeners: 541 | 542 | ```javascript 543 | subscribe(listener1); 544 | subscribe(listener2); 545 | subscribe(listener3); 546 | subscribe(listener4); 547 | 548 | // or 549 | 550 | const listeners = [listener1, listener2, listener3, listener4]; 551 | 552 | listeners.map(listener => subscribe(listener)); 553 | ``` 554 | 555 | Nucleo will execute one by one, following the order you provided. 556 | 557 | ## Error management 558 | 559 | Nucleo makes error management easy by type checking every level of contracts and returning an Object human and machine readable. The `update` and `dispatch` methods return an object with the following structure: 560 | 561 | ```javascript 562 | { 563 | status: 'NOK', 564 | errors: [ 565 | { 566 | error: ' is not in contract and can not be saved in store', 567 | contract: 'contractName', 568 | field: 'fieldName' 569 | } 570 | ], 571 | data: { ... } // the data you just tried to save in store 572 | } 573 | ``` 574 | 575 | Code example: 576 | 577 | ```javascript 578 | import { 579 | NucleoString, 580 | NucleoObject 581 | } from 'nucleojs'; 582 | 583 | const userType = new NucleoObject({ 584 | name: 'user', 585 | fields: { 586 | name: NucleoString, 587 | } 588 | }); 589 | 590 | const contracts = { 591 | user: userType 592 | }; 593 | 594 | const { update } = createStore(contracts); // send contracts to create the store 595 | 596 | const user = update('user')({ age: 140 }); 597 | 598 | console.log(user.errors); // here you'll find the error below: 599 | /* 600 | 601 | [ 602 | { 603 | error: 'age field does not match its rules according to user contract', 604 | contract: 'user', 605 | field: 'age' 606 | } 607 | ] 608 | } 609 | */ 610 | ``` 611 | 612 | In cases with no errors, `errors` list will be an empty list and `status` will be `OK` 613 | 614 | ```javascript 615 | { 616 | status: 'OK', 617 | errors: [] 618 | data: { ... } // the data you just tried to save in store 619 | } 620 | ``` 621 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at matmarsiglio@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | Nucleo is open to any contribution made by community. And by contributing to Nucleo, you agree to our [code of conduct](https://github.com/mtmr0x/nucleo/blob/master/CODE_OF_CONDUCT.md) 4 | 5 | ### Bugs and improvements 6 | 7 | Open a issue with the prefix [BUG] or [FEATURE REQUEST] for one of those cases with no restrictions, and try to clarify all your points bringing examples and well-founded arguments. If you need help in something, just make it clear at the beginning of your issue. 8 | 9 | ### Pull Requests 10 | 11 | Once you want to fix something for Nucleo, you can just go ahead and do it, but for making people know the problem and that you're working on it (and maybe can get even more information) open an issue about it, and if necessary, just point that you desire to fix it, or if some help is needed. 12 | 13 | For new features, it's highly recommended to open an issue first and discuss more to make sure this feature is really required to the project. 14 | 15 | ### Roadmap 16 | 17 | Every approved issue as features and issues for fixes will be placed at Nucleo roadmap, in this repository milestones. 18 | 19 | ### Critical fixes 20 | 21 | In case of critical fixes, which applies to everything that would directly interfere in Nucleo functionalities, we'll work hard to solve it and publish a new minor patch as soon as possible. 22 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) Matheus Marsiglio. http://mtmr0x.com 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nucleo 2 | 3 | Nucleo creates and manages a strongly typed and predictable state container. 4 | 5 | ## Roadmap 6 | 7 | It's in this project milestones https://github.com/mtmr0x/nucleo/milestones; 8 | 9 | For requesting any feature, please open an issue with the prefix "[FEATURE REQUEST]". 10 | 11 | ## Why 12 | 13 | JavaScript is a really dynamic language which we can't always rely in the language resilience from types perspective. Every project has types problems and developers can not make sure all the time the data is predictable. Inspired by how GraphQL does a great job with safety and trustful data and Redux by its simplicity on storing state, Nucleo was idealized to make sure the data model (contracts) and the data types are expected and reliable. 14 | 15 | ## Installation 16 | 17 | Using NPM: 18 | 19 | ``` 20 | npm install nucleojs --save 21 | ``` 22 | 23 | Using Yarn: 24 | 25 | ``` 26 | yarn add nucleojs 27 | ``` 28 | 29 | ## Documentation 30 | 31 | The links below take you to our `API_DOCUMENTATION.md` file present in this repository with deeper information and documentation to Nucleo usage. 32 | 33 | - [Installation](API_DOCUMENTATION.md#installation) 34 | - [Usage](API_DOCUMENTATION.md#usage) 35 | - [Contracts](API_DOCUMENTATION.md#contracts) 36 | - [Types](API_DOCUMENTATION.md#types) 37 | - [NucleoObject](API_DOCUMENTATION.md#creating-nucleoobject) 38 | - [Anatomy](API_DOCUMENTATION.md#nucleoobject-anatomy) 39 | - [Usage](API_DOCUMENTATION.md#nucleoobject-usage) 40 | - [NucleoList](API_DOCUMENTATION.md#creating-nucleolist) 41 | - [Anatomy](API_DOCUMENTATION.md#nucleolist-anatomy) 42 | - [Usage](API_DOCUMENTATION.md#nucleolist-usage) 43 | - [NucleoString](API_DOCUMENTATION.md#creating-nucleostring) 44 | - [NucleoNumber](API_DOCUMENTATION.md#creating-nucleonumber) 45 | - [NucleoBoolean](API_DOCUMENTATION.md#creating-nucleoboolean) 46 | - [NucleoStringAssertion](API_DOCUMENTATION.md#creating-nucleostringassertion) 47 | - [Anatomy](API_DOCUMENTATION.md#nucleostringassertion-anatomy) 48 | - [Usage](API_DOCUMENTATION.md#nucleostringassertion-usage) 49 | - [NucleoNumberAssertion](API_DOCUMENTATION.md#creating-nucleonumberassertion) 50 | - [Anatomy](API_DOCUMENTATION.md#nucleonumberassertion-anatomy) 51 | - [Usage](API_DOCUMENTATION.md#nucleonumberassertion-usage) 52 | - [Creating the store](API_DOCUMENTATION.md#creating-the-store) 53 | - [Dispatching and updating the store](API_DOCUMENTATION.md#dispatching-and-updating-the-store) 54 | - [Get contracts in store](API_DOCUMENTATION.md#get-contracts-in-store) 55 | - [Subscribing to changes](API_DOCUMENTATION.md#subscribing-to-changes) 56 | - [Unsubscribing](API_DOCUMENTATION.md#unsubscribing) 57 | - [Error management](API_DOCUMENTATION.md#error-management) 58 | 59 | ## Basic usage 60 | 61 | Nucleo is written in TypeScript and compatible with es2016+. Importing for a ECMAScript usage: 62 | 63 | ```javascript 64 | import { createStore } from 'nucleojs'; 65 | ``` 66 | 67 | Importing from Nucleo source for TypeScript usage just add `/src` after nucleojs module: 68 | 69 | ```javascript 70 | import { createStore } from 'nucleojs/src'; 71 | ``` 72 | 73 | ### Defining a data model (contract): 74 | 75 | ```javascript 76 | import { 77 | NucleoString, 78 | NucleoNumber, 79 | NucleoObject, 80 | createStore 81 | } from 'nucleojs' 82 | 83 | const completeNameContract = new NucleoObject({ 84 | name: 'completeNameContract', 85 | fields: { 86 | firstName: NucleoString, 87 | lastName: NucleoString 88 | } 89 | }); 90 | 91 | const userContract = new NucleoObject({ 92 | name: 'user', // don't need to be the same name as the variable, but need to be unique 93 | fields: { 94 | name: completeNameContract, 95 | age: NucleoNumber 96 | } 97 | }); 98 | 99 | const productsContract = new NucleoObject({ 100 | name: 'products', 101 | fields: { 102 | title: NucleoString 103 | } 104 | }); 105 | 106 | const contracts = { 107 | user: userContract, 108 | products: productsContract 109 | }; 110 | 111 | ``` 112 | 113 | ### Creating the store 114 | 115 | ```javascript 116 | import { createStore } from 'nucleojs'; 117 | import * as contracts from './contracts'; 118 | 119 | const store = createStore(contracts); // send contracts to create the store 120 | const { dispatch, update, cloneState, subscribe } = store; // these 4 functions are returned from store creation 121 | ``` 122 | 123 | ### Dispatching and updating the store 124 | 125 | Nucleo provides two methods of saving data, used for different approaches. 126 | 127 | **dispatch:** works for saving data according to the full contract, used to save the very first contract state in the store or to update the whole contract in the store; 128 | 129 | **update:** works for updating parts of data, it performs a index search in the object and save it. `update` will fail if you try to first save a contract to the store using it. 130 | 131 | --- 132 | 133 | Dispatch function, considering user contract above: 134 | 135 | ```javascript 136 | 137 | let user = dispatch('user')({ name: { firstName: 'John', lastName: 'Nor' } }); 138 | // it'll fail because it's missing age field 139 | 140 | user = dispatch('user')({ name: { firstName: 'John', lastName: 'Nor' }, age: 27 }); 141 | // it'll save the data to store properly 142 | 143 | console.log(user); 144 | /* 145 | { 146 | status: 'OK', 147 | errors: [], 148 | data: { 149 | name: { 150 | firstName: 'John', 151 | lastName: 'Nor' 152 | }, 153 | age: 27 154 | }, 155 | } 156 | */ 157 | ``` 158 | 159 | Update function, considering user contract above: 160 | 161 | ```javascript 162 | const user = update('user')({ name: { firstName: 'Robert' }}); 163 | // it'll update only the user first name and only if this item has been already created in the store before 164 | 165 | console.log(user); 166 | /* 167 | { 168 | status: 'OK', 169 | errors: [], 170 | data: { 171 | name: { 172 | firstName: 'Robert', 173 | }, 174 | }, 175 | } 176 | 177 | It'll return the data you asked to save. To receive the new store, you will have to clone this state or subscribe to Nucleo changes through subscribe function 178 | Check documentation for cloneState in the next section 179 | */ 180 | const newUser = cloneState('user'); 181 | console.log(newUser); 182 | /* 183 | { 184 | name: { 185 | firstName: 'Robert', 186 | lastName: 'Nor', 187 | }, 188 | age: 27, 189 | } 190 | */ 191 | ``` 192 | 193 | #### Update and Dispatch function signature 194 | 195 | `update` and `dispatch` functions have the same signature albeit a discrete behavioral difference (you can find this difference in . 196 | 197 | **Both are curried functions:** 198 | 199 | - `update()()`; 200 | - `dispatch()()`. 201 | 202 | ``: a `string` for the contract name you want to update or dispatch. It's the `name` field for every new `NucleoObject` in the contracts definition. Those must be unique. You can find more information about contracts in API_DOCUMENTATION.md. 203 | 204 | ``: must follow its contract model. For understanding how to use `update` and `dispatch` for saving data, check API_DOCUMENTATION.md in "Dispatching and updating the store" section. 205 | 206 | **Both return the same object interface:** 207 | 208 | ```javascript 209 | { 210 | status: 'OK' | 'NOK', // a string return 'OK' for success cases and 'NOK' for errors 211 | errors: [], // in case of errors, it will return the list of errors 212 | data: { ... } // the data you just tried to save in store 213 | } 214 | ``` 215 | 216 | - `status`: a string return 'OK' for success cases and 'NOK' for errors; 217 | - `errors`: a list of objects containing the errors in this operation. Usually related to contract violations. You can find more details in API_DOCUMENTATION.md at "Error management" area. 218 | - `data`: This is the exactly same object you tried to save at store for comparison reasons in cases of errors. 219 | 220 | ### Getting a state clone from store 221 | 222 | The `cloneState` function receives one argument which is the contract name in store, performs a deep clone using the contracts data model as a map to predict the key/values of that contract and be able to return it with great performance. 223 | 224 | ```javascript 225 | const user = cloneState('user'); 226 | console.log(user); 227 | /* 228 | { 229 | name: { 230 | firstName: 'Robert', 231 | lastName: 'Nor' 232 | }, 233 | age: 27 234 | } 235 | */ 236 | ``` 237 | 238 | ## Development 239 | 240 | ### Tasks available 241 | 242 | - `npm start` - Start development mode. 243 | - `npm run nodemon` - Start development mode and waiting for changes. 244 | - `npm run tests` - Run automated tests. 245 | - `npm run lint` - Validate syntax of all Typescript files. 246 | - `npm run compile` - Compile for production. 247 | 248 | ## Contributing 249 | 250 | Want to contribute? [Follow these recommendations](https://github.com/mtmr0x/nucleo/blob/master/CONTRIBUTING.md). 251 | 252 | ## Versioning 253 | 254 | To keep better organization of releases we follow the [Semantic Versioning 2.0.0](http://semver.org/) guidelines. 255 | 256 | ## Licence 257 | 258 | [MIT Licence](https://github.com/mtmr0x/nucleo/blob/master/LICENCE.md) © [Matheus Marsiglio](http://mtmr0x.com) 259 | -------------------------------------------------------------------------------- /nodemon.json: -------------------------------------------------------------------------------- 1 | { 2 | "watch": ["src"], 3 | "ext": "ts", 4 | "ignore": ["src/**/*.spec.ts"], 5 | "exec": "ts-node ./src/index.ts" 6 | } 7 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nucleojs", 3 | "version": "1.4.1", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.0.0", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", 10 | "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.0.0" 14 | } 15 | }, 16 | "@babel/highlight": { 17 | "version": "7.0.0", 18 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", 19 | "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", 20 | "dev": true, 21 | "requires": { 22 | "chalk": "^2.0.0", 23 | "esutils": "^2.0.2", 24 | "js-tokens": "^4.0.0" 25 | } 26 | }, 27 | "@eslint/eslintrc": { 28 | "version": "0.2.2", 29 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.2.tgz", 30 | "integrity": "sha512-EfB5OHNYp1F4px/LI/FEnGylop7nOqkQ1LRzCM0KccA2U8tvV8w01KBv37LbO7nW4H+YhKyo2LcJhRwjjV17QQ==", 31 | "dev": true, 32 | "requires": { 33 | "ajv": "^6.12.4", 34 | "debug": "^4.1.1", 35 | "espree": "^7.3.0", 36 | "globals": "^12.1.0", 37 | "ignore": "^4.0.6", 38 | "import-fresh": "^3.2.1", 39 | "js-yaml": "^3.13.1", 40 | "lodash": "^4.17.19", 41 | "minimatch": "^3.0.4", 42 | "strip-json-comments": "^3.1.1" 43 | }, 44 | "dependencies": { 45 | "debug": { 46 | "version": "4.3.1", 47 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 48 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 49 | "dev": true, 50 | "requires": { 51 | "ms": "2.1.2" 52 | } 53 | }, 54 | "ignore": { 55 | "version": "4.0.6", 56 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 57 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 58 | "dev": true 59 | }, 60 | "ms": { 61 | "version": "2.1.2", 62 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 63 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 64 | "dev": true 65 | }, 66 | "strip-json-comments": { 67 | "version": "3.1.1", 68 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 69 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 70 | "dev": true 71 | } 72 | } 73 | }, 74 | "@nodelib/fs.scandir": { 75 | "version": "2.1.3", 76 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", 77 | "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", 78 | "dev": true, 79 | "requires": { 80 | "@nodelib/fs.stat": "2.0.3", 81 | "run-parallel": "^1.1.9" 82 | } 83 | }, 84 | "@nodelib/fs.stat": { 85 | "version": "2.0.3", 86 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", 87 | "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", 88 | "dev": true 89 | }, 90 | "@nodelib/fs.walk": { 91 | "version": "1.2.4", 92 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", 93 | "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", 94 | "dev": true, 95 | "requires": { 96 | "@nodelib/fs.scandir": "2.1.3", 97 | "fastq": "^1.6.0" 98 | } 99 | }, 100 | "@types/chai": { 101 | "version": "4.2.11", 102 | "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.11.tgz", 103 | "integrity": "sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw==", 104 | "dev": true 105 | }, 106 | "@types/json-schema": { 107 | "version": "7.0.6", 108 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", 109 | "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", 110 | "dev": true 111 | }, 112 | "@types/json5": { 113 | "version": "0.0.29", 114 | "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", 115 | "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", 116 | "dev": true 117 | }, 118 | "@types/mocha": { 119 | "version": "5.2.7", 120 | "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", 121 | "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", 122 | "dev": true 123 | }, 124 | "@types/normalize-package-data": { 125 | "version": "2.4.0", 126 | "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", 127 | "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", 128 | "dev": true 129 | }, 130 | "@typescript-eslint/eslint-plugin": { 131 | "version": "4.9.1", 132 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.9.1.tgz", 133 | "integrity": "sha512-QRLDSvIPeI1pz5tVuurD+cStNR4sle4avtHhxA+2uyixWGFjKzJ+EaFVRW6dA/jOgjV5DTAjOxboQkRDE8cRlQ==", 134 | "dev": true, 135 | "requires": { 136 | "@typescript-eslint/experimental-utils": "4.9.1", 137 | "@typescript-eslint/scope-manager": "4.9.1", 138 | "debug": "^4.1.1", 139 | "functional-red-black-tree": "^1.0.1", 140 | "regexpp": "^3.0.0", 141 | "semver": "^7.3.2", 142 | "tsutils": "^3.17.1" 143 | }, 144 | "dependencies": { 145 | "debug": { 146 | "version": "4.3.1", 147 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 148 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 149 | "dev": true, 150 | "requires": { 151 | "ms": "2.1.2" 152 | } 153 | }, 154 | "lru-cache": { 155 | "version": "6.0.0", 156 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 157 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 158 | "dev": true, 159 | "requires": { 160 | "yallist": "^4.0.0" 161 | } 162 | }, 163 | "ms": { 164 | "version": "2.1.2", 165 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 166 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 167 | "dev": true 168 | }, 169 | "semver": { 170 | "version": "7.3.4", 171 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", 172 | "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", 173 | "dev": true, 174 | "requires": { 175 | "lru-cache": "^6.0.0" 176 | } 177 | }, 178 | "yallist": { 179 | "version": "4.0.0", 180 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 181 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 182 | "dev": true 183 | } 184 | } 185 | }, 186 | "@typescript-eslint/experimental-utils": { 187 | "version": "4.9.1", 188 | "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.9.1.tgz", 189 | "integrity": "sha512-c3k/xJqk0exLFs+cWSJxIjqLYwdHCuLWhnpnikmPQD2+NGAx9KjLYlBDcSI81EArh9FDYSL6dslAUSwILeWOxg==", 190 | "dev": true, 191 | "requires": { 192 | "@types/json-schema": "^7.0.3", 193 | "@typescript-eslint/scope-manager": "4.9.1", 194 | "@typescript-eslint/types": "4.9.1", 195 | "@typescript-eslint/typescript-estree": "4.9.1", 196 | "eslint-scope": "^5.0.0", 197 | "eslint-utils": "^2.0.0" 198 | } 199 | }, 200 | "@typescript-eslint/parser": { 201 | "version": "4.9.1", 202 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.9.1.tgz", 203 | "integrity": "sha512-Gv2VpqiomvQ2v4UL+dXlQcZ8zCX4eTkoIW+1aGVWT6yTO+6jbxsw7yQl2z2pPl/4B9qa5JXeIbhJpONKjXIy3g==", 204 | "dev": true, 205 | "requires": { 206 | "@typescript-eslint/scope-manager": "4.9.1", 207 | "@typescript-eslint/types": "4.9.1", 208 | "@typescript-eslint/typescript-estree": "4.9.1", 209 | "debug": "^4.1.1" 210 | }, 211 | "dependencies": { 212 | "debug": { 213 | "version": "4.3.1", 214 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 215 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 216 | "dev": true, 217 | "requires": { 218 | "ms": "2.1.2" 219 | } 220 | }, 221 | "ms": { 222 | "version": "2.1.2", 223 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 224 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 225 | "dev": true 226 | } 227 | } 228 | }, 229 | "@typescript-eslint/scope-manager": { 230 | "version": "4.9.1", 231 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.9.1.tgz", 232 | "integrity": "sha512-sa4L9yUfD/1sg9Kl8OxPxvpUcqxKXRjBeZxBuZSSV1v13hjfEJkn84n0An2hN8oLQ1PmEl2uA6FkI07idXeFgQ==", 233 | "dev": true, 234 | "requires": { 235 | "@typescript-eslint/types": "4.9.1", 236 | "@typescript-eslint/visitor-keys": "4.9.1" 237 | } 238 | }, 239 | "@typescript-eslint/types": { 240 | "version": "4.9.1", 241 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.9.1.tgz", 242 | "integrity": "sha512-fjkT+tXR13ks6Le7JiEdagnwEFc49IkOyys7ueWQ4O8k4quKPwPJudrwlVOJCUQhXo45PrfIvIarcrEjFTNwUA==", 243 | "dev": true 244 | }, 245 | "@typescript-eslint/typescript-estree": { 246 | "version": "4.9.1", 247 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.9.1.tgz", 248 | "integrity": "sha512-bzP8vqwX6Vgmvs81bPtCkLtM/Skh36NE6unu6tsDeU/ZFoYthlTXbBmpIrvosgiDKlWTfb2ZpPELHH89aQjeQw==", 249 | "dev": true, 250 | "requires": { 251 | "@typescript-eslint/types": "4.9.1", 252 | "@typescript-eslint/visitor-keys": "4.9.1", 253 | "debug": "^4.1.1", 254 | "globby": "^11.0.1", 255 | "is-glob": "^4.0.1", 256 | "lodash": "^4.17.15", 257 | "semver": "^7.3.2", 258 | "tsutils": "^3.17.1" 259 | }, 260 | "dependencies": { 261 | "debug": { 262 | "version": "4.3.1", 263 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 264 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 265 | "dev": true, 266 | "requires": { 267 | "ms": "2.1.2" 268 | } 269 | }, 270 | "lru-cache": { 271 | "version": "6.0.0", 272 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 273 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 274 | "dev": true, 275 | "requires": { 276 | "yallist": "^4.0.0" 277 | } 278 | }, 279 | "ms": { 280 | "version": "2.1.2", 281 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 282 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 283 | "dev": true 284 | }, 285 | "semver": { 286 | "version": "7.3.4", 287 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", 288 | "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", 289 | "dev": true, 290 | "requires": { 291 | "lru-cache": "^6.0.0" 292 | } 293 | }, 294 | "yallist": { 295 | "version": "4.0.0", 296 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 297 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 298 | "dev": true 299 | } 300 | } 301 | }, 302 | "@typescript-eslint/visitor-keys": { 303 | "version": "4.9.1", 304 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.9.1.tgz", 305 | "integrity": "sha512-9gspzc6UqLQHd7lXQS7oWs+hrYggspv/rk6zzEMhCbYwPE/sF7oxo7GAjkS35Tdlt7wguIG+ViWCPtVZHz/ybQ==", 306 | "dev": true, 307 | "requires": { 308 | "@typescript-eslint/types": "4.9.1", 309 | "eslint-visitor-keys": "^2.0.0" 310 | } 311 | }, 312 | "acorn": { 313 | "version": "7.4.1", 314 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", 315 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", 316 | "dev": true 317 | }, 318 | "acorn-jsx": { 319 | "version": "5.3.1", 320 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", 321 | "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", 322 | "dev": true 323 | }, 324 | "ajv": { 325 | "version": "6.12.6", 326 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 327 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 328 | "dev": true, 329 | "requires": { 330 | "fast-deep-equal": "^3.1.1", 331 | "fast-json-stable-stringify": "^2.0.0", 332 | "json-schema-traverse": "^0.4.1", 333 | "uri-js": "^4.2.2" 334 | } 335 | }, 336 | "ansi-colors": { 337 | "version": "4.1.1", 338 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 339 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 340 | "dev": true 341 | }, 342 | "ansi-regex": { 343 | "version": "5.0.1", 344 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 345 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 346 | "dev": true 347 | }, 348 | "ansi-styles": { 349 | "version": "3.2.1", 350 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 351 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 352 | "dev": true, 353 | "requires": { 354 | "color-convert": "^1.9.0" 355 | } 356 | }, 357 | "anymatch": { 358 | "version": "3.1.3", 359 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 360 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 361 | "dev": true, 362 | "requires": { 363 | "normalize-path": "^3.0.0", 364 | "picomatch": "^2.0.4" 365 | } 366 | }, 367 | "argparse": { 368 | "version": "1.0.10", 369 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 370 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 371 | "dev": true, 372 | "requires": { 373 | "sprintf-js": "~1.0.2" 374 | } 375 | }, 376 | "array-includes": { 377 | "version": "3.1.2", 378 | "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.2.tgz", 379 | "integrity": "sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw==", 380 | "dev": true, 381 | "requires": { 382 | "call-bind": "^1.0.0", 383 | "define-properties": "^1.1.3", 384 | "es-abstract": "^1.18.0-next.1", 385 | "get-intrinsic": "^1.0.1", 386 | "is-string": "^1.0.5" 387 | } 388 | }, 389 | "array-union": { 390 | "version": "2.1.0", 391 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 392 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 393 | "dev": true 394 | }, 395 | "array.prototype.flat": { 396 | "version": "1.2.4", 397 | "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", 398 | "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", 399 | "dev": true, 400 | "requires": { 401 | "call-bind": "^1.0.0", 402 | "define-properties": "^1.1.3", 403 | "es-abstract": "^1.18.0-next.1" 404 | } 405 | }, 406 | "arrify": { 407 | "version": "1.0.1", 408 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 409 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 410 | "dev": true 411 | }, 412 | "assertion-error": { 413 | "version": "1.1.0", 414 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 415 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 416 | "dev": true 417 | }, 418 | "astral-regex": { 419 | "version": "1.0.0", 420 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", 421 | "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", 422 | "dev": true 423 | }, 424 | "balanced-match": { 425 | "version": "1.0.0", 426 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 427 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 428 | "dev": true 429 | }, 430 | "binary-extensions": { 431 | "version": "2.3.0", 432 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 433 | "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 434 | "dev": true 435 | }, 436 | "brace-expansion": { 437 | "version": "1.1.11", 438 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 439 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 440 | "dev": true, 441 | "requires": { 442 | "balanced-match": "^1.0.0", 443 | "concat-map": "0.0.1" 444 | } 445 | }, 446 | "braces": { 447 | "version": "3.0.3", 448 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 449 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 450 | "dev": true, 451 | "requires": { 452 | "fill-range": "^7.1.1" 453 | } 454 | }, 455 | "browser-stdout": { 456 | "version": "1.3.1", 457 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 458 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 459 | "dev": true 460 | }, 461 | "buffer-from": { 462 | "version": "1.1.1", 463 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 464 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 465 | "dev": true 466 | }, 467 | "call-bind": { 468 | "version": "1.0.0", 469 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", 470 | "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", 471 | "dev": true, 472 | "requires": { 473 | "function-bind": "^1.1.1", 474 | "get-intrinsic": "^1.0.0" 475 | } 476 | }, 477 | "caller-callsite": { 478 | "version": "2.0.0", 479 | "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", 480 | "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", 481 | "dev": true, 482 | "requires": { 483 | "callsites": "^2.0.0" 484 | }, 485 | "dependencies": { 486 | "callsites": { 487 | "version": "2.0.0", 488 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", 489 | "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", 490 | "dev": true 491 | } 492 | } 493 | }, 494 | "caller-path": { 495 | "version": "2.0.0", 496 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", 497 | "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", 498 | "dev": true, 499 | "requires": { 500 | "caller-callsite": "^2.0.0" 501 | } 502 | }, 503 | "callsites": { 504 | "version": "3.1.0", 505 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 506 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 507 | "dev": true 508 | }, 509 | "chai": { 510 | "version": "4.2.0", 511 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", 512 | "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", 513 | "dev": true, 514 | "requires": { 515 | "assertion-error": "^1.1.0", 516 | "check-error": "^1.0.2", 517 | "deep-eql": "^3.0.1", 518 | "get-func-name": "^2.0.0", 519 | "pathval": "^1.1.0", 520 | "type-detect": "^4.0.5" 521 | } 522 | }, 523 | "chalk": { 524 | "version": "2.4.1", 525 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", 526 | "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", 527 | "dev": true, 528 | "requires": { 529 | "ansi-styles": "^3.2.1", 530 | "escape-string-regexp": "^1.0.5", 531 | "supports-color": "^5.3.0" 532 | } 533 | }, 534 | "check-error": { 535 | "version": "1.0.2", 536 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 537 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 538 | "dev": true 539 | }, 540 | "chokidar": { 541 | "version": "3.6.0", 542 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 543 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 544 | "dev": true, 545 | "requires": { 546 | "anymatch": "~3.1.2", 547 | "braces": "~3.0.2", 548 | "fsevents": "~2.3.2", 549 | "glob-parent": "~5.1.2", 550 | "is-binary-path": "~2.1.0", 551 | "is-glob": "~4.0.1", 552 | "normalize-path": "~3.0.0", 553 | "readdirp": "~3.6.0" 554 | } 555 | }, 556 | "cliui": { 557 | "version": "7.0.4", 558 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 559 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 560 | "dev": true, 561 | "requires": { 562 | "string-width": "^4.2.0", 563 | "strip-ansi": "^6.0.0", 564 | "wrap-ansi": "^7.0.0" 565 | }, 566 | "dependencies": { 567 | "emoji-regex": { 568 | "version": "8.0.0", 569 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 570 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 571 | "dev": true 572 | }, 573 | "is-fullwidth-code-point": { 574 | "version": "3.0.0", 575 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 576 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 577 | "dev": true 578 | }, 579 | "string-width": { 580 | "version": "4.2.3", 581 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 582 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 583 | "dev": true, 584 | "requires": { 585 | "emoji-regex": "^8.0.0", 586 | "is-fullwidth-code-point": "^3.0.0", 587 | "strip-ansi": "^6.0.1" 588 | } 589 | }, 590 | "strip-ansi": { 591 | "version": "6.0.1", 592 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 593 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 594 | "dev": true, 595 | "requires": { 596 | "ansi-regex": "^5.0.1" 597 | } 598 | } 599 | } 600 | }, 601 | "color-convert": { 602 | "version": "1.9.2", 603 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", 604 | "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", 605 | "dev": true, 606 | "requires": { 607 | "color-name": "1.1.1" 608 | } 609 | }, 610 | "color-name": { 611 | "version": "1.1.1", 612 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", 613 | "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=", 614 | "dev": true 615 | }, 616 | "concat-map": { 617 | "version": "0.0.1", 618 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 619 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 620 | "dev": true 621 | }, 622 | "confusing-browser-globals": { 623 | "version": "1.0.10", 624 | "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz", 625 | "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", 626 | "dev": true 627 | }, 628 | "contains-path": { 629 | "version": "0.1.0", 630 | "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", 631 | "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", 632 | "dev": true 633 | }, 634 | "cosmiconfig": { 635 | "version": "5.2.1", 636 | "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", 637 | "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", 638 | "dev": true, 639 | "requires": { 640 | "import-fresh": "^2.0.0", 641 | "is-directory": "^0.3.1", 642 | "js-yaml": "^3.13.1", 643 | "parse-json": "^4.0.0" 644 | }, 645 | "dependencies": { 646 | "import-fresh": { 647 | "version": "2.0.0", 648 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", 649 | "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", 650 | "dev": true, 651 | "requires": { 652 | "caller-path": "^2.0.0", 653 | "resolve-from": "^3.0.0" 654 | } 655 | }, 656 | "resolve-from": { 657 | "version": "3.0.0", 658 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", 659 | "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", 660 | "dev": true 661 | } 662 | } 663 | }, 664 | "debug": { 665 | "version": "4.3.4", 666 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 667 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 668 | "dev": true, 669 | "requires": { 670 | "ms": "2.1.2" 671 | }, 672 | "dependencies": { 673 | "ms": { 674 | "version": "2.1.2", 675 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 676 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 677 | "dev": true 678 | } 679 | } 680 | }, 681 | "decamelize": { 682 | "version": "4.0.0", 683 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 684 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 685 | "dev": true 686 | }, 687 | "deep-eql": { 688 | "version": "3.0.1", 689 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 690 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 691 | "dev": true, 692 | "requires": { 693 | "type-detect": "^4.0.0" 694 | } 695 | }, 696 | "deep-is": { 697 | "version": "0.1.3", 698 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 699 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 700 | "dev": true 701 | }, 702 | "define-properties": { 703 | "version": "1.1.3", 704 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 705 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 706 | "dev": true, 707 | "requires": { 708 | "object-keys": "^1.0.12" 709 | } 710 | }, 711 | "diff": { 712 | "version": "3.5.0", 713 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 714 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 715 | "dev": true 716 | }, 717 | "dir-glob": { 718 | "version": "3.0.1", 719 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 720 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 721 | "dev": true, 722 | "requires": { 723 | "path-type": "^4.0.0" 724 | } 725 | }, 726 | "doctrine": { 727 | "version": "3.0.0", 728 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 729 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 730 | "dev": true, 731 | "requires": { 732 | "esutils": "^2.0.2" 733 | } 734 | }, 735 | "emoji-regex": { 736 | "version": "7.0.3", 737 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 738 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 739 | "dev": true 740 | }, 741 | "end-of-stream": { 742 | "version": "1.4.4", 743 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 744 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 745 | "dev": true, 746 | "requires": { 747 | "once": "^1.4.0" 748 | } 749 | }, 750 | "enquirer": { 751 | "version": "2.3.6", 752 | "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", 753 | "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", 754 | "dev": true, 755 | "requires": { 756 | "ansi-colors": "^4.1.1" 757 | } 758 | }, 759 | "error-ex": { 760 | "version": "1.3.2", 761 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 762 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 763 | "dev": true, 764 | "requires": { 765 | "is-arrayish": "^0.2.1" 766 | } 767 | }, 768 | "es-abstract": { 769 | "version": "1.18.0-next.1", 770 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", 771 | "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", 772 | "dev": true, 773 | "requires": { 774 | "es-to-primitive": "^1.2.1", 775 | "function-bind": "^1.1.1", 776 | "has": "^1.0.3", 777 | "has-symbols": "^1.0.1", 778 | "is-callable": "^1.2.2", 779 | "is-negative-zero": "^2.0.0", 780 | "is-regex": "^1.1.1", 781 | "object-inspect": "^1.8.0", 782 | "object-keys": "^1.1.1", 783 | "object.assign": "^4.1.1", 784 | "string.prototype.trimend": "^1.0.1", 785 | "string.prototype.trimstart": "^1.0.1" 786 | } 787 | }, 788 | "es-to-primitive": { 789 | "version": "1.2.1", 790 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 791 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 792 | "dev": true, 793 | "requires": { 794 | "is-callable": "^1.1.4", 795 | "is-date-object": "^1.0.1", 796 | "is-symbol": "^1.0.2" 797 | } 798 | }, 799 | "escalade": { 800 | "version": "3.1.1", 801 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 802 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 803 | "dev": true 804 | }, 805 | "escape-string-regexp": { 806 | "version": "1.0.5", 807 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 808 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 809 | "dev": true 810 | }, 811 | "eslint": { 812 | "version": "7.15.0", 813 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.15.0.tgz", 814 | "integrity": "sha512-Vr64xFDT8w30wFll643e7cGrIkPEU50yIiI36OdSIDoSGguIeaLzBo0vpGvzo9RECUqq7htURfwEtKqwytkqzA==", 815 | "dev": true, 816 | "requires": { 817 | "@babel/code-frame": "^7.0.0", 818 | "@eslint/eslintrc": "^0.2.2", 819 | "ajv": "^6.10.0", 820 | "chalk": "^4.0.0", 821 | "cross-spawn": "^7.0.2", 822 | "debug": "^4.0.1", 823 | "doctrine": "^3.0.0", 824 | "enquirer": "^2.3.5", 825 | "eslint-scope": "^5.1.1", 826 | "eslint-utils": "^2.1.0", 827 | "eslint-visitor-keys": "^2.0.0", 828 | "espree": "^7.3.1", 829 | "esquery": "^1.2.0", 830 | "esutils": "^2.0.2", 831 | "file-entry-cache": "^6.0.0", 832 | "functional-red-black-tree": "^1.0.1", 833 | "glob-parent": "^5.0.0", 834 | "globals": "^12.1.0", 835 | "ignore": "^4.0.6", 836 | "import-fresh": "^3.0.0", 837 | "imurmurhash": "^0.1.4", 838 | "is-glob": "^4.0.0", 839 | "js-yaml": "^3.13.1", 840 | "json-stable-stringify-without-jsonify": "^1.0.1", 841 | "levn": "^0.4.1", 842 | "lodash": "^4.17.19", 843 | "minimatch": "^3.0.4", 844 | "natural-compare": "^1.4.0", 845 | "optionator": "^0.9.1", 846 | "progress": "^2.0.0", 847 | "regexpp": "^3.1.0", 848 | "semver": "^7.2.1", 849 | "strip-ansi": "^6.0.0", 850 | "strip-json-comments": "^3.1.0", 851 | "table": "^5.2.3", 852 | "text-table": "^0.2.0", 853 | "v8-compile-cache": "^2.0.3" 854 | }, 855 | "dependencies": { 856 | "ansi-styles": { 857 | "version": "4.3.0", 858 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 859 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 860 | "dev": true, 861 | "requires": { 862 | "color-convert": "^2.0.1" 863 | } 864 | }, 865 | "chalk": { 866 | "version": "4.1.0", 867 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", 868 | "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", 869 | "dev": true, 870 | "requires": { 871 | "ansi-styles": "^4.1.0", 872 | "supports-color": "^7.1.0" 873 | } 874 | }, 875 | "color-convert": { 876 | "version": "2.0.1", 877 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 878 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 879 | "dev": true, 880 | "requires": { 881 | "color-name": "~1.1.4" 882 | } 883 | }, 884 | "color-name": { 885 | "version": "1.1.4", 886 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 887 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 888 | "dev": true 889 | }, 890 | "cross-spawn": { 891 | "version": "7.0.3", 892 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 893 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 894 | "dev": true, 895 | "requires": { 896 | "path-key": "^3.1.0", 897 | "shebang-command": "^2.0.0", 898 | "which": "^2.0.1" 899 | } 900 | }, 901 | "debug": { 902 | "version": "4.3.1", 903 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", 904 | "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", 905 | "dev": true, 906 | "requires": { 907 | "ms": "2.1.2" 908 | } 909 | }, 910 | "glob-parent": { 911 | "version": "5.1.1", 912 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 913 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 914 | "dev": true, 915 | "requires": { 916 | "is-glob": "^4.0.1" 917 | } 918 | }, 919 | "has-flag": { 920 | "version": "4.0.0", 921 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 922 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 923 | "dev": true 924 | }, 925 | "ignore": { 926 | "version": "4.0.6", 927 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 928 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 929 | "dev": true 930 | }, 931 | "lru-cache": { 932 | "version": "6.0.0", 933 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 934 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 935 | "dev": true, 936 | "requires": { 937 | "yallist": "^4.0.0" 938 | } 939 | }, 940 | "ms": { 941 | "version": "2.1.2", 942 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 943 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 944 | "dev": true 945 | }, 946 | "path-key": { 947 | "version": "3.1.1", 948 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 949 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 950 | "dev": true 951 | }, 952 | "semver": { 953 | "version": "7.3.4", 954 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", 955 | "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", 956 | "dev": true, 957 | "requires": { 958 | "lru-cache": "^6.0.0" 959 | } 960 | }, 961 | "shebang-command": { 962 | "version": "2.0.0", 963 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 964 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 965 | "dev": true, 966 | "requires": { 967 | "shebang-regex": "^3.0.0" 968 | } 969 | }, 970 | "shebang-regex": { 971 | "version": "3.0.0", 972 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 973 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 974 | "dev": true 975 | }, 976 | "strip-ansi": { 977 | "version": "6.0.0", 978 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 979 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 980 | "dev": true, 981 | "requires": { 982 | "ansi-regex": "^5.0.0" 983 | } 984 | }, 985 | "strip-json-comments": { 986 | "version": "3.1.1", 987 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 988 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 989 | "dev": true 990 | }, 991 | "supports-color": { 992 | "version": "7.2.0", 993 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 994 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 995 | "dev": true, 996 | "requires": { 997 | "has-flag": "^4.0.0" 998 | } 999 | }, 1000 | "which": { 1001 | "version": "2.0.2", 1002 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1003 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1004 | "dev": true, 1005 | "requires": { 1006 | "isexe": "^2.0.0" 1007 | } 1008 | }, 1009 | "yallist": { 1010 | "version": "4.0.0", 1011 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1012 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 1013 | "dev": true 1014 | } 1015 | } 1016 | }, 1017 | "eslint-config-airbnb-base": { 1018 | "version": "14.2.1", 1019 | "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz", 1020 | "integrity": "sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==", 1021 | "dev": true, 1022 | "requires": { 1023 | "confusing-browser-globals": "^1.0.10", 1024 | "object.assign": "^4.1.2", 1025 | "object.entries": "^1.1.2" 1026 | } 1027 | }, 1028 | "eslint-config-google": { 1029 | "version": "0.14.0", 1030 | "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", 1031 | "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", 1032 | "dev": true 1033 | }, 1034 | "eslint-config-standard": { 1035 | "version": "16.0.2", 1036 | "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.2.tgz", 1037 | "integrity": "sha512-fx3f1rJDsl9bY7qzyX8SAtP8GBSk6MfXFaTfaGgk12aAYW4gJSyRm7dM790L6cbXv63fvjY4XeSzXnb4WM+SKw==", 1038 | "dev": true 1039 | }, 1040 | "eslint-import-resolver-node": { 1041 | "version": "0.3.4", 1042 | "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", 1043 | "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", 1044 | "dev": true, 1045 | "requires": { 1046 | "debug": "^2.6.9", 1047 | "resolve": "^1.13.1" 1048 | }, 1049 | "dependencies": { 1050 | "debug": { 1051 | "version": "2.6.9", 1052 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1053 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1054 | "dev": true, 1055 | "requires": { 1056 | "ms": "2.0.0" 1057 | } 1058 | } 1059 | } 1060 | }, 1061 | "eslint-module-utils": { 1062 | "version": "2.6.0", 1063 | "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", 1064 | "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", 1065 | "dev": true, 1066 | "requires": { 1067 | "debug": "^2.6.9", 1068 | "pkg-dir": "^2.0.0" 1069 | }, 1070 | "dependencies": { 1071 | "debug": { 1072 | "version": "2.6.9", 1073 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1074 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1075 | "dev": true, 1076 | "requires": { 1077 | "ms": "2.0.0" 1078 | } 1079 | }, 1080 | "find-up": { 1081 | "version": "2.1.0", 1082 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", 1083 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", 1084 | "dev": true, 1085 | "requires": { 1086 | "locate-path": "^2.0.0" 1087 | } 1088 | }, 1089 | "locate-path": { 1090 | "version": "2.0.0", 1091 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", 1092 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", 1093 | "dev": true, 1094 | "requires": { 1095 | "p-locate": "^2.0.0", 1096 | "path-exists": "^3.0.0" 1097 | } 1098 | }, 1099 | "p-limit": { 1100 | "version": "1.3.0", 1101 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", 1102 | "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", 1103 | "dev": true, 1104 | "requires": { 1105 | "p-try": "^1.0.0" 1106 | } 1107 | }, 1108 | "p-locate": { 1109 | "version": "2.0.0", 1110 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", 1111 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", 1112 | "dev": true, 1113 | "requires": { 1114 | "p-limit": "^1.1.0" 1115 | } 1116 | }, 1117 | "p-try": { 1118 | "version": "1.0.0", 1119 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", 1120 | "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", 1121 | "dev": true 1122 | }, 1123 | "pkg-dir": { 1124 | "version": "2.0.0", 1125 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", 1126 | "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", 1127 | "dev": true, 1128 | "requires": { 1129 | "find-up": "^2.1.0" 1130 | } 1131 | } 1132 | } 1133 | }, 1134 | "eslint-plugin-es": { 1135 | "version": "3.0.1", 1136 | "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", 1137 | "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", 1138 | "dev": true, 1139 | "requires": { 1140 | "eslint-utils": "^2.0.0", 1141 | "regexpp": "^3.0.0" 1142 | } 1143 | }, 1144 | "eslint-plugin-import": { 1145 | "version": "2.22.1", 1146 | "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz", 1147 | "integrity": "sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==", 1148 | "dev": true, 1149 | "requires": { 1150 | "array-includes": "^3.1.1", 1151 | "array.prototype.flat": "^1.2.3", 1152 | "contains-path": "^0.1.0", 1153 | "debug": "^2.6.9", 1154 | "doctrine": "1.5.0", 1155 | "eslint-import-resolver-node": "^0.3.4", 1156 | "eslint-module-utils": "^2.6.0", 1157 | "has": "^1.0.3", 1158 | "minimatch": "^3.0.4", 1159 | "object.values": "^1.1.1", 1160 | "read-pkg-up": "^2.0.0", 1161 | "resolve": "^1.17.0", 1162 | "tsconfig-paths": "^3.9.0" 1163 | }, 1164 | "dependencies": { 1165 | "debug": { 1166 | "version": "2.6.9", 1167 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 1168 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 1169 | "dev": true, 1170 | "requires": { 1171 | "ms": "2.0.0" 1172 | } 1173 | }, 1174 | "doctrine": { 1175 | "version": "1.5.0", 1176 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", 1177 | "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", 1178 | "dev": true, 1179 | "requires": { 1180 | "esutils": "^2.0.2", 1181 | "isarray": "^1.0.0" 1182 | } 1183 | } 1184 | } 1185 | }, 1186 | "eslint-plugin-node": { 1187 | "version": "11.1.0", 1188 | "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", 1189 | "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", 1190 | "dev": true, 1191 | "requires": { 1192 | "eslint-plugin-es": "^3.0.0", 1193 | "eslint-utils": "^2.0.0", 1194 | "ignore": "^5.1.1", 1195 | "minimatch": "^3.0.4", 1196 | "resolve": "^1.10.1", 1197 | "semver": "^6.1.0" 1198 | }, 1199 | "dependencies": { 1200 | "semver": { 1201 | "version": "6.3.0", 1202 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1203 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1204 | "dev": true 1205 | } 1206 | } 1207 | }, 1208 | "eslint-plugin-promise": { 1209 | "version": "4.2.1", 1210 | "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz", 1211 | "integrity": "sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==", 1212 | "dev": true 1213 | }, 1214 | "eslint-scope": { 1215 | "version": "5.1.1", 1216 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 1217 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 1218 | "dev": true, 1219 | "requires": { 1220 | "esrecurse": "^4.3.0", 1221 | "estraverse": "^4.1.1" 1222 | } 1223 | }, 1224 | "eslint-utils": { 1225 | "version": "2.1.0", 1226 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", 1227 | "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", 1228 | "dev": true, 1229 | "requires": { 1230 | "eslint-visitor-keys": "^1.1.0" 1231 | }, 1232 | "dependencies": { 1233 | "eslint-visitor-keys": { 1234 | "version": "1.3.0", 1235 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 1236 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 1237 | "dev": true 1238 | } 1239 | } 1240 | }, 1241 | "eslint-visitor-keys": { 1242 | "version": "2.0.0", 1243 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", 1244 | "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", 1245 | "dev": true 1246 | }, 1247 | "espree": { 1248 | "version": "7.3.1", 1249 | "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", 1250 | "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", 1251 | "dev": true, 1252 | "requires": { 1253 | "acorn": "^7.4.0", 1254 | "acorn-jsx": "^5.3.1", 1255 | "eslint-visitor-keys": "^1.3.0" 1256 | }, 1257 | "dependencies": { 1258 | "eslint-visitor-keys": { 1259 | "version": "1.3.0", 1260 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 1261 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 1262 | "dev": true 1263 | } 1264 | } 1265 | }, 1266 | "esprima": { 1267 | "version": "4.0.1", 1268 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 1269 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 1270 | "dev": true 1271 | }, 1272 | "esquery": { 1273 | "version": "1.3.1", 1274 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", 1275 | "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", 1276 | "dev": true, 1277 | "requires": { 1278 | "estraverse": "^5.1.0" 1279 | }, 1280 | "dependencies": { 1281 | "estraverse": { 1282 | "version": "5.2.0", 1283 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", 1284 | "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", 1285 | "dev": true 1286 | } 1287 | } 1288 | }, 1289 | "esrecurse": { 1290 | "version": "4.3.0", 1291 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 1292 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 1293 | "dev": true, 1294 | "requires": { 1295 | "estraverse": "^5.2.0" 1296 | }, 1297 | "dependencies": { 1298 | "estraverse": { 1299 | "version": "5.2.0", 1300 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", 1301 | "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", 1302 | "dev": true 1303 | } 1304 | } 1305 | }, 1306 | "estraverse": { 1307 | "version": "4.3.0", 1308 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 1309 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 1310 | "dev": true 1311 | }, 1312 | "esutils": { 1313 | "version": "2.0.2", 1314 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 1315 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 1316 | "dev": true 1317 | }, 1318 | "fast-deep-equal": { 1319 | "version": "3.1.3", 1320 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1321 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1322 | "dev": true 1323 | }, 1324 | "fast-glob": { 1325 | "version": "3.2.4", 1326 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", 1327 | "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", 1328 | "dev": true, 1329 | "requires": { 1330 | "@nodelib/fs.stat": "^2.0.2", 1331 | "@nodelib/fs.walk": "^1.2.3", 1332 | "glob-parent": "^5.1.0", 1333 | "merge2": "^1.3.0", 1334 | "micromatch": "^4.0.2", 1335 | "picomatch": "^2.2.1" 1336 | }, 1337 | "dependencies": { 1338 | "fill-range": { 1339 | "version": "7.0.1", 1340 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 1341 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 1342 | "requires": { 1343 | "to-regex-range": "^5.0.1" 1344 | } 1345 | }, 1346 | "glob-parent": { 1347 | "version": "5.1.1", 1348 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 1349 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 1350 | "dev": true, 1351 | "requires": { 1352 | "is-glob": "^4.0.1" 1353 | } 1354 | }, 1355 | "is-number": { 1356 | "version": "7.0.0", 1357 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1358 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" 1359 | }, 1360 | "micromatch": { 1361 | "version": "4.0.2", 1362 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", 1363 | "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", 1364 | "dev": true, 1365 | "requires": { 1366 | "braces": "^3.0.1", 1367 | "picomatch": "^2.0.5" 1368 | } 1369 | }, 1370 | "to-regex-range": { 1371 | "version": "5.0.1", 1372 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 1373 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 1374 | "requires": { 1375 | "is-number": "^7.0.0" 1376 | } 1377 | } 1378 | } 1379 | }, 1380 | "fast-json-stable-stringify": { 1381 | "version": "2.1.0", 1382 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1383 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1384 | "dev": true 1385 | }, 1386 | "fast-levenshtein": { 1387 | "version": "2.0.6", 1388 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1389 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 1390 | "dev": true 1391 | }, 1392 | "fastq": { 1393 | "version": "1.9.0", 1394 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", 1395 | "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==", 1396 | "dev": true, 1397 | "requires": { 1398 | "reusify": "^1.0.4" 1399 | } 1400 | }, 1401 | "file-entry-cache": { 1402 | "version": "6.0.0", 1403 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", 1404 | "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", 1405 | "dev": true, 1406 | "requires": { 1407 | "flat-cache": "^3.0.4" 1408 | } 1409 | }, 1410 | "fill-range": { 1411 | "version": "7.1.1", 1412 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 1413 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1414 | "dev": true, 1415 | "requires": { 1416 | "to-regex-range": "^5.0.1" 1417 | } 1418 | }, 1419 | "find-up": { 1420 | "version": "3.0.0", 1421 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 1422 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 1423 | "dev": true, 1424 | "requires": { 1425 | "locate-path": "^3.0.0" 1426 | } 1427 | }, 1428 | "flat": { 1429 | "version": "5.0.2", 1430 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 1431 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 1432 | "dev": true 1433 | }, 1434 | "flat-cache": { 1435 | "version": "3.0.4", 1436 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 1437 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 1438 | "dev": true, 1439 | "requires": { 1440 | "flatted": "^3.1.0", 1441 | "rimraf": "^3.0.2" 1442 | } 1443 | }, 1444 | "flatted": { 1445 | "version": "3.1.0", 1446 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz", 1447 | "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==", 1448 | "dev": true 1449 | }, 1450 | "fs.realpath": { 1451 | "version": "1.0.0", 1452 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1453 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 1454 | "dev": true 1455 | }, 1456 | "fsevents": { 1457 | "version": "2.3.3", 1458 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1459 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1460 | "dev": true, 1461 | "optional": true 1462 | }, 1463 | "function-bind": { 1464 | "version": "1.1.1", 1465 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 1466 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 1467 | "dev": true 1468 | }, 1469 | "functional-red-black-tree": { 1470 | "version": "1.0.1", 1471 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 1472 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 1473 | "dev": true 1474 | }, 1475 | "get-caller-file": { 1476 | "version": "2.0.5", 1477 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1478 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 1479 | "dev": true 1480 | }, 1481 | "get-func-name": { 1482 | "version": "2.0.0", 1483 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 1484 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 1485 | "dev": true 1486 | }, 1487 | "get-intrinsic": { 1488 | "version": "1.0.1", 1489 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.1.tgz", 1490 | "integrity": "sha512-ZnWP+AmS1VUaLgTRy47+zKtjTxz+0xMpx3I52i+aalBK1QP19ggLF3Db89KJX7kjfOfP2eoa01qc++GwPgufPg==", 1491 | "dev": true, 1492 | "requires": { 1493 | "function-bind": "^1.1.1", 1494 | "has": "^1.0.3", 1495 | "has-symbols": "^1.0.1" 1496 | } 1497 | }, 1498 | "get-stdin": { 1499 | "version": "7.0.0", 1500 | "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", 1501 | "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", 1502 | "dev": true 1503 | }, 1504 | "glob": { 1505 | "version": "7.2.0", 1506 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 1507 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 1508 | "dev": true, 1509 | "requires": { 1510 | "fs.realpath": "^1.0.0", 1511 | "inflight": "^1.0.4", 1512 | "inherits": "2", 1513 | "minimatch": "^3.0.4", 1514 | "once": "^1.3.0", 1515 | "path-is-absolute": "^1.0.0" 1516 | } 1517 | }, 1518 | "glob-parent": { 1519 | "version": "5.1.2", 1520 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1521 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1522 | "dev": true, 1523 | "requires": { 1524 | "is-glob": "^4.0.1" 1525 | } 1526 | }, 1527 | "globals": { 1528 | "version": "12.4.0", 1529 | "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", 1530 | "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", 1531 | "dev": true, 1532 | "requires": { 1533 | "type-fest": "^0.8.1" 1534 | }, 1535 | "dependencies": { 1536 | "type-fest": { 1537 | "version": "0.8.1", 1538 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", 1539 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", 1540 | "dev": true 1541 | } 1542 | } 1543 | }, 1544 | "globby": { 1545 | "version": "11.0.1", 1546 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", 1547 | "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", 1548 | "dev": true, 1549 | "requires": { 1550 | "array-union": "^2.1.0", 1551 | "dir-glob": "^3.0.1", 1552 | "fast-glob": "^3.1.1", 1553 | "ignore": "^5.1.4", 1554 | "merge2": "^1.3.0", 1555 | "slash": "^3.0.0" 1556 | } 1557 | }, 1558 | "graceful-fs": { 1559 | "version": "4.2.4", 1560 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 1561 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", 1562 | "dev": true 1563 | }, 1564 | "has": { 1565 | "version": "1.0.3", 1566 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1567 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1568 | "dev": true, 1569 | "requires": { 1570 | "function-bind": "^1.1.1" 1571 | } 1572 | }, 1573 | "has-flag": { 1574 | "version": "3.0.0", 1575 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 1576 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 1577 | "dev": true 1578 | }, 1579 | "has-symbols": { 1580 | "version": "1.0.1", 1581 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", 1582 | "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", 1583 | "dev": true 1584 | }, 1585 | "he": { 1586 | "version": "1.2.0", 1587 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 1588 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 1589 | "dev": true 1590 | }, 1591 | "hosted-git-info": { 1592 | "version": "2.8.9", 1593 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", 1594 | "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", 1595 | "dev": true 1596 | }, 1597 | "husky": { 1598 | "version": "2.7.0", 1599 | "resolved": "https://registry.npmjs.org/husky/-/husky-2.7.0.tgz", 1600 | "integrity": "sha512-LIi8zzT6PyFpcYKdvWRCn/8X+6SuG2TgYYMrM6ckEYhlp44UcEduVymZGIZNLiwOUjrEud+78w/AsAiqJA/kRg==", 1601 | "dev": true, 1602 | "requires": { 1603 | "cosmiconfig": "^5.2.0", 1604 | "execa": "^1.0.0", 1605 | "find-up": "^3.0.0", 1606 | "get-stdin": "^7.0.0", 1607 | "is-ci": "^2.0.0", 1608 | "pkg-dir": "^4.1.0", 1609 | "please-upgrade-node": "^3.1.1", 1610 | "read-pkg": "^5.1.1", 1611 | "run-node": "^1.0.0", 1612 | "slash": "^3.0.0" 1613 | }, 1614 | "dependencies": { 1615 | "ci-info": { 1616 | "version": "2.0.0", 1617 | "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", 1618 | "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", 1619 | "dev": true 1620 | }, 1621 | "cross-spawn": { 1622 | "version": "6.0.5", 1623 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", 1624 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", 1625 | "dev": true, 1626 | "requires": { 1627 | "nice-try": "^1.0.4", 1628 | "path-key": "^2.0.1", 1629 | "semver": "^5.5.0", 1630 | "shebang-command": "^1.2.0", 1631 | "which": "^1.2.9" 1632 | } 1633 | }, 1634 | "execa": { 1635 | "version": "1.0.0", 1636 | "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", 1637 | "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", 1638 | "dev": true, 1639 | "requires": { 1640 | "cross-spawn": "^6.0.0", 1641 | "get-stream": "^4.0.0", 1642 | "is-stream": "^1.1.0", 1643 | "npm-run-path": "^2.0.0", 1644 | "p-finally": "^1.0.0", 1645 | "signal-exit": "^3.0.0", 1646 | "strip-eof": "^1.0.0" 1647 | } 1648 | }, 1649 | "get-stream": { 1650 | "version": "4.1.0", 1651 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 1652 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 1653 | "dev": true, 1654 | "requires": { 1655 | "pump": "^3.0.0" 1656 | } 1657 | }, 1658 | "is-ci": { 1659 | "version": "2.0.0", 1660 | "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", 1661 | "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", 1662 | "dev": true, 1663 | "requires": { 1664 | "ci-info": "^2.0.0" 1665 | } 1666 | } 1667 | } 1668 | }, 1669 | "ignore": { 1670 | "version": "5.1.8", 1671 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", 1672 | "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", 1673 | "dev": true 1674 | }, 1675 | "ignore-by-default": { 1676 | "version": "1.0.1", 1677 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 1678 | "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", 1679 | "dev": true 1680 | }, 1681 | "import-fresh": { 1682 | "version": "3.2.2", 1683 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", 1684 | "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", 1685 | "dev": true, 1686 | "requires": { 1687 | "parent-module": "^1.0.0", 1688 | "resolve-from": "^4.0.0" 1689 | } 1690 | }, 1691 | "imurmurhash": { 1692 | "version": "0.1.4", 1693 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1694 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1695 | "dev": true 1696 | }, 1697 | "inflight": { 1698 | "version": "1.0.6", 1699 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1700 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1701 | "dev": true, 1702 | "requires": { 1703 | "once": "^1.3.0", 1704 | "wrappy": "1" 1705 | } 1706 | }, 1707 | "inherits": { 1708 | "version": "2.0.3", 1709 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 1710 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 1711 | "dev": true 1712 | }, 1713 | "is-arrayish": { 1714 | "version": "0.2.1", 1715 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 1716 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", 1717 | "dev": true 1718 | }, 1719 | "is-binary-path": { 1720 | "version": "2.1.0", 1721 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1722 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1723 | "dev": true, 1724 | "requires": { 1725 | "binary-extensions": "^2.0.0" 1726 | } 1727 | }, 1728 | "is-callable": { 1729 | "version": "1.2.2", 1730 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", 1731 | "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", 1732 | "dev": true 1733 | }, 1734 | "is-date-object": { 1735 | "version": "1.0.2", 1736 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", 1737 | "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", 1738 | "dev": true 1739 | }, 1740 | "is-directory": { 1741 | "version": "0.3.1", 1742 | "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", 1743 | "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", 1744 | "dev": true 1745 | }, 1746 | "is-extglob": { 1747 | "version": "2.1.1", 1748 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1749 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1750 | "dev": true 1751 | }, 1752 | "is-fullwidth-code-point": { 1753 | "version": "2.0.0", 1754 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1755 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 1756 | "dev": true 1757 | }, 1758 | "is-glob": { 1759 | "version": "4.0.1", 1760 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 1761 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 1762 | "dev": true, 1763 | "requires": { 1764 | "is-extglob": "^2.1.1" 1765 | } 1766 | }, 1767 | "is-negative-zero": { 1768 | "version": "2.0.1", 1769 | "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", 1770 | "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", 1771 | "dev": true 1772 | }, 1773 | "is-number": { 1774 | "version": "7.0.0", 1775 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1776 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1777 | "dev": true 1778 | }, 1779 | "is-plain-obj": { 1780 | "version": "2.1.0", 1781 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 1782 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 1783 | "dev": true 1784 | }, 1785 | "is-regex": { 1786 | "version": "1.1.1", 1787 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", 1788 | "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", 1789 | "dev": true, 1790 | "requires": { 1791 | "has-symbols": "^1.0.1" 1792 | } 1793 | }, 1794 | "is-stream": { 1795 | "version": "1.1.0", 1796 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 1797 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", 1798 | "dev": true 1799 | }, 1800 | "is-string": { 1801 | "version": "1.0.5", 1802 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", 1803 | "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", 1804 | "dev": true 1805 | }, 1806 | "is-symbol": { 1807 | "version": "1.0.3", 1808 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", 1809 | "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", 1810 | "dev": true, 1811 | "requires": { 1812 | "has-symbols": "^1.0.1" 1813 | } 1814 | }, 1815 | "is-unicode-supported": { 1816 | "version": "0.1.0", 1817 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", 1818 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", 1819 | "dev": true 1820 | }, 1821 | "isarray": { 1822 | "version": "1.0.0", 1823 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1824 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 1825 | "dev": true 1826 | }, 1827 | "isexe": { 1828 | "version": "2.0.0", 1829 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1830 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1831 | "dev": true 1832 | }, 1833 | "js-tokens": { 1834 | "version": "4.0.0", 1835 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1836 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1837 | "dev": true 1838 | }, 1839 | "js-yaml": { 1840 | "version": "3.13.1", 1841 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 1842 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 1843 | "dev": true, 1844 | "requires": { 1845 | "argparse": "^1.0.7", 1846 | "esprima": "^4.0.0" 1847 | } 1848 | }, 1849 | "json-parse-better-errors": { 1850 | "version": "1.0.2", 1851 | "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", 1852 | "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", 1853 | "dev": true 1854 | }, 1855 | "json-schema-traverse": { 1856 | "version": "0.4.1", 1857 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1858 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1859 | "dev": true 1860 | }, 1861 | "json-stable-stringify-without-jsonify": { 1862 | "version": "1.0.1", 1863 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1864 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1865 | "dev": true 1866 | }, 1867 | "json5": { 1868 | "version": "1.0.2", 1869 | "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", 1870 | "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", 1871 | "dev": true, 1872 | "requires": { 1873 | "minimist": "^1.2.0" 1874 | } 1875 | }, 1876 | "levn": { 1877 | "version": "0.4.1", 1878 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1879 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1880 | "dev": true, 1881 | "requires": { 1882 | "prelude-ls": "^1.2.1", 1883 | "type-check": "~0.4.0" 1884 | } 1885 | }, 1886 | "lines-and-columns": { 1887 | "version": "1.1.6", 1888 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", 1889 | "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", 1890 | "dev": true 1891 | }, 1892 | "load-json-file": { 1893 | "version": "2.0.0", 1894 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", 1895 | "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", 1896 | "dev": true, 1897 | "requires": { 1898 | "graceful-fs": "^4.1.2", 1899 | "parse-json": "^2.2.0", 1900 | "pify": "^2.0.0", 1901 | "strip-bom": "^3.0.0" 1902 | }, 1903 | "dependencies": { 1904 | "parse-json": { 1905 | "version": "2.2.0", 1906 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", 1907 | "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", 1908 | "dev": true, 1909 | "requires": { 1910 | "error-ex": "^1.2.0" 1911 | } 1912 | }, 1913 | "pify": { 1914 | "version": "2.3.0", 1915 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 1916 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 1917 | "dev": true 1918 | } 1919 | } 1920 | }, 1921 | "locate-path": { 1922 | "version": "3.0.0", 1923 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 1924 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 1925 | "dev": true, 1926 | "requires": { 1927 | "p-locate": "^3.0.0", 1928 | "path-exists": "^3.0.0" 1929 | } 1930 | }, 1931 | "lodash": { 1932 | "version": "4.17.21", 1933 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 1934 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 1935 | "dev": true 1936 | }, 1937 | "log-symbols": { 1938 | "version": "4.1.0", 1939 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", 1940 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", 1941 | "dev": true, 1942 | "requires": { 1943 | "chalk": "^4.1.0", 1944 | "is-unicode-supported": "^0.1.0" 1945 | }, 1946 | "dependencies": { 1947 | "ansi-styles": { 1948 | "version": "4.3.0", 1949 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1950 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1951 | "dev": true, 1952 | "requires": { 1953 | "color-convert": "^2.0.1" 1954 | } 1955 | }, 1956 | "chalk": { 1957 | "version": "4.1.2", 1958 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1959 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1960 | "dev": true, 1961 | "requires": { 1962 | "ansi-styles": "^4.1.0", 1963 | "supports-color": "^7.1.0" 1964 | } 1965 | }, 1966 | "color-convert": { 1967 | "version": "2.0.1", 1968 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1969 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1970 | "dev": true, 1971 | "requires": { 1972 | "color-name": "~1.1.4" 1973 | } 1974 | }, 1975 | "color-name": { 1976 | "version": "1.1.4", 1977 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1978 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1979 | "dev": true 1980 | }, 1981 | "has-flag": { 1982 | "version": "4.0.0", 1983 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1984 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1985 | "dev": true 1986 | }, 1987 | "supports-color": { 1988 | "version": "7.2.0", 1989 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1990 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1991 | "dev": true, 1992 | "requires": { 1993 | "has-flag": "^4.0.0" 1994 | } 1995 | } 1996 | } 1997 | }, 1998 | "make-error": { 1999 | "version": "1.3.6", 2000 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 2001 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", 2002 | "dev": true 2003 | }, 2004 | "merge2": { 2005 | "version": "1.4.1", 2006 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 2007 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 2008 | "dev": true 2009 | }, 2010 | "minimatch": { 2011 | "version": "3.1.2", 2012 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 2013 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 2014 | "dev": true, 2015 | "requires": { 2016 | "brace-expansion": "^1.1.7" 2017 | } 2018 | }, 2019 | "minimist": { 2020 | "version": "1.2.8", 2021 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 2022 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 2023 | "dev": true 2024 | }, 2025 | "mkdirp": { 2026 | "version": "0.5.6", 2027 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 2028 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 2029 | "dev": true, 2030 | "requires": { 2031 | "minimist": "^1.2.6" 2032 | } 2033 | }, 2034 | "mocha": { 2035 | "version": "10.2.0", 2036 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", 2037 | "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", 2038 | "dev": true, 2039 | "requires": { 2040 | "ansi-colors": "4.1.1", 2041 | "browser-stdout": "1.3.1", 2042 | "chokidar": "3.5.3", 2043 | "debug": "4.3.4", 2044 | "diff": "5.0.0", 2045 | "escape-string-regexp": "4.0.0", 2046 | "find-up": "5.0.0", 2047 | "glob": "7.2.0", 2048 | "he": "1.2.0", 2049 | "js-yaml": "4.1.0", 2050 | "log-symbols": "4.1.0", 2051 | "minimatch": "5.0.1", 2052 | "ms": "2.1.3", 2053 | "nanoid": "3.3.3", 2054 | "serialize-javascript": "6.0.0", 2055 | "strip-json-comments": "3.1.1", 2056 | "supports-color": "8.1.1", 2057 | "workerpool": "6.2.1", 2058 | "yargs": "16.2.0", 2059 | "yargs-parser": "20.2.4", 2060 | "yargs-unparser": "2.0.0" 2061 | }, 2062 | "dependencies": { 2063 | "anymatch": { 2064 | "version": "3.1.3", 2065 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 2066 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 2067 | "dev": true, 2068 | "requires": { 2069 | "normalize-path": "^3.0.0", 2070 | "picomatch": "^2.0.4" 2071 | } 2072 | }, 2073 | "argparse": { 2074 | "version": "2.0.1", 2075 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 2076 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 2077 | "dev": true 2078 | }, 2079 | "binary-extensions": { 2080 | "version": "2.2.0", 2081 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", 2082 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", 2083 | "dev": true 2084 | }, 2085 | "brace-expansion": { 2086 | "version": "2.0.1", 2087 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 2088 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 2089 | "dev": true, 2090 | "requires": { 2091 | "balanced-match": "^1.0.0" 2092 | } 2093 | }, 2094 | "chokidar": { 2095 | "version": "3.5.3", 2096 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", 2097 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", 2098 | "dev": true, 2099 | "requires": { 2100 | "anymatch": "~3.1.2", 2101 | "braces": "~3.0.2", 2102 | "fsevents": "~2.3.2", 2103 | "glob-parent": "~5.1.2", 2104 | "is-binary-path": "~2.1.0", 2105 | "is-glob": "~4.0.1", 2106 | "normalize-path": "~3.0.0", 2107 | "readdirp": "~3.6.0" 2108 | } 2109 | }, 2110 | "diff": { 2111 | "version": "5.0.0", 2112 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 2113 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 2114 | "dev": true 2115 | }, 2116 | "escape-string-regexp": { 2117 | "version": "4.0.0", 2118 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 2119 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 2120 | "dev": true 2121 | }, 2122 | "fill-range": { 2123 | "version": "7.0.1", 2124 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 2125 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 2126 | "requires": { 2127 | "to-regex-range": "^5.0.1" 2128 | } 2129 | }, 2130 | "find-up": { 2131 | "version": "5.0.0", 2132 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 2133 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 2134 | "dev": true, 2135 | "requires": { 2136 | "locate-path": "^6.0.0", 2137 | "path-exists": "^4.0.0" 2138 | } 2139 | }, 2140 | "fsevents": { 2141 | "version": "2.3.2", 2142 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", 2143 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", 2144 | "dev": true, 2145 | "optional": true 2146 | }, 2147 | "glob-parent": { 2148 | "version": "5.1.2", 2149 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 2150 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 2151 | "dev": true, 2152 | "requires": { 2153 | "is-glob": "^4.0.1" 2154 | } 2155 | }, 2156 | "has-flag": { 2157 | "version": "4.0.0", 2158 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 2159 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 2160 | "dev": true 2161 | }, 2162 | "is-binary-path": { 2163 | "version": "2.1.0", 2164 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 2165 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 2166 | "dev": true, 2167 | "requires": { 2168 | "binary-extensions": "^2.0.0" 2169 | } 2170 | }, 2171 | "is-number": { 2172 | "version": "7.0.0", 2173 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 2174 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" 2175 | }, 2176 | "js-yaml": { 2177 | "version": "4.1.0", 2178 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 2179 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 2180 | "dev": true, 2181 | "requires": { 2182 | "argparse": "^2.0.1" 2183 | } 2184 | }, 2185 | "locate-path": { 2186 | "version": "6.0.0", 2187 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 2188 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 2189 | "dev": true, 2190 | "requires": { 2191 | "p-locate": "^5.0.0" 2192 | } 2193 | }, 2194 | "minimatch": { 2195 | "version": "5.0.1", 2196 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", 2197 | "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", 2198 | "dev": true, 2199 | "requires": { 2200 | "brace-expansion": "^2.0.1" 2201 | } 2202 | }, 2203 | "ms": { 2204 | "version": "2.1.3", 2205 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 2206 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 2207 | "dev": true 2208 | }, 2209 | "p-limit": { 2210 | "version": "3.1.0", 2211 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 2212 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 2213 | "dev": true, 2214 | "requires": { 2215 | "yocto-queue": "^0.1.0" 2216 | } 2217 | }, 2218 | "p-locate": { 2219 | "version": "5.0.0", 2220 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 2221 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 2222 | "dev": true, 2223 | "requires": { 2224 | "p-limit": "^3.0.2" 2225 | } 2226 | }, 2227 | "path-exists": { 2228 | "version": "4.0.0", 2229 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 2230 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 2231 | "dev": true 2232 | }, 2233 | "readdirp": { 2234 | "version": "3.6.0", 2235 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 2236 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 2237 | "dev": true, 2238 | "requires": { 2239 | "picomatch": "^2.2.1" 2240 | } 2241 | }, 2242 | "strip-json-comments": { 2243 | "version": "3.1.1", 2244 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2245 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2246 | "dev": true 2247 | }, 2248 | "supports-color": { 2249 | "version": "8.1.1", 2250 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 2251 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 2252 | "dev": true, 2253 | "requires": { 2254 | "has-flag": "^4.0.0" 2255 | } 2256 | }, 2257 | "to-regex-range": { 2258 | "version": "5.0.1", 2259 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2260 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2261 | "requires": { 2262 | "is-number": "^7.0.0" 2263 | } 2264 | } 2265 | } 2266 | }, 2267 | "ms": { 2268 | "version": "2.0.0", 2269 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 2270 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 2271 | "dev": true 2272 | }, 2273 | "nanoid": { 2274 | "version": "3.3.3", 2275 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", 2276 | "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", 2277 | "dev": true 2278 | }, 2279 | "natural-compare": { 2280 | "version": "1.4.0", 2281 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 2282 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 2283 | "dev": true 2284 | }, 2285 | "nice-try": { 2286 | "version": "1.0.5", 2287 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 2288 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", 2289 | "dev": true 2290 | }, 2291 | "nodemon": { 2292 | "version": "3.1.3", 2293 | "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.3.tgz", 2294 | "integrity": "sha512-m4Vqs+APdKzDFpuaL9F9EVOF85+h070FnkHVEoU4+rmT6Vw0bmNl7s61VEkY/cJkL7RCv1p4urnUDUMrS5rk2w==", 2295 | "dev": true, 2296 | "requires": { 2297 | "chokidar": "^3.5.2", 2298 | "debug": "^4", 2299 | "ignore-by-default": "^1.0.1", 2300 | "minimatch": "^3.1.2", 2301 | "pstree.remy": "^1.1.8", 2302 | "semver": "^7.5.3", 2303 | "simple-update-notifier": "^2.0.0", 2304 | "supports-color": "^5.5.0", 2305 | "touch": "^3.1.0", 2306 | "undefsafe": "^2.0.5" 2307 | }, 2308 | "dependencies": { 2309 | "semver": { 2310 | "version": "7.6.2", 2311 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", 2312 | "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", 2313 | "dev": true 2314 | }, 2315 | "supports-color": { 2316 | "version": "5.5.0", 2317 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 2318 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 2319 | "dev": true, 2320 | "requires": { 2321 | "has-flag": "^3.0.0" 2322 | } 2323 | } 2324 | } 2325 | }, 2326 | "normalize-package-data": { 2327 | "version": "2.5.0", 2328 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", 2329 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", 2330 | "dev": true, 2331 | "requires": { 2332 | "hosted-git-info": "^2.1.4", 2333 | "resolve": "^1.10.0", 2334 | "semver": "2 || 3 || 4 || 5", 2335 | "validate-npm-package-license": "^3.0.1" 2336 | } 2337 | }, 2338 | "normalize-path": { 2339 | "version": "3.0.0", 2340 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 2341 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 2342 | "dev": true 2343 | }, 2344 | "npm-run-path": { 2345 | "version": "2.0.2", 2346 | "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", 2347 | "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", 2348 | "dev": true, 2349 | "requires": { 2350 | "path-key": "^2.0.0" 2351 | } 2352 | }, 2353 | "object-inspect": { 2354 | "version": "1.9.0", 2355 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", 2356 | "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", 2357 | "dev": true 2358 | }, 2359 | "object-keys": { 2360 | "version": "1.1.1", 2361 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 2362 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 2363 | "dev": true 2364 | }, 2365 | "object.assign": { 2366 | "version": "4.1.2", 2367 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", 2368 | "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", 2369 | "dev": true, 2370 | "requires": { 2371 | "call-bind": "^1.0.0", 2372 | "define-properties": "^1.1.3", 2373 | "has-symbols": "^1.0.1", 2374 | "object-keys": "^1.1.1" 2375 | } 2376 | }, 2377 | "object.entries": { 2378 | "version": "1.1.3", 2379 | "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.3.tgz", 2380 | "integrity": "sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg==", 2381 | "dev": true, 2382 | "requires": { 2383 | "call-bind": "^1.0.0", 2384 | "define-properties": "^1.1.3", 2385 | "es-abstract": "^1.18.0-next.1", 2386 | "has": "^1.0.3" 2387 | } 2388 | }, 2389 | "object.values": { 2390 | "version": "1.1.2", 2391 | "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.2.tgz", 2392 | "integrity": "sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag==", 2393 | "dev": true, 2394 | "requires": { 2395 | "call-bind": "^1.0.0", 2396 | "define-properties": "^1.1.3", 2397 | "es-abstract": "^1.18.0-next.1", 2398 | "has": "^1.0.3" 2399 | } 2400 | }, 2401 | "once": { 2402 | "version": "1.4.0", 2403 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2404 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 2405 | "dev": true, 2406 | "requires": { 2407 | "wrappy": "1" 2408 | } 2409 | }, 2410 | "optionator": { 2411 | "version": "0.9.1", 2412 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 2413 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 2414 | "dev": true, 2415 | "requires": { 2416 | "deep-is": "^0.1.3", 2417 | "fast-levenshtein": "^2.0.6", 2418 | "levn": "^0.4.1", 2419 | "prelude-ls": "^1.2.1", 2420 | "type-check": "^0.4.0", 2421 | "word-wrap": "^1.2.3" 2422 | } 2423 | }, 2424 | "p-finally": { 2425 | "version": "1.0.0", 2426 | "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", 2427 | "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", 2428 | "dev": true 2429 | }, 2430 | "p-limit": { 2431 | "version": "2.3.0", 2432 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 2433 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 2434 | "dev": true, 2435 | "requires": { 2436 | "p-try": "^2.0.0" 2437 | } 2438 | }, 2439 | "p-locate": { 2440 | "version": "3.0.0", 2441 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 2442 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 2443 | "dev": true, 2444 | "requires": { 2445 | "p-limit": "^2.0.0" 2446 | } 2447 | }, 2448 | "p-try": { 2449 | "version": "2.2.0", 2450 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 2451 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 2452 | "dev": true 2453 | }, 2454 | "parent-module": { 2455 | "version": "1.0.1", 2456 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 2457 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 2458 | "dev": true, 2459 | "requires": { 2460 | "callsites": "^3.0.0" 2461 | } 2462 | }, 2463 | "parse-json": { 2464 | "version": "4.0.0", 2465 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", 2466 | "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", 2467 | "dev": true, 2468 | "requires": { 2469 | "error-ex": "^1.3.1", 2470 | "json-parse-better-errors": "^1.0.1" 2471 | } 2472 | }, 2473 | "path-exists": { 2474 | "version": "3.0.0", 2475 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 2476 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 2477 | "dev": true 2478 | }, 2479 | "path-is-absolute": { 2480 | "version": "1.0.1", 2481 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2482 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 2483 | "dev": true 2484 | }, 2485 | "path-key": { 2486 | "version": "2.0.1", 2487 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 2488 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", 2489 | "dev": true 2490 | }, 2491 | "path-parse": { 2492 | "version": "1.0.7", 2493 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 2494 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 2495 | "dev": true 2496 | }, 2497 | "path-type": { 2498 | "version": "4.0.0", 2499 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 2500 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 2501 | "dev": true 2502 | }, 2503 | "pathval": { 2504 | "version": "1.1.1", 2505 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 2506 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 2507 | "dev": true 2508 | }, 2509 | "picomatch": { 2510 | "version": "2.2.2", 2511 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 2512 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 2513 | "dev": true 2514 | }, 2515 | "pkg-dir": { 2516 | "version": "4.2.0", 2517 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 2518 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 2519 | "dev": true, 2520 | "requires": { 2521 | "find-up": "^4.0.0" 2522 | }, 2523 | "dependencies": { 2524 | "find-up": { 2525 | "version": "4.1.0", 2526 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 2527 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 2528 | "dev": true, 2529 | "requires": { 2530 | "locate-path": "^5.0.0", 2531 | "path-exists": "^4.0.0" 2532 | } 2533 | }, 2534 | "locate-path": { 2535 | "version": "5.0.0", 2536 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 2537 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 2538 | "dev": true, 2539 | "requires": { 2540 | "p-locate": "^4.1.0" 2541 | } 2542 | }, 2543 | "p-locate": { 2544 | "version": "4.1.0", 2545 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 2546 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 2547 | "dev": true, 2548 | "requires": { 2549 | "p-limit": "^2.2.0" 2550 | } 2551 | }, 2552 | "path-exists": { 2553 | "version": "4.0.0", 2554 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 2555 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 2556 | "dev": true 2557 | } 2558 | } 2559 | }, 2560 | "please-upgrade-node": { 2561 | "version": "3.2.0", 2562 | "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", 2563 | "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", 2564 | "dev": true, 2565 | "requires": { 2566 | "semver-compare": "^1.0.0" 2567 | } 2568 | }, 2569 | "prelude-ls": { 2570 | "version": "1.2.1", 2571 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 2572 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 2573 | "dev": true 2574 | }, 2575 | "progress": { 2576 | "version": "2.0.3", 2577 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 2578 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 2579 | "dev": true 2580 | }, 2581 | "pstree.remy": { 2582 | "version": "1.1.8", 2583 | "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", 2584 | "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", 2585 | "dev": true 2586 | }, 2587 | "pump": { 2588 | "version": "3.0.0", 2589 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 2590 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 2591 | "dev": true, 2592 | "requires": { 2593 | "end-of-stream": "^1.1.0", 2594 | "once": "^1.3.1" 2595 | } 2596 | }, 2597 | "punycode": { 2598 | "version": "2.1.1", 2599 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 2600 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 2601 | "dev": true 2602 | }, 2603 | "randombytes": { 2604 | "version": "2.1.0", 2605 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", 2606 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", 2607 | "dev": true, 2608 | "requires": { 2609 | "safe-buffer": "^5.1.0" 2610 | } 2611 | }, 2612 | "read-pkg": { 2613 | "version": "5.2.0", 2614 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", 2615 | "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", 2616 | "dev": true, 2617 | "requires": { 2618 | "@types/normalize-package-data": "^2.4.0", 2619 | "normalize-package-data": "^2.5.0", 2620 | "parse-json": "^5.0.0", 2621 | "type-fest": "^0.6.0" 2622 | }, 2623 | "dependencies": { 2624 | "parse-json": { 2625 | "version": "5.0.0", 2626 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", 2627 | "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", 2628 | "dev": true, 2629 | "requires": { 2630 | "@babel/code-frame": "^7.0.0", 2631 | "error-ex": "^1.3.1", 2632 | "json-parse-better-errors": "^1.0.1", 2633 | "lines-and-columns": "^1.1.6" 2634 | } 2635 | } 2636 | } 2637 | }, 2638 | "read-pkg-up": { 2639 | "version": "2.0.0", 2640 | "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", 2641 | "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", 2642 | "dev": true, 2643 | "requires": { 2644 | "find-up": "^2.0.0", 2645 | "read-pkg": "^2.0.0" 2646 | }, 2647 | "dependencies": { 2648 | "find-up": { 2649 | "version": "2.1.0", 2650 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", 2651 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", 2652 | "dev": true, 2653 | "requires": { 2654 | "locate-path": "^2.0.0" 2655 | } 2656 | }, 2657 | "locate-path": { 2658 | "version": "2.0.0", 2659 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", 2660 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", 2661 | "dev": true, 2662 | "requires": { 2663 | "p-locate": "^2.0.0", 2664 | "path-exists": "^3.0.0" 2665 | } 2666 | }, 2667 | "p-limit": { 2668 | "version": "1.3.0", 2669 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", 2670 | "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", 2671 | "dev": true, 2672 | "requires": { 2673 | "p-try": "^1.0.0" 2674 | } 2675 | }, 2676 | "p-locate": { 2677 | "version": "2.0.0", 2678 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", 2679 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", 2680 | "dev": true, 2681 | "requires": { 2682 | "p-limit": "^1.1.0" 2683 | } 2684 | }, 2685 | "p-try": { 2686 | "version": "1.0.0", 2687 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", 2688 | "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", 2689 | "dev": true 2690 | }, 2691 | "path-type": { 2692 | "version": "2.0.0", 2693 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", 2694 | "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", 2695 | "dev": true, 2696 | "requires": { 2697 | "pify": "^2.0.0" 2698 | } 2699 | }, 2700 | "pify": { 2701 | "version": "2.3.0", 2702 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 2703 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 2704 | "dev": true 2705 | }, 2706 | "read-pkg": { 2707 | "version": "2.0.0", 2708 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", 2709 | "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", 2710 | "dev": true, 2711 | "requires": { 2712 | "load-json-file": "^2.0.0", 2713 | "normalize-package-data": "^2.3.2", 2714 | "path-type": "^2.0.0" 2715 | } 2716 | } 2717 | } 2718 | }, 2719 | "readdirp": { 2720 | "version": "3.6.0", 2721 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 2722 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 2723 | "dev": true, 2724 | "requires": { 2725 | "picomatch": "^2.2.1" 2726 | } 2727 | }, 2728 | "regexpp": { 2729 | "version": "3.1.0", 2730 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", 2731 | "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", 2732 | "dev": true 2733 | }, 2734 | "require-directory": { 2735 | "version": "2.1.1", 2736 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 2737 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 2738 | "dev": true 2739 | }, 2740 | "resolve": { 2741 | "version": "1.17.0", 2742 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", 2743 | "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", 2744 | "dev": true, 2745 | "requires": { 2746 | "path-parse": "^1.0.6" 2747 | } 2748 | }, 2749 | "resolve-from": { 2750 | "version": "4.0.0", 2751 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 2752 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 2753 | "dev": true 2754 | }, 2755 | "reusify": { 2756 | "version": "1.0.4", 2757 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 2758 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 2759 | "dev": true 2760 | }, 2761 | "rimraf": { 2762 | "version": "3.0.2", 2763 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2764 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2765 | "dev": true, 2766 | "requires": { 2767 | "glob": "^7.1.3" 2768 | }, 2769 | "dependencies": { 2770 | "glob": { 2771 | "version": "7.1.6", 2772 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 2773 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 2774 | "dev": true, 2775 | "requires": { 2776 | "fs.realpath": "^1.0.0", 2777 | "inflight": "^1.0.4", 2778 | "inherits": "2", 2779 | "minimatch": "^3.0.4", 2780 | "once": "^1.3.0", 2781 | "path-is-absolute": "^1.0.0" 2782 | } 2783 | } 2784 | } 2785 | }, 2786 | "run-node": { 2787 | "version": "1.0.0", 2788 | "resolved": "https://registry.npmjs.org/run-node/-/run-node-1.0.0.tgz", 2789 | "integrity": "sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==", 2790 | "dev": true 2791 | }, 2792 | "run-parallel": { 2793 | "version": "1.1.10", 2794 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", 2795 | "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", 2796 | "dev": true 2797 | }, 2798 | "safe-buffer": { 2799 | "version": "5.1.2", 2800 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 2801 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 2802 | "dev": true 2803 | }, 2804 | "semver": { 2805 | "version": "5.5.0", 2806 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", 2807 | "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", 2808 | "dev": true 2809 | }, 2810 | "semver-compare": { 2811 | "version": "1.0.0", 2812 | "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", 2813 | "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", 2814 | "dev": true 2815 | }, 2816 | "serialize-javascript": { 2817 | "version": "6.0.0", 2818 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", 2819 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", 2820 | "dev": true, 2821 | "requires": { 2822 | "randombytes": "^2.1.0" 2823 | } 2824 | }, 2825 | "shebang-command": { 2826 | "version": "1.2.0", 2827 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 2828 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 2829 | "dev": true, 2830 | "requires": { 2831 | "shebang-regex": "^1.0.0" 2832 | } 2833 | }, 2834 | "shebang-regex": { 2835 | "version": "1.0.0", 2836 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 2837 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 2838 | "dev": true 2839 | }, 2840 | "signal-exit": { 2841 | "version": "3.0.2", 2842 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 2843 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 2844 | "dev": true 2845 | }, 2846 | "simple-update-notifier": { 2847 | "version": "2.0.0", 2848 | "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", 2849 | "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", 2850 | "dev": true, 2851 | "requires": { 2852 | "semver": "^7.5.3" 2853 | }, 2854 | "dependencies": { 2855 | "semver": { 2856 | "version": "7.6.2", 2857 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", 2858 | "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", 2859 | "dev": true 2860 | } 2861 | } 2862 | }, 2863 | "slash": { 2864 | "version": "3.0.0", 2865 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 2866 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 2867 | "dev": true 2868 | }, 2869 | "slice-ansi": { 2870 | "version": "2.1.0", 2871 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", 2872 | "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", 2873 | "dev": true, 2874 | "requires": { 2875 | "ansi-styles": "^3.2.0", 2876 | "astral-regex": "^1.0.0", 2877 | "is-fullwidth-code-point": "^2.0.0" 2878 | } 2879 | }, 2880 | "source-map": { 2881 | "version": "0.6.1", 2882 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2883 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 2884 | "dev": true 2885 | }, 2886 | "source-map-support": { 2887 | "version": "0.5.19", 2888 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", 2889 | "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", 2890 | "dev": true, 2891 | "requires": { 2892 | "buffer-from": "^1.0.0", 2893 | "source-map": "^0.6.0" 2894 | } 2895 | }, 2896 | "spdx-correct": { 2897 | "version": "3.1.1", 2898 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", 2899 | "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", 2900 | "dev": true, 2901 | "requires": { 2902 | "spdx-expression-parse": "^3.0.0", 2903 | "spdx-license-ids": "^3.0.0" 2904 | } 2905 | }, 2906 | "spdx-exceptions": { 2907 | "version": "2.3.0", 2908 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", 2909 | "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", 2910 | "dev": true 2911 | }, 2912 | "spdx-expression-parse": { 2913 | "version": "3.0.1", 2914 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", 2915 | "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", 2916 | "dev": true, 2917 | "requires": { 2918 | "spdx-exceptions": "^2.1.0", 2919 | "spdx-license-ids": "^3.0.0" 2920 | } 2921 | }, 2922 | "spdx-license-ids": { 2923 | "version": "3.0.5", 2924 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", 2925 | "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", 2926 | "dev": true 2927 | }, 2928 | "sprintf-js": { 2929 | "version": "1.0.3", 2930 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2931 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 2932 | "dev": true 2933 | }, 2934 | "string.prototype.trimend": { 2935 | "version": "1.0.3", 2936 | "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", 2937 | "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", 2938 | "dev": true, 2939 | "requires": { 2940 | "call-bind": "^1.0.0", 2941 | "define-properties": "^1.1.3" 2942 | } 2943 | }, 2944 | "string.prototype.trimstart": { 2945 | "version": "1.0.3", 2946 | "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", 2947 | "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", 2948 | "dev": true, 2949 | "requires": { 2950 | "call-bind": "^1.0.0", 2951 | "define-properties": "^1.1.3" 2952 | } 2953 | }, 2954 | "strip-bom": { 2955 | "version": "3.0.0", 2956 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 2957 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", 2958 | "dev": true 2959 | }, 2960 | "strip-eof": { 2961 | "version": "1.0.0", 2962 | "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", 2963 | "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", 2964 | "dev": true 2965 | }, 2966 | "supports-color": { 2967 | "version": "5.4.0", 2968 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", 2969 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", 2970 | "dev": true, 2971 | "requires": { 2972 | "has-flag": "^3.0.0" 2973 | } 2974 | }, 2975 | "table": { 2976 | "version": "5.4.6", 2977 | "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", 2978 | "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", 2979 | "dev": true, 2980 | "requires": { 2981 | "ajv": "^6.10.2", 2982 | "lodash": "^4.17.14", 2983 | "slice-ansi": "^2.1.0", 2984 | "string-width": "^3.0.0" 2985 | }, 2986 | "dependencies": { 2987 | "ansi-regex": { 2988 | "version": "4.1.1", 2989 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", 2990 | "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", 2991 | "dev": true 2992 | }, 2993 | "string-width": { 2994 | "version": "3.1.0", 2995 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 2996 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 2997 | "dev": true, 2998 | "requires": { 2999 | "emoji-regex": "^7.0.1", 3000 | "is-fullwidth-code-point": "^2.0.0", 3001 | "strip-ansi": "^5.1.0" 3002 | } 3003 | }, 3004 | "strip-ansi": { 3005 | "version": "5.2.0", 3006 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 3007 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 3008 | "dev": true, 3009 | "requires": { 3010 | "ansi-regex": "^4.1.0" 3011 | } 3012 | } 3013 | } 3014 | }, 3015 | "text-table": { 3016 | "version": "0.2.0", 3017 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 3018 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 3019 | "dev": true 3020 | }, 3021 | "to-regex-range": { 3022 | "version": "5.0.1", 3023 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 3024 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 3025 | "dev": true, 3026 | "requires": { 3027 | "is-number": "^7.0.0" 3028 | } 3029 | }, 3030 | "touch": { 3031 | "version": "3.1.1", 3032 | "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", 3033 | "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", 3034 | "dev": true 3035 | }, 3036 | "ts-node": { 3037 | "version": "7.0.1", 3038 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", 3039 | "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", 3040 | "dev": true, 3041 | "requires": { 3042 | "arrify": "^1.0.0", 3043 | "buffer-from": "^1.1.0", 3044 | "diff": "^3.1.0", 3045 | "make-error": "^1.1.1", 3046 | "minimist": "^1.2.0", 3047 | "mkdirp": "^0.5.1", 3048 | "source-map-support": "^0.5.6", 3049 | "yn": "^2.0.0" 3050 | } 3051 | }, 3052 | "tsconfig-paths": { 3053 | "version": "3.14.1", 3054 | "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", 3055 | "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", 3056 | "dev": true, 3057 | "requires": { 3058 | "@types/json5": "^0.0.29", 3059 | "json5": "^1.0.1", 3060 | "minimist": "^1.2.6", 3061 | "strip-bom": "^3.0.0" 3062 | }, 3063 | "dependencies": { 3064 | "minimist": { 3065 | "version": "1.2.7", 3066 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", 3067 | "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", 3068 | "dev": true 3069 | } 3070 | } 3071 | }, 3072 | "tslib": { 3073 | "version": "1.14.1", 3074 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 3075 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", 3076 | "dev": true 3077 | }, 3078 | "tsutils": { 3079 | "version": "3.17.1", 3080 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz", 3081 | "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==", 3082 | "dev": true, 3083 | "requires": { 3084 | "tslib": "^1.8.1" 3085 | } 3086 | }, 3087 | "type-check": { 3088 | "version": "0.4.0", 3089 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 3090 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 3091 | "dev": true, 3092 | "requires": { 3093 | "prelude-ls": "^1.2.1" 3094 | } 3095 | }, 3096 | "type-detect": { 3097 | "version": "4.0.8", 3098 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 3099 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 3100 | "dev": true 3101 | }, 3102 | "type-fest": { 3103 | "version": "0.6.0", 3104 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", 3105 | "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", 3106 | "dev": true 3107 | }, 3108 | "typescript": { 3109 | "version": "3.7.5", 3110 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz", 3111 | "integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==", 3112 | "dev": true 3113 | }, 3114 | "undefsafe": { 3115 | "version": "2.0.5", 3116 | "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", 3117 | "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", 3118 | "dev": true 3119 | }, 3120 | "uri-js": { 3121 | "version": "4.4.0", 3122 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", 3123 | "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", 3124 | "dev": true, 3125 | "requires": { 3126 | "punycode": "^2.1.0" 3127 | } 3128 | }, 3129 | "v8-compile-cache": { 3130 | "version": "2.2.0", 3131 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", 3132 | "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", 3133 | "dev": true 3134 | }, 3135 | "validate-npm-package-license": { 3136 | "version": "3.0.4", 3137 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 3138 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 3139 | "dev": true, 3140 | "requires": { 3141 | "spdx-correct": "^3.0.0", 3142 | "spdx-expression-parse": "^3.0.0" 3143 | } 3144 | }, 3145 | "which": { 3146 | "version": "1.3.1", 3147 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 3148 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 3149 | "dev": true, 3150 | "requires": { 3151 | "isexe": "^2.0.0" 3152 | } 3153 | }, 3154 | "word-wrap": { 3155 | "version": "1.2.4", 3156 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz", 3157 | "integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==", 3158 | "dev": true 3159 | }, 3160 | "workerpool": { 3161 | "version": "6.2.1", 3162 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", 3163 | "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", 3164 | "dev": true 3165 | }, 3166 | "wrap-ansi": { 3167 | "version": "7.0.0", 3168 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 3169 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 3170 | "dev": true, 3171 | "requires": { 3172 | "ansi-styles": "^4.0.0", 3173 | "string-width": "^4.1.0", 3174 | "strip-ansi": "^6.0.0" 3175 | }, 3176 | "dependencies": { 3177 | "ansi-styles": { 3178 | "version": "4.3.0", 3179 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 3180 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 3181 | "dev": true, 3182 | "requires": { 3183 | "color-convert": "^2.0.1" 3184 | } 3185 | }, 3186 | "color-convert": { 3187 | "version": "2.0.1", 3188 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 3189 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 3190 | "dev": true, 3191 | "requires": { 3192 | "color-name": "~1.1.4" 3193 | } 3194 | }, 3195 | "color-name": { 3196 | "version": "1.1.4", 3197 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 3198 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 3199 | "dev": true 3200 | }, 3201 | "emoji-regex": { 3202 | "version": "8.0.0", 3203 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 3204 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 3205 | "dev": true 3206 | }, 3207 | "is-fullwidth-code-point": { 3208 | "version": "3.0.0", 3209 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 3210 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 3211 | "dev": true 3212 | }, 3213 | "string-width": { 3214 | "version": "4.2.3", 3215 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 3216 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 3217 | "dev": true, 3218 | "requires": { 3219 | "emoji-regex": "^8.0.0", 3220 | "is-fullwidth-code-point": "^3.0.0", 3221 | "strip-ansi": "^6.0.1" 3222 | } 3223 | }, 3224 | "strip-ansi": { 3225 | "version": "6.0.1", 3226 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 3227 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 3228 | "dev": true, 3229 | "requires": { 3230 | "ansi-regex": "^5.0.1" 3231 | } 3232 | } 3233 | } 3234 | }, 3235 | "wrappy": { 3236 | "version": "1.0.2", 3237 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 3238 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 3239 | "dev": true 3240 | }, 3241 | "y18n": { 3242 | "version": "5.0.8", 3243 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 3244 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 3245 | "dev": true 3246 | }, 3247 | "yargs": { 3248 | "version": "16.2.0", 3249 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 3250 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 3251 | "dev": true, 3252 | "requires": { 3253 | "cliui": "^7.0.2", 3254 | "escalade": "^3.1.1", 3255 | "get-caller-file": "^2.0.5", 3256 | "require-directory": "^2.1.1", 3257 | "string-width": "^4.2.0", 3258 | "y18n": "^5.0.5", 3259 | "yargs-parser": "^20.2.2" 3260 | }, 3261 | "dependencies": { 3262 | "emoji-regex": { 3263 | "version": "8.0.0", 3264 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 3265 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 3266 | "dev": true 3267 | }, 3268 | "is-fullwidth-code-point": { 3269 | "version": "3.0.0", 3270 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 3271 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 3272 | "dev": true 3273 | }, 3274 | "string-width": { 3275 | "version": "4.2.3", 3276 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 3277 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 3278 | "dev": true, 3279 | "requires": { 3280 | "emoji-regex": "^8.0.0", 3281 | "is-fullwidth-code-point": "^3.0.0", 3282 | "strip-ansi": "^6.0.1" 3283 | } 3284 | }, 3285 | "strip-ansi": { 3286 | "version": "6.0.1", 3287 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 3288 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 3289 | "dev": true, 3290 | "requires": { 3291 | "ansi-regex": "^5.0.1" 3292 | } 3293 | } 3294 | } 3295 | }, 3296 | "yargs-parser": { 3297 | "version": "20.2.4", 3298 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", 3299 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", 3300 | "dev": true 3301 | }, 3302 | "yargs-unparser": { 3303 | "version": "2.0.0", 3304 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 3305 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 3306 | "dev": true, 3307 | "requires": { 3308 | "camelcase": "^6.0.0", 3309 | "decamelize": "^4.0.0", 3310 | "flat": "^5.0.2", 3311 | "is-plain-obj": "^2.1.0" 3312 | }, 3313 | "dependencies": { 3314 | "camelcase": { 3315 | "version": "6.3.0", 3316 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", 3317 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", 3318 | "dev": true 3319 | } 3320 | } 3321 | }, 3322 | "yn": { 3323 | "version": "2.0.0", 3324 | "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", 3325 | "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", 3326 | "dev": true 3327 | }, 3328 | "yocto-queue": { 3329 | "version": "0.1.0", 3330 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 3331 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 3332 | "dev": true 3333 | } 3334 | } 3335 | } 3336 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nucleojs", 3 | "version": "1.4.1", 4 | "main": "dist/index.js", 5 | "types": "dist/index.d.ts", 6 | "author": "Matheus Marsiglio ", 7 | "repository": "git://github.com/mtmr0x/nucleo", 8 | "license": "MIT", 9 | "private": false, 10 | "husky": { 11 | "hooks": { 12 | "pre-commit": "npm run tests && npm run lint", 13 | "pre-push": "npm run tests && npm run lint" 14 | } 15 | }, 16 | "devDependencies": { 17 | "@types/chai": "^4.2.11", 18 | "@types/mocha": "^5.2.7", 19 | "@typescript-eslint/eslint-plugin": "^4.9.1", 20 | "@typescript-eslint/parser": "^4.9.1", 21 | "chai": "^4.2.0", 22 | "eslint": "^7.15.0", 23 | "eslint-config-airbnb-base": "^14.2.1", 24 | "eslint-config-google": "^0.14.0", 25 | "eslint-config-standard": "^16.0.2", 26 | "eslint-plugin-import": "^2.22.1", 27 | "eslint-plugin-node": "^11.1.0", 28 | "eslint-plugin-promise": "^4.2.1", 29 | "husky": "^2.7.0", 30 | "mocha": "^10.2.0", 31 | "nodemon": "^3.1.3", 32 | "ts-node": "^7.0.1", 33 | "typescript": "3.7.5" 34 | }, 35 | "scripts": { 36 | "start": "ts-node ./src/index.ts", 37 | "nodemon": "nodemon", 38 | "tests": "mocha -r ts-node/register **/*.spec.ts", 39 | "lint": "./node_modules/.bin/eslint src/*.ts src/**/*.ts", 40 | "compile": "tsc" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/_types/Contracts.ts: -------------------------------------------------------------------------------- 1 | import { NucleoObjectType } from './NucleoObjectType'; 2 | 3 | export interface Contracts { 4 | [key: string]: NucleoObjectType 5 | } 6 | 7 | -------------------------------------------------------------------------------- /src/_types/NucleoListType.ts: -------------------------------------------------------------------------------- 1 | export type NucleoListType = { 2 | getListChildrenType: () => string; 3 | }; 4 | 5 | -------------------------------------------------------------------------------- /src/_types/NucleoObjectType.ts: -------------------------------------------------------------------------------- 1 | export interface NucleoObjectType { 2 | name: string; 3 | fields: { [key: string]: any }; 4 | } 5 | -------------------------------------------------------------------------------- /src/_types/NucleoPrimitiveType.ts: -------------------------------------------------------------------------------- 1 | export interface SerializeFunction { 2 | (value: T): boolean 3 | } 4 | 5 | export type NucleoPrimitiveType = { 6 | Type: string, 7 | serialize: SerializeFunction 8 | }; 9 | -------------------------------------------------------------------------------- /src/_types/State.ts: -------------------------------------------------------------------------------- 1 | export type State = { 2 | [key: string]: string|number|boolean, 3 | } 4 | 5 | -------------------------------------------------------------------------------- /src/_types/Update.ts: -------------------------------------------------------------------------------- 1 | interface UpdateError { 2 | contract: string; 3 | error: string; 4 | } 5 | 6 | export interface Update { 7 | status: '' | 'OK' | 'NOK'; 8 | errors: UpdateError[]; 9 | data: T; 10 | } 11 | -------------------------------------------------------------------------------- /src/executeListeners.ts: -------------------------------------------------------------------------------- 1 | import { Listener } from './subscribe'; 2 | 3 | const executeListeners = (contractName: string, listeners: Array, data: any) => { 4 | for (let i = 0; i < listeners.length; i++) { 5 | if (listeners[i].on) { 6 | listeners[i].listener({ contractName, data }); 7 | } 8 | } 9 | }; 10 | 11 | export default executeListeners; 12 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { createStore } from './store'; 2 | 3 | import { 4 | NucleoString, 5 | NucleoNumber, 6 | NucleoBoolean, 7 | NucleoStringAssertion, 8 | NucleoNumberAssertion 9 | } from './nucleoTypes/primitive'; 10 | 11 | import NucleoObject from './nucleoTypes/NucleoObject'; 12 | import NucleoList from './nucleoTypes/NucleoList'; 13 | 14 | export { 15 | createStore, 16 | NucleoString, 17 | NucleoNumber, 18 | NucleoBoolean, 19 | NucleoStringAssertion, 20 | NucleoNumberAssertion, 21 | NucleoList, 22 | NucleoObject, 23 | }; 24 | -------------------------------------------------------------------------------- /src/indexSearch.ts: -------------------------------------------------------------------------------- 1 | import executeListeners from './executeListeners'; 2 | import { Listener } from './subscribe'; 3 | 4 | const saveType = (data:any):'rec'|'save' => { 5 | if (typeof data === 'object' && !Array.isArray(data)) { 6 | return 'rec'; 7 | } 8 | 9 | return 'save'; 10 | }; 11 | 12 | interface IndexSearch { 13 | contractName: string; 14 | storeData: any; 15 | data: any; 16 | listeners: Array|void; 17 | newStoreData: any; 18 | newListenersData: any; 19 | } 20 | 21 | export default function indexSearch(args: IndexSearch) { 22 | const { 23 | contractName, 24 | storeData = {}, 25 | data, 26 | listeners, 27 | newStoreData = {}, 28 | newListenersData = {} 29 | } = args; 30 | 31 | const storeDataKeys = Object.keys(storeData); 32 | 33 | for (let i = 0; storeDataKeys.length > i; i++) { 34 | const dataTypeMapper = () => ({ 35 | rec: () => { 36 | const bufferData = data[storeDataKeys[i]] === null || data[storeDataKeys[i]] === undefined ? storeData[storeDataKeys[i]] : data[storeDataKeys[i]]; 37 | newStoreData[storeDataKeys[i]] = {}; 38 | newListenersData[storeDataKeys[i]] = {}; 39 | 40 | return indexSearch({ 41 | contractName: '', 42 | storeData: storeData[storeDataKeys[i]], 43 | data: bufferData, 44 | listeners: undefined, 45 | newStoreData: newStoreData[storeDataKeys[i]], 46 | newListenersData: newListenersData[storeDataKeys[i]] 47 | }); 48 | }, 49 | save: () => { 50 | const nonExistentValue = data[storeDataKeys[i]] === null || data[storeDataKeys[i]] === undefined ? true : false; 51 | if (!nonExistentValue) { 52 | newStoreData[storeDataKeys[i]] = data[storeDataKeys[i]]; 53 | return newListenersData[storeDataKeys[i]] = data[storeDataKeys[i]]; 54 | } 55 | newStoreData[storeDataKeys[i]] = storeData[storeDataKeys[i]]; 56 | return newListenersData[storeDataKeys[i]] = storeData[storeDataKeys[i]]; 57 | } 58 | }); 59 | 60 | dataTypeMapper()[saveType(storeData[storeDataKeys[i]])](); 61 | } 62 | 63 | if (listeners && listeners.length) { 64 | executeListeners(contractName, listeners, newListenersData); 65 | } 66 | return newStoreData; 67 | } 68 | -------------------------------------------------------------------------------- /src/nucleoTypes/NucleoList.ts: -------------------------------------------------------------------------------- 1 | import { NucleoObjectType } from './../_types/NucleoObjectType'; 2 | import { NucleoListType } from './../_types/NucleoListType'; 3 | import { SerializeFunction } from './../_types/NucleoPrimitiveType'; 4 | 5 | import NucleoObject from './../nucleoTypes/NucleoObject'; 6 | 7 | interface N { 8 | name?: string; 9 | fields?: any; 10 | Type?: string; 11 | serialize?: SerializeFunction; 12 | } 13 | 14 | export default class NucleoList implements NucleoListType { 15 | NucleoObject: NucleoObjectType; 16 | NucleoPrimitive: N; 17 | 18 | constructor(config: N) { 19 | if (config instanceof NucleoObject) { 20 | this.NucleoObject = config; 21 | } 22 | this.NucleoPrimitive = { Type: config.Type, serialize: config.serialize }; 23 | } 24 | 25 | getListChildrenType = ():string => { 26 | if (this.NucleoObject) { 27 | return 'NucleoObject'; 28 | } 29 | return 'NucleoPrimitive'; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/nucleoTypes/NucleoObject.ts: -------------------------------------------------------------------------------- 1 | import { NucleoObjectType } from './../_types/NucleoObjectType'; 2 | 3 | export default class NucleoObject implements NucleoObjectType { 4 | name: string; 5 | fields: { [key: string]: T }; 6 | 7 | constructor(config: NucleoObjectType) { 8 | this.name = config.name; 9 | this.fields = config.fields; 10 | } 11 | 12 | getFields = () => this.fields 13 | } 14 | -------------------------------------------------------------------------------- /src/nucleoTypes/primitive.ts: -------------------------------------------------------------------------------- 1 | import { NucleoPrimitiveType } from './../_types/NucleoPrimitiveType'; 2 | 3 | type UserFormatValidation = (arg: T) => boolean; 4 | 5 | export class NucleoCustomPrimitive { 6 | Type: string; 7 | userFormatValidation: UserFormatValidation; 8 | nativeType: string; 9 | 10 | serialize(value: T):boolean { 11 | if (typeof value !== 'boolean' && (typeof value !== this.nativeType || this.formatValidation(value))) { 12 | return false; 13 | } 14 | return true; 15 | } 16 | 17 | formatValidation(value: T):boolean { 18 | if (this.userFormatValidation) { 19 | return !this.userFormatValidation(value); 20 | } 21 | return false; 22 | } 23 | } 24 | 25 | export class NucleoStringAssertion extends NucleoCustomPrimitive { 26 | constructor(userFormatValidation:UserFormatValidation) { 27 | super(); 28 | this.Type = 'NucleoString'; 29 | this.nativeType = 'string'; 30 | this.userFormatValidation = userFormatValidation; 31 | } 32 | } 33 | 34 | export class NucleoNumberAssertion extends NucleoCustomPrimitive { 35 | constructor(userFormatValidation:UserFormatValidation) { 36 | super(); 37 | this.Type = 'NucleoNumber'; 38 | this.nativeType = 'number'; 39 | this.userFormatValidation = userFormatValidation; 40 | } 41 | } 42 | 43 | export const NucleoString: NucleoPrimitiveType = { 44 | Type: 'NucleoString', 45 | serialize: (value: string):boolean => { 46 | if (typeof value !== 'string') { 47 | return false; 48 | } 49 | 50 | return true; 51 | } 52 | }; 53 | 54 | export const NucleoNumber: NucleoPrimitiveType = { 55 | Type: 'NucleoNumber', 56 | serialize: (value: number):boolean => { 57 | if (typeof value !== 'number') { 58 | return false; 59 | } 60 | 61 | return true; 62 | } 63 | }; 64 | 65 | export const NucleoBoolean: NucleoPrimitiveType = { 66 | Type: 'NucleoBoolean', 67 | serialize: (value: boolean):boolean => { 68 | if (typeof value !== 'boolean') { 69 | return false; 70 | } 71 | 72 | return true; 73 | } 74 | }; 75 | -------------------------------------------------------------------------------- /src/save.ts: -------------------------------------------------------------------------------- 1 | import indexSearch from './indexSearch'; 2 | import NucleoObject from './nucleoTypes/NucleoObject'; 3 | import NucleoList from './nucleoTypes/NucleoList'; 4 | 5 | import { NucleoObjectType } from './_types/NucleoObjectType'; 6 | import { Listener } from './subscribe'; 7 | 8 | interface Save { 9 | contracts: any; 10 | store: any; 11 | listeners: Array; 12 | saveMethod: 'update'|'dispatch' 13 | } 14 | 15 | const saveMethodMapper = (store: any, contractName: string, listeners: Array) => ({ 16 | dispatch: (data: any) => { 17 | return store[contractName] = indexSearch({ 18 | contractName, 19 | storeData: data, 20 | data, 21 | listeners, 22 | newStoreData: {}, 23 | newListenersData: {} 24 | }); 25 | }, 26 | update: (data: any) => { 27 | return store[contractName] = indexSearch({ 28 | contractName, 29 | storeData: store[contractName], 30 | data, 31 | listeners, 32 | newStoreData: {}, 33 | newListenersData: {} 34 | }); 35 | } 36 | }); 37 | 38 | interface ContractVerification { 39 | contract: NucleoObjectType; 40 | data: any; 41 | saveMethod: 'update'|'dispatch'; 42 | __errors__: Array<{ contract: string; error: string; field?: string }>; 43 | } 44 | 45 | function contractVerification({ 46 | contract, 47 | data, 48 | saveMethod, 49 | __errors__, 50 | }:ContractVerification) { 51 | const { fields: contractFields } = contract; 52 | const dataKeys:Array = Object.keys(data); 53 | const contractName:string = contract.name; 54 | 55 | if (dataKeys.length !== Object.keys(contractFields).length && saveMethod === 'dispatch') { 56 | throw Error( 57 | `Fatal error: In dispatch, the dispatched data and the contract must match in every level. For changing just few values from ${contractName} contract, use update() method.` 58 | ); 59 | } 60 | 61 | for (let i = 0; dataKeys.length > i; i++) { 62 | const currentDataKey = data[dataKeys[i]]; 63 | if (contractFields[dataKeys[i]] instanceof NucleoObject) { 64 | contractVerification({ 65 | contract: contractFields[dataKeys[i]], 66 | data: currentDataKey, 67 | saveMethod, 68 | __errors__ 69 | }); 70 | continue; 71 | } 72 | 73 | if ((contractFields[dataKeys[i]] instanceof NucleoList) && Array.isArray(currentDataKey)) { 74 | const _listItemType = contractFields[dataKeys[i]].getListChildrenType(); 75 | const _NucleoItemType = contractFields[dataKeys[i]][_listItemType]; 76 | 77 | const dataTypeMapper = (): { [key: string]: () => void } => ({ 78 | NucleoPrimitive: () => { 79 | const { serialize, Type } = _NucleoItemType; 80 | 81 | for (let d = 0; d < currentDataKey.length; d++) { 82 | if (!serialize(currentDataKey[d])) { 83 | __errors__.push({ 84 | contract: contractName, 85 | error: `NucleoList expect to receive ${Type}, but got ${typeof currentDataKey[d]}` 86 | }); 87 | } 88 | } 89 | }, 90 | NucleoObject: () => { 91 | if (_NucleoItemType instanceof NucleoObject) { 92 | for (let d = 0; d < currentDataKey.length; d++) { 93 | if (Object.keys(currentDataKey[d]).length !== Object.keys(_NucleoItemType.fields).length) { 94 | __errors__.push({ 95 | contract: _NucleoItemType.name, 96 | error: 'You can not update a NucleoList of NucleoObject without its data according to contract in every level' 97 | }); 98 | 99 | continue; 100 | } 101 | 102 | contractVerification({ 103 | contract: _NucleoItemType, 104 | data: currentDataKey[d], 105 | saveMethod, 106 | __errors__ 107 | }); 108 | } 109 | } 110 | }, 111 | }); 112 | 113 | dataTypeMapper()[_listItemType](); 114 | continue; 115 | } else if ((contractFields[dataKeys[i]] instanceof NucleoList) && !Array.isArray(currentDataKey)) { 116 | __errors__.push({ 117 | contract: contractName, 118 | error: `NucleoList should receive data as list, but got ${typeof currentDataKey}` 119 | }); 120 | } 121 | 122 | if (!contractFields[dataKeys[i]]) { 123 | __errors__.push({ 124 | contract: contractName, 125 | error: `${dataKeys[i]} is not in ${contractName} contract and can not be saved in store.` 126 | }); 127 | } 128 | 129 | if (contractFields[dataKeys[i]] && contractFields[dataKeys[i]].serialize && !contractFields[dataKeys[i]].serialize(currentDataKey)) { 130 | __errors__.push({ 131 | contract: contractName, 132 | field: contractFields[dataKeys[i]], 133 | error: `${dataKeys[i]} does not match its rules according to ${contractName} contract` 134 | }); 135 | } 136 | } 137 | 138 | let operationStatus:''|'NOK'|'OK' = ''; 139 | if (__errors__.length) { 140 | operationStatus = 'NOK'; 141 | } else { 142 | operationStatus = 'OK'; 143 | } 144 | 145 | return (store:any, listeners:Array) => { 146 | if (!__errors__.length) { 147 | saveMethodMapper(store, contractName, listeners)[saveMethod](data); 148 | } 149 | 150 | return { 151 | status: operationStatus, 152 | errors: __errors__, 153 | data, 154 | }; 155 | }; 156 | } 157 | export default function save({ 158 | contracts, 159 | store, 160 | listeners, 161 | saveMethod 162 | }:Save) { 163 | return (contractName: string) => { 164 | if (!contracts[contractName]) { 165 | throw Error( 166 | `Fatal error: The provided contract named as "${contractName}" could not be found in store contracts` 167 | ); 168 | } 169 | 170 | if (saveMethod === 'update' && !store[contractName]) { 171 | throw Error( 172 | `Fatal error: you can not update an item in store if it is not created yet. 173 | First use dispatch to save it and then you can perform updates at ${contractName} contract.` 174 | ); 175 | } 176 | return (data: any) => { 177 | return contractVerification({ 178 | contract: { name: contractName, fields: contracts[contractName]}, 179 | data, 180 | saveMethod, 181 | __errors__: [] 182 | })(store, listeners); 183 | }; 184 | }; 185 | } 186 | -------------------------------------------------------------------------------- /src/store.ts: -------------------------------------------------------------------------------- 1 | import save from './save'; 2 | import NucleoObject from './nucleoTypes/NucleoObject'; 3 | import indexSearch from './indexSearch'; 4 | import subscribe, { listeners } from './subscribe'; 5 | import { Contracts } from './_types/Contracts'; 6 | import { Update } from './_types/Update'; 7 | 8 | export interface Store { 9 | dispatch: (contract: string) => (d: T) => Update; 10 | update: (contract: string) => (d: T) => Update; 11 | subscribe: (f: (arg: { contractName: string; data: T }) => void) => () => void; 12 | cloneState: (contract: string) => T; 13 | } 14 | 15 | function createStore(contracts: Contracts): Store { 16 | const __store__: any = {}; 17 | let __contracts__: any = {}; 18 | const contractsKeys: string[] = Object.keys(contracts); 19 | 20 | for (let c = 0; c < contractsKeys.length; c++) { 21 | const current = contracts[contractsKeys[c]]; 22 | if (!(current instanceof NucleoObject)) { 23 | throw Error( 24 | `Each contract must be instances of NucleoObject. Received ${JSON.stringify(current)}.\nTo understand more, check the documentation about creating a contract in Nucleo here: https://github.com/mtmr0x/nucleo` 25 | ); 26 | } 27 | 28 | const { fields = {} } = current; 29 | if (__contracts__[current.name]) { 30 | __contracts__ = {}; 31 | throw Error( 32 | `Two contracts can not have the same name. Received more than one ${current.name} contract` 33 | ); 34 | } 35 | __contracts__[current.name] = { ...fields }; 36 | } 37 | 38 | return { 39 | dispatch: save({ contracts: __contracts__, store: __store__, listeners, saveMethod: 'dispatch' }), 40 | update: save({ contracts: __contracts__, store: __store__, listeners, saveMethod: 'update' }), 41 | subscribe, 42 | cloneState: (contractName:string) => { 43 | if (!__contracts__[contractName]) { 44 | return undefined; 45 | } 46 | 47 | return indexSearch({ 48 | contractName, 49 | storeData: __store__[contractName], 50 | data: {}, 51 | listeners: undefined, 52 | newStoreData: {}, 53 | newListenersData: {} 54 | }); 55 | } 56 | }; 57 | } 58 | 59 | export { 60 | createStore 61 | }; 62 | -------------------------------------------------------------------------------- /src/subscribe.ts: -------------------------------------------------------------------------------- 1 | export type Listener = { 2 | index: number, 3 | listener: (arg: { contractName: string; data: any }) => void, 4 | on: boolean, 5 | } 6 | 7 | export const listeners: Listener[] = []; 8 | 9 | export default function subscribe(listener: (arg: { contractName: string; data: T }) => void):() => void { 10 | if (typeof listener !== 'function') { 11 | throw Error('Expected listener to be a function'); 12 | } 13 | 14 | const index:number = listeners.length; 15 | 16 | const newListener:Listener = { 17 | index, 18 | listener, 19 | on: true, 20 | }; 21 | 22 | listeners.push(newListener); 23 | 24 | return function unsubscribe() { 25 | for (let i = 0; i < listeners.length; i++) { 26 | if (listeners[i].index === index) { 27 | listeners[i].on = false; 28 | } 29 | } 30 | }; 31 | } 32 | 33 | -------------------------------------------------------------------------------- /tests/cloneState.spec.ts: -------------------------------------------------------------------------------- 1 | import { createStore } from '../src/store'; 2 | import { 3 | NucleoString, 4 | NucleoNumber, 5 | } from '../src/nucleoTypes/primitive' 6 | import NucleoObject from '../src/nucleoTypes/NucleoObject'; 7 | import { expect } from 'chai'; 8 | import 'mocha'; 9 | 10 | describe('Update forbidden attempts', () => { 11 | const completeNameType = new NucleoObject({ 12 | name: 'completeName', 13 | fields: { 14 | firstName: NucleoString, 15 | lastName: NucleoString 16 | } 17 | }); 18 | 19 | const userType = new NucleoObject({ 20 | name: 'user', 21 | fields: { 22 | name: completeNameType, 23 | age: NucleoNumber 24 | } 25 | }); 26 | const contracts = { user: userType }; 27 | const store = createStore(contracts); 28 | const { dispatch, update, cloneState } = store; 29 | 30 | it('should use update method and throw for this item in store be empty', () => { 31 | const d = () => update('user')({ name: { firstName: 'John' }}); 32 | 33 | expect(d).to.throw(); 34 | }); 35 | 36 | it('should dispatch values and then return error tring to update fields violating the contract', () => { 37 | dispatch('user')({ 38 | name: { firstName: 'John', lastName: 'Doe' }, 39 | age: 27 40 | }); 41 | 42 | const { errors, data } = update('user')({ name: { name: 'matheus' } }); 43 | const user = cloneState('user') as any; 44 | 45 | expect(errors.length).to.equal(1); 46 | expect(user.name.firstName).to.equal('John'); 47 | expect(user.name.lastName).to.equal('Doe'); 48 | expect(user.age).to.equal(27); 49 | }); 50 | }); 51 | 52 | describe('Clone method', () => { 53 | const completeNameType = new NucleoObject({ 54 | name: 'completeName', 55 | fields: { 56 | firstName: NucleoString, 57 | lastName: NucleoString 58 | } 59 | }); 60 | 61 | const userAddressType = new NucleoObject({ 62 | name: 'userAddressType', 63 | fields: { 64 | street: NucleoString, 65 | streetNumber: NucleoString, 66 | complement: NucleoString 67 | } 68 | }); 69 | 70 | const userLocationType = new NucleoObject({ 71 | name: 'userLocationType', 72 | fields: { 73 | city: NucleoString, 74 | address: userAddressType 75 | } 76 | }); 77 | 78 | const userType = new NucleoObject({ 79 | name: 'user', 80 | fields: { 81 | name: completeNameType, 82 | age: NucleoNumber, 83 | location: userLocationType 84 | } 85 | }); 86 | const contracts = { user: userType }; 87 | const store = createStore(contracts); 88 | const { dispatch, update, subscribe, cloneState } = store; 89 | 90 | it('should dispatch first data to store', () => { 91 | const d = dispatch('user')({ 92 | name: { firstName: 'John', lastName: 'Doe' }, 93 | location: { 94 | city: 'NY', 95 | address: { 96 | street: '9 avenue', 97 | streetNumber: '678', 98 | complement: '' 99 | } 100 | }, 101 | age: 27 102 | }); 103 | }); 104 | it('should update data, then clone state to get updated data', () => { 105 | update('user')({ age: 18 }); 106 | const clonedUser = cloneState('user') as any; 107 | 108 | expect(clonedUser.name.firstName).to.equal('John'); 109 | expect(clonedUser.name.lastName).to.equal('Doe'); 110 | expect(clonedUser.age).to.equal(18); 111 | }); 112 | it('should update data, clone and mutate first clone, then a new clone displays store is untouchable', () => { 113 | update('user')({ name: { firstName: 'Noah' } }); 114 | const clonedUser = cloneState('user') as any; 115 | clonedUser.name.firstName = 'Joseph'; 116 | 117 | const clonedUser2 = cloneState('user') as any; 118 | 119 | expect(clonedUser2.name.firstName).to.equal('Noah'); 120 | expect(clonedUser2.name.lastName).to.equal('Doe'); 121 | expect(clonedUser2.age).to.equal(18); 122 | }); 123 | it('should try to clone a state that does not exist and receiv a undefined as response', () => { 124 | const state = cloneState('nonExistingState'); 125 | 126 | expect(state).to.equal(undefined); 127 | }) 128 | }); 129 | 130 | -------------------------------------------------------------------------------- /tests/nucleoTypes/NucleoFunction.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createStore, 3 | NucleoString, 4 | NucleoObject, 5 | } from '../../src/index' 6 | 7 | import { expect } from 'chai'; 8 | import 'mocha'; 9 | 10 | describe('NucleoFunction', () => { 11 | function taxIdValidation(value:string) { 12 | return value.length === 11; 13 | } 14 | 15 | const userType = new NucleoObject({ 16 | name: 'user', 17 | fields: { 18 | name: NucleoString, 19 | } 20 | }); 21 | 22 | const contracts = { document: userType }; 23 | const store = createStore(contracts); 24 | const { dispatch, update, cloneState } = store; 25 | 26 | it('should try to violate contract with wrong type dispatching to contract', () => { 27 | const d = dispatch('user')({ 28 | name: 'John', 29 | taxIdValidation: '123456789090' 30 | }); 31 | 32 | expect(d.errors.length).to.equal(1); 33 | }); 34 | 35 | it('should dispatch and create this item in store', () => { 36 | dispatch('user')({ 37 | name: 'John', 38 | taxIdValidation: taxIdValidation 39 | }); 40 | const user = cloneState('user') as any; 41 | 42 | expect(user.name).to.equal('John'); 43 | expect(user.taxIdValidation).to.equal(taxIdValidation); 44 | }); 45 | 46 | it('should try to violate contract by trying to update it', () => { 47 | const u = update('user')({ taxIdValidation: '0123345678909' }); 48 | 49 | expect(u.errors.length).to.equal(1); 50 | }); 51 | 52 | it('should update data according to contract and save it in store', () => { 53 | function newTaxIdValidation(value:string) { 54 | return value.length === 14; 55 | } 56 | update('user')({ taxIdValidation: newTaxIdValidation }); 57 | const user = cloneState('user') as any; 58 | 59 | expect(user.taxIdValidation).to.equal(newTaxIdValidation); 60 | expect(user.name).to.equal('John'); 61 | }) 62 | }); 63 | -------------------------------------------------------------------------------- /tests/nucleoTypes/NucleoList.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | NucleoString, 3 | NucleoNumber, 4 | NucleoList, 5 | NucleoObject, 6 | createStore 7 | } from '../../src/index' 8 | import { expect } from 'chai'; 9 | import 'mocha'; 10 | 11 | describe('NucleoList', () => { 12 | const userAccountsType = new NucleoObject({ 13 | name: 'userAccountsType', 14 | fields: { 15 | accountType: NucleoString, 16 | accountNumber: NucleoNumber, 17 | } 18 | }); 19 | 20 | const personalInfoType = new NucleoObject({ 21 | name: 'personalInfo', 22 | fields: { 23 | firstName: NucleoString, 24 | lastName: NucleoString, 25 | items: new NucleoList(NucleoString), 26 | accounts: new NucleoList(userAccountsType) 27 | } 28 | }); 29 | 30 | const userType = new NucleoObject({ 31 | name: 'user', 32 | fields: { 33 | personalInfo: personalInfoType, 34 | age: NucleoNumber, 35 | } 36 | }); 37 | 38 | const contracts = { user: userType }; 39 | const store = createStore(contracts); 40 | const { dispatch, update, cloneState } = store; 41 | 42 | const taxIdValidator = (value:string) => value.length === 12; 43 | const newTaxIdValidator = (value:string) => value.length === 14; 44 | const accountNumberValidator = (value:number) => String(value).length <= 8; 45 | const ageValidator = (value:number) => value >= 18; 46 | 47 | it('should dispatch all data to store with empty array at accounts', () => { 48 | const data = { 49 | age: 27, 50 | validators: [taxIdValidator, ageValidator], 51 | personalInfo: { 52 | firstName: 'Joseph', 53 | lastName: 'Nor', 54 | items: ['a', 'b', 'c'], 55 | accounts: [] 56 | } 57 | } 58 | 59 | const d = dispatch('user')(data); 60 | const clonedData = cloneState('user') as any; 61 | const { personalInfo } = clonedData; 62 | expect(d.errors.length).to.equal(0); 63 | expect(personalInfo.accounts.length).to.equal(0); 64 | expect(Array.isArray(personalInfo.accounts)).to.equal(true); 65 | }); 66 | 67 | it('should dispatch all data to store', () => { 68 | const data = { 69 | age: 27, 70 | validators: [taxIdValidator, ageValidator], 71 | personalInfo: { 72 | firstName: 'Joseph', 73 | lastName: 'Nor', 74 | items: ['a', 'b', 'c'], 75 | accounts: [ 76 | { accountType: 'bank', accountNumber: 1233, taxIdValidator: taxIdValidator }, 77 | { accountType: 'bank', accountNumber: 9876, taxIdValidator: taxIdValidator } 78 | ] 79 | } 80 | } 81 | 82 | const d = dispatch('user')(data); 83 | expect(d.errors.length).to.equal(0); 84 | }); 85 | 86 | it('should try to update a NucleoList of primitive values succesfully', () => { 87 | update('user')({ personalInfo: { items: ['g', 'h', 'j', 'k'] } }); 88 | 89 | const user = cloneState('user') as any; 90 | const { personalInfo } = user; 91 | 92 | const { items } = personalInfo; 93 | 94 | expect(personalInfo.firstName).to.equal('Joseph'); 95 | expect(personalInfo.lastName).to.equal('Nor'); 96 | expect(items.length).to.equal(4); 97 | expect(personalInfo.accounts.length).to.equal(2); 98 | expect(items[0]).to.equal('g'); 99 | }); 100 | 101 | it('should try to violate a NucleoList of primitive values with update', () => { 102 | const u = update('user')({ personalInfo: { items: ['g', 'h', 'j', 1] } }); 103 | 104 | const user = cloneState('user') as any; 105 | const { personalInfo } = user; 106 | const { items } = personalInfo; 107 | 108 | expect(u.errors.length).to.equal(1); 109 | expect(personalInfo.firstName).to.equal('Joseph'); 110 | expect(personalInfo.lastName).to.equal('Nor'); 111 | expect(items.length).to.equal(4); 112 | expect(personalInfo.accounts.length).to.equal(2); 113 | expect(items[3]).to.equal('k'); 114 | }); 115 | 116 | it('should try to update a NucleoList of function values succesfully', () => { 117 | update('user')({ validators: [taxIdValidator, accountNumberValidator, ageValidator] }); 118 | 119 | const user = cloneState('user') as any; 120 | const { validators, personalInfo } = user; 121 | 122 | 123 | expect(personalInfo.accounts.length).to.equal(2); 124 | expect(validators[1]).to.equal(accountNumberValidator); 125 | expect(validators.length).to.equal(3); 126 | }); 127 | 128 | it('should try to violate a NucleoList of function values with update', () => { 129 | const u = update('user')({ validators: [taxIdValidator, 'string', ageValidator] }); 130 | 131 | const user = cloneState('user') as any; 132 | const { personalInfo, validators } = user; 133 | 134 | expect(u.errors.length).to.equal(1); 135 | expect(personalInfo.accounts.length).to.equal(2); 136 | expect(validators[1]).to.equal(accountNumberValidator); 137 | expect(validators.length).to.equal(3); 138 | }); 139 | 140 | it('should try to update a NucleoList of object values succesfully', () => { 141 | const obj = { 142 | personalInfo: { 143 | accounts: [ 144 | { accountType: 'service', accountNumber: 1111, taxIdValidator: newTaxIdValidator }, 145 | { accountType: 'service', accountNumber: 2222, taxIdValidator: newTaxIdValidator } 146 | ] 147 | } 148 | }; 149 | 150 | const u = update('user')(obj); 151 | const user = cloneState('user') as any; 152 | const { personalInfo } = user; 153 | 154 | expect(u.errors.length).to.equal(0); 155 | expect(personalInfo.accounts[0].accountType).to.equal('service'); 156 | expect(personalInfo.accounts[1].accountType).to.equal('service'); 157 | expect(personalInfo.accounts[0].accountNumber).to.equal(1111); 158 | expect(personalInfo.accounts[1].accountNumber).to.equal(2222); 159 | expect(personalInfo.accounts[0].taxIdValidator).to.equal(newTaxIdValidator); 160 | expect(personalInfo.accounts[1].taxIdValidator).to.equal(newTaxIdValidator); 161 | }); 162 | 163 | it('should try to violate a NucleoList of object values with update', () => { 164 | const obj = { 165 | personalInfo: { 166 | accounts: [ 167 | { accountType: 'service' }, 168 | { accountType: 'service', accountNumber: '2222' } 169 | ] 170 | } 171 | }; 172 | 173 | const u = update('user')(obj); 174 | 175 | const user = cloneState('user') as any; 176 | const { personalInfo } = user; 177 | 178 | expect(u.errors.length).to.equal(2); 179 | expect(personalInfo.accounts[0].accountType).to.equal('service'); 180 | expect(personalInfo.accounts[1].accountType).to.equal('service'); 181 | expect(personalInfo.accounts[0].accountNumber).to.equal(1111); 182 | expect(personalInfo.accounts[1].accountNumber).to.equal(2222); 183 | expect(personalInfo.accounts[0].taxIdValidator).to.equal(newTaxIdValidator); 184 | expect(personalInfo.accounts[1].taxIdValidator).to.equal(newTaxIdValidator); 185 | }); 186 | 187 | it('should be able to save empty list to NucleoList', () => { 188 | const obj = { 189 | personalInfo: { 190 | accounts: [] 191 | } 192 | }; 193 | 194 | const u = update('user')(obj); 195 | 196 | const user = cloneState('user') as any; 197 | const { personalInfo } = user; 198 | 199 | expect(u.errors.length).to.equal(0); 200 | expect(personalInfo.accounts.length).to.equal(0); 201 | }); 202 | }); 203 | 204 | -------------------------------------------------------------------------------- /tests/nucleoTypes/NucleoNumberAssertion.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createStore, 3 | NucleoNumberAssertion, 4 | NucleoString, 5 | NucleoObject, 6 | } from '../../src/index' 7 | 8 | import { expect } from 'chai'; 9 | import 'mocha'; 10 | 11 | describe('NucleoNumberAssertion', () => { 12 | function ageValidation(value:number) { 13 | return value < 100; 14 | } 15 | 16 | const userType = new NucleoObject({ 17 | name: 'user', 18 | fields: { 19 | name: NucleoString, 20 | age: new NucleoNumberAssertion(ageValidation) 21 | } 22 | }); 23 | 24 | const contracts = { document: userType }; 25 | const store = createStore(contracts); 26 | const { dispatch, update, cloneState } = store; 27 | 28 | it('should try to violate contract with wrong type dispatching to contract', () => { 29 | const d = dispatch('user')({ 30 | name: 'John', 31 | age: 110 32 | }); 33 | 34 | expect(d.errors.length).to.equal(1); 35 | }); 36 | 37 | it('should dispatch and create this item in store', () => { 38 | dispatch('user')({ 39 | name: 'John', 40 | age: 27 41 | }); 42 | const user = cloneState('user') as any; 43 | 44 | expect(user.name).to.equal('John'); 45 | expect(user.age).to.equal(27); 46 | }); 47 | 48 | it('should try to violate contract by trying to update it', () => { 49 | const u = update('user')({ age: 200 }); 50 | 51 | expect(u.errors.length).to.equal(1); 52 | }); 53 | 54 | it('should update data according to contract and save it in store', () => { 55 | update('user')({ age: 34 }); 56 | const user = cloneState('user') as any; 57 | 58 | expect(user.age).to.equal(34); 59 | expect(user.name).to.equal('John'); 60 | }) 61 | }); 62 | 63 | -------------------------------------------------------------------------------- /tests/nucleoTypes/NucleoStringAssertion.spec.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createStore, 3 | NucleoStringAssertion, 4 | NucleoString, 5 | NucleoObject, 6 | } from '../../src/index' 7 | 8 | import { expect } from 'chai'; 9 | import 'mocha'; 10 | 11 | describe('NucleoStringAssertion', () => { 12 | function taxIdValidation(value:string) { 13 | return value.length === 11; 14 | } 15 | 16 | const userType = new NucleoObject({ 17 | name: 'user', 18 | fields: { 19 | name: NucleoString, 20 | taxId: new NucleoStringAssertion(taxIdValidation) 21 | } 22 | }); 23 | 24 | const contracts = { document: userType }; 25 | const store = createStore(contracts); 26 | const { dispatch, update, cloneState } = store; 27 | 28 | it('should try to violate contract with wrong type dispatching to contract', () => { 29 | const d = dispatch('user')({ 30 | name: 'John', 31 | taxId: '123456789090' 32 | }); 33 | 34 | expect(d.errors.length).to.equal(1); 35 | }); 36 | 37 | it('should dispatch and create this item in store', () => { 38 | dispatch('user')({ 39 | name: 'John', 40 | taxId: '12345678909' 41 | }); 42 | const user = cloneState('user') as any; 43 | 44 | expect(user.name).to.equal('John'); 45 | expect(user.taxId).to.equal('12345678909'); 46 | }); 47 | 48 | it('should try to violate contract by trying to update it', () => { 49 | const u = update('user')({ taxId: '0123345678909' }); 50 | 51 | expect(u.errors.length).to.equal(1); 52 | }); 53 | 54 | it('should update data according to contract and save it in store', () => { 55 | update('user')({ taxId: '12334567890' }); 56 | const user = cloneState('user') as any; 57 | 58 | expect(user.taxId).to.equal('12334567890'); 59 | expect(user.name).to.equal('John'); 60 | }) 61 | }); 62 | 63 | -------------------------------------------------------------------------------- /tests/store.spec.ts: -------------------------------------------------------------------------------- 1 | import { createStore } from '../src/store'; 2 | import { 3 | NucleoString, 4 | NucleoNumber, 5 | NucleoBoolean 6 | } from '../src/nucleoTypes/primitive'; 7 | import NucleoObject from '../src/nucleoTypes/NucleoObject'; 8 | import NucleoList from '../src/nucleoTypes/NucleoList'; 9 | import { expect } from 'chai'; 10 | import 'mocha'; 11 | 12 | type UserTest = { 13 | name: { 14 | firstName: string, 15 | lastName: string, 16 | }, 17 | age: number, 18 | } 19 | 20 | const completeNameType = new NucleoObject({ 21 | name: 'completeName', 22 | fields: { 23 | firstName: NucleoString, 24 | lastName: NucleoString 25 | } 26 | }); 27 | 28 | const userTestType = new NucleoObject({ 29 | name: 'userTest', 30 | fields: { 31 | name: completeNameType, 32 | age: NucleoNumber 33 | } 34 | }); 35 | 36 | const productsTestType = new NucleoObject({ 37 | name: 'productTest', 38 | fields: { 39 | available: NucleoBoolean 40 | } 41 | }); 42 | 43 | const contracts = { 44 | userTest: userTestType, 45 | productsTest: productsTestType 46 | }; 47 | 48 | describe('createStore function errors', () => { 49 | const newStore = createStore(contracts); 50 | const { dispatch } = newStore; 51 | it('should create store properly', () => { 52 | expect(!!dispatch).to.equal(true); 53 | }); 54 | 55 | it('should throw at trying to dispatch an invalid contract', () => { 56 | const d = () => dispatch('user')({ name: 'Test' }); 57 | 58 | expect(d).to.throw(); 59 | }); 60 | 61 | it('should throw at saving data to userTest not according to its contract fields', () => { 62 | const d = () => dispatch('userTest')({ firstName: 'Test' }); 63 | 64 | expect(d).to.throw(); 65 | }); 66 | 67 | it('should throw at saving data to userTest not according to its contract types', () => { 68 | const d = () => dispatch('userTest')({ age: '23' }); 69 | expect(d).to.throw(); 70 | }); 71 | 72 | it('should have a NucleoList of NucleoString and throw for dispatching wrong value type', () => { 73 | const productsType = new NucleoObject({ 74 | name: 'products', 75 | fields: { 76 | sku: new NucleoList(NucleoString) 77 | } 78 | }); 79 | const contracts = { products: productsType }; 80 | const store = createStore(contracts); 81 | const { dispatch } = store; 82 | const { errors } = dispatch('products')({ sku: ['a', 1] }); 83 | 84 | expect(errors.length).to.equal(1); 85 | }); 86 | 87 | it('should have a NucleoList and dispatch it as a non-list and show receive and error', () => { 88 | const productsType = new NucleoObject({ 89 | name: 'products', 90 | fields: { 91 | sku: new NucleoList(NucleoString) 92 | } 93 | }); 94 | const contracts = { products: productsType }; 95 | const store = createStore(contracts); 96 | const { dispatch } = store; 97 | const { errors } = dispatch('products')({ sku: 'a' }); 98 | 99 | expect(errors.length).to.equal(1); 100 | }); 101 | 102 | it('should have a NucleoList of NucleoObject and fails at dispatch it because the contract is violated', () => { 103 | const productType = new NucleoObject({ 104 | name: 'product', 105 | fields: { 106 | title: NucleoString, 107 | sku: NucleoString 108 | } 109 | }); 110 | 111 | const productsType = new NucleoObject({ 112 | name: 'products', 113 | fields: { 114 | items: new NucleoList(productType) 115 | } 116 | }); 117 | 118 | const contracts = { products: productsType }; 119 | const store = createStore(contracts); 120 | const { dispatch } = store; 121 | const items = [ 122 | { title: 'USB adapter', sku: '1324' }, 123 | { title: 'USB Type-C adapter', sku: 4321 } 124 | ]; 125 | 126 | const { errors } = dispatch('products')({ items }); 127 | expect(errors.length).to.equal(1); 128 | }); 129 | }); 130 | 131 | describe('createStore function dispatch flow', () => { 132 | const newStore = createStore(contracts); 133 | const { dispatch, cloneState, subscribe } = newStore; 134 | it('should subscribe and listeners be properly executed', () => { 135 | type listenerObjectArgumentType = { 136 | contractName: string 137 | }; 138 | 139 | const value:Array = []; 140 | 141 | function myListener(obj:listenerObjectArgumentType) { 142 | return value.push(obj); 143 | } 144 | 145 | subscribe(myListener); 146 | 147 | dispatch('userTest')({ name: { firstName: 'John', lastName: 'Doe' }, age: 27 }); 148 | dispatch('userTest')({ name: { firstName: 'John', lastName: 'Doe' }, age: 28 }); 149 | 150 | expect(value.length).to.equal(2); 151 | }); 152 | 153 | it('should dispatch values to store', () => { 154 | dispatch('userTest')({ name: { firstName: 'John', lastName: 'Doe' }, age: 29 }); 155 | 156 | const userTest = cloneState('userTest') as any; 157 | expect(userTest.name.firstName).to.equal('John'); 158 | }); 159 | 160 | it('should have a NucleoList of NucleoString and dispatch it properly', () => { 161 | const productsType = new NucleoObject({ 162 | name: 'products', 163 | fields: { 164 | sku: new NucleoList(NucleoString) 165 | } 166 | }); 167 | const contracts = { products: productsType }; 168 | const store = createStore(contracts); 169 | const { dispatch, cloneState } = store; 170 | 171 | dispatch('products')({ sku: ['a', 'b'] }); 172 | const products = cloneState('products') as any; 173 | 174 | expect(JSON.stringify(products.sku)).to.equal(JSON.stringify(['a', 'b'])); 175 | }); 176 | 177 | it('should have a NucleoList of NucleoObject and dispatch it properly', () => { 178 | const productType = new NucleoObject({ 179 | name: 'product', 180 | fields: { 181 | title: NucleoString, 182 | sku: NucleoString 183 | } 184 | }); 185 | 186 | const productsType = new NucleoObject({ 187 | name: 'products', 188 | fields: { 189 | items: new NucleoList(productType) 190 | } 191 | }); 192 | 193 | const contracts = { products: productsType }; 194 | const store = createStore(contracts); 195 | const { dispatch, cloneState } = store; 196 | const items = [ 197 | { title: 'USB adapter', sku: '1324' }, 198 | { title: 'USB Type-C adapter', sku: '4321' } 199 | ]; 200 | 201 | dispatch('products')({ items }); 202 | const products = cloneState('products'); 203 | 204 | expect(JSON.stringify(products)).to.equal(JSON.stringify({ items })); 205 | }); 206 | }); 207 | 208 | -------------------------------------------------------------------------------- /tests/subscribe.spec.ts: -------------------------------------------------------------------------------- 1 | import subscribe, { listeners } from './../src/subscribe'; 2 | 3 | import { expect } from 'chai'; 4 | import 'mocha'; 5 | 6 | describe('Subscription functionality', () => { 7 | function listenA() { 8 | return false; 9 | } 10 | 11 | function listenB() { 12 | return false; 13 | } 14 | it('Should add functions to list of listeners', () => { 15 | const length = listeners.length + 1; 16 | subscribe(listenA); 17 | 18 | expect(listeners).to.have.length(length); 19 | }); 20 | it('Should add listenB to list of listeners', () => { 21 | const length = listeners.length + 1; 22 | subscribe(listenB); 23 | expect(listeners).to.have.length(length); 24 | }); 25 | it('Should add listenA to list of listeners and unsubscribe it', () => { 26 | const length = listeners.length + 1; 27 | const unsubscribe = subscribe(listenA); 28 | unsubscribe(); 29 | expect(listeners).to.have.length(length); 30 | expect(listeners[length - 1].on).to.equal(false); 31 | }); 32 | }); 33 | 34 | -------------------------------------------------------------------------------- /tests/update.spec.ts: -------------------------------------------------------------------------------- 1 | import { createStore } from '../src/store'; 2 | import { 3 | NucleoString, 4 | NucleoNumber, 5 | NucleoBoolean 6 | } from '../src/nucleoTypes/primitive' 7 | import NucleoObject from '../src/nucleoTypes/NucleoObject'; 8 | import { expect } from 'chai'; 9 | import 'mocha'; 10 | 11 | describe('Update forbidden attempts', () => { 12 | const completeNameType = new NucleoObject({ 13 | name: 'completeName', 14 | fields: { 15 | firstName: NucleoString, 16 | lastName: NucleoString 17 | } 18 | }); 19 | 20 | const userType = new NucleoObject({ 21 | name: 'user', 22 | fields: { 23 | name: completeNameType, 24 | age: NucleoNumber 25 | } 26 | }); 27 | const contracts = { user: userType }; 28 | const store = createStore(contracts); 29 | const { dispatch, update, cloneState } = store; 30 | 31 | it('should use update method and throw for this item in store be empty', () => { 32 | const d = () => update('user')({ name: { firstName: 'John' }}); 33 | 34 | expect(d).to.throw(); 35 | }); 36 | 37 | it('should dispatch values and then return error tring to update fields violating the contract', () => { 38 | const d = dispatch('user')({ 39 | name: { firstName: 'John', lastName: 'Doe' }, 40 | age: 27 41 | }); 42 | 43 | const { errors, data } = update('user')({ name: { name: 'matheus' } }); 44 | expect(errors.length).to.equal(1); 45 | const user = cloneState('user') as any; 46 | expect(user.name.firstName).to.equal('John'); 47 | expect(user.name.lastName).to.equal('Doe'); 48 | expect(user.age).to.equal(27); 49 | }); 50 | }); 51 | 52 | describe('Update method', () => { 53 | const completeNameType = new NucleoObject({ 54 | name: 'completeName', 55 | fields: { 56 | firstName: NucleoString, 57 | lastName: NucleoString 58 | } 59 | }); 60 | 61 | const userAddressType = new NucleoObject({ 62 | name: 'userAddressType', 63 | fields: { 64 | street: NucleoString, 65 | streetNumber: NucleoString, 66 | complement: NucleoString 67 | } 68 | }); 69 | 70 | const userLocationType = new NucleoObject({ 71 | name: 'userLocationType', 72 | fields: { 73 | city: NucleoString, 74 | address: userAddressType 75 | } 76 | }); 77 | 78 | const userType = new NucleoObject({ 79 | name: 'user', 80 | fields: { 81 | name: completeNameType, 82 | age: NucleoNumber, 83 | location: userLocationType, 84 | verified: NucleoBoolean 85 | } 86 | }); 87 | const contracts = { user: userType }; 88 | const store = createStore(contracts); 89 | const { dispatch, update, cloneState, subscribe } = store; 90 | 91 | it('should dispatch only one property in deeper levels and just this property should be updated in store', () => { 92 | const d = dispatch('user')({ 93 | name: { firstName: 'John', lastName: 'Doe' }, 94 | location: { 95 | city: 'NY', 96 | address: { 97 | street: '9 avenue', 98 | streetNumber: '678', 99 | complement: '' 100 | } 101 | }, 102 | age: 27, 103 | verified: true 104 | }); 105 | 106 | update('user')({ name: { firstName: 'Joseph' } }); 107 | const user = cloneState('user') as any; 108 | expect(user.name.firstName).to.equal('Joseph'); 109 | expect(user.name.lastName).to.equal('Doe'); 110 | expect(user.age).to.equal(27); 111 | }); 112 | it('should dispatch only one property in first level and just this property should be updated in store', () => { 113 | update('user')({ age: 18 }); 114 | const user = cloneState('user') as any; 115 | 116 | expect(user.name.firstName).to.equal('Joseph'); 117 | expect(user.name.lastName).to.equal('Doe'); 118 | expect(user.age).to.equal(18); 119 | }); 120 | 121 | it('should dispatch a value to a deeper level and save it properly', () => { 122 | update('user')({ location: { address: { complement: 'apartment 2' } } }); 123 | const user = cloneState('user') as any; 124 | 125 | expect(user.name.firstName).to.equal('Joseph'); 126 | expect(user.name.lastName).to.equal('Doe'); 127 | expect(user.age).to.equal(18); 128 | expect(user.location.city).to.equal('NY'); 129 | expect(user.location.address.street).to.equal('9 avenue'); 130 | expect(user.location.address.streetNumber).to.equal('678'); 131 | expect(user.location.address.complement).to.equal('apartment 2'); 132 | }); 133 | 134 | it('should update value and listener should receive data properly', () => { 135 | let receivedData:any; 136 | function listener(data: any) { 137 | receivedData = data; 138 | } 139 | subscribe(listener); 140 | update('user')({ location: { address: { complement: 'apartment 3' } } }); 141 | const user = cloneState('user') as any; 142 | 143 | expect(receivedData.data.name.firstName).to.equal('Joseph'); 144 | expect(receivedData.data.name.lastName).to.equal('Doe'); 145 | expect(receivedData.data.age).to.equal(18); 146 | expect(receivedData.data.location.city).to.equal('NY'); 147 | expect(receivedData.data.location.address.street).to.equal('9 avenue'); 148 | expect(receivedData.data.location.address.streetNumber).to.equal('678'); 149 | expect(receivedData.data.location.address.complement).to.equal('apartment 3'); 150 | 151 | expect(user.name.firstName).to.equal('Joseph'); 152 | expect(user.name.lastName).to.equal('Doe'); 153 | expect(user.age).to.equal(18); 154 | expect(user.location.city).to.equal('NY'); 155 | expect(user.location.address.street).to.equal('9 avenue'); 156 | expect(user.location.address.streetNumber).to.equal('678'); 157 | expect(user.location.address.complement).to.equal('apartment 3'); 158 | }); 159 | 160 | it('should update false javascript values and save it properly', () => { 161 | const { errors, data } = update('user')({ 162 | age: 0, 163 | name: { 164 | lastName: '' 165 | }, 166 | verified: false 167 | }); 168 | 169 | const user = cloneState('user') as any; 170 | 171 | expect(user.name.lastName).to.equal(''); 172 | expect(user.verified).to.equal(false); 173 | expect(user.age).to.equal(0); 174 | 175 | }); 176 | }); 177 | 178 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2016", 5 | "noImplicitAny": true, 6 | "strictNullChecks": true, 7 | "moduleResolution": "node", 8 | "resolveJsonModule": true, 9 | "isolatedModules": true, 10 | "sourceMap": true, 11 | "outDir": "dist", 12 | "baseUrl": "src", 13 | "declaration": true, 14 | "paths": { 15 | "*": [ 16 | "node_modules/*" 17 | ] 18 | } 19 | }, 20 | "include": [ 21 | "src/**/*" 22 | ] 23 | } 24 | 25 | --------------------------------------------------------------------------------