├── .eslintignore ├── .eslintrc ├── .github └── workflows │ ├── pull_request.yml │ └── release.yml ├── .gitignore ├── .nycrc.json ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── README.md ├── package-lock.json ├── package.json ├── src ├── deepClone │ ├── deepClone.test.ts │ └── deepClone.ts ├── filter │ ├── filter.test.ts │ └── filter.ts ├── filterDuplicates │ ├── filterDuplicates.test.ts │ └── filterDuplicates.ts ├── index.ts ├── is │ ├── is.test.ts │ └── is.ts ├── isArray │ ├── isArray.test.ts │ └── isArray.ts ├── isBoolean │ ├── isBoolean.test.ts │ └── isBoolean.ts ├── isEmpty │ ├── isEmpty.test.ts │ └── isEmpty.ts ├── isFalse │ ├── isFalse.test.ts │ └── isFalse.ts ├── isNull │ ├── isNull.test.ts │ └── isNull.ts ├── isNumber │ ├── isNumber.test.ts │ └── isNumber.ts ├── isObject │ ├── isObject.test.ts │ └── isObject.ts ├── isString │ ├── isString.test.ts │ └── isString.ts ├── isTrue │ ├── isTrue.test.ts │ └── isTrue.ts ├── isTruthy │ ├── isTruthy.test.ts │ └── isTruthy.ts ├── isUndefined │ ├── isUndefined.test.ts │ └── isUndefined.ts ├── isZero │ ├── isZero.test.ts │ └── isZero.ts ├── logical │ ├── logical.test.ts │ └── logical.ts ├── pick │ ├── pick.test.ts │ └── pick.ts ├── sorting │ ├── sorting.test.ts │ └── sorting.ts ├── types.ts └── uniqueArray │ ├── uniqueArray.test.ts │ └── uniqueArray.ts ├── tsconfig-cjs.json └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "plugins": ["@typescript-eslint", "prettier"], 5 | "extends": [ 6 | "eslint:recommended", 7 | "plugin:@typescript-eslint/eslint-recommended", 8 | "plugin:@typescript-eslint/recommended", 9 | "prettier" 10 | ], 11 | "rules": { 12 | "no-console": "error", 13 | "prettier/prettier": "off", 14 | "@typescript-eslint/no-unused-vars": ["off", { "argsIgnorePattern": "^_" }], 15 | "@typescript-eslint/ban-types": "off", 16 | "@typescript-eslint/no-explicit-any": "off" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/workflows/pull_request.yml: -------------------------------------------------------------------------------- 1 | name: run lint and tests 2 | 3 | on: 4 | pull_request: 5 | types: [opened, synchronize] 6 | 7 | jobs: 8 | tests: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | 13 | - uses: actions/setup-node@v1 14 | with: 15 | node-version: 10 16 | 17 | - run: npm install 18 | 19 | - run: npm run lint 20 | 21 | - run: npm test 22 | 23 | - run: npm run build 24 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Update version & publish to npm 2 | 3 | on: 4 | push: 5 | branches: 6 | - 'main' 7 | 8 | jobs: 9 | publish: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | 14 | - name: install node 15 | uses: actions/setup-node@v1 16 | with: 17 | node-version: 10 18 | 19 | - run: npm install 20 | 21 | - name: run test 22 | run: npm test 23 | 24 | - run: npm run coverage 25 | 26 | - name: output test coverage 27 | run: npm run coverage:output-report 28 | 29 | - uses: actions/upload-artifact@v2 30 | with: 31 | name: coverage-report 32 | path: coverage-report.txt 33 | 34 | - name: build package 35 | run: npm run build 36 | 37 | - name: bump version and create tag 38 | uses: 'phips28/gh-action-bump-version@master' 39 | env: 40 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 41 | with: 42 | minor-wording: 'feat,feature' 43 | 44 | - name: publish to npm 45 | uses: JS-DevTools/npm-publish@v1 46 | with: 47 | token: ${{ secrets.NPM_TOKEN }} 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .nyc_output 3 | lib 4 | coverage-report.txt -------------------------------------------------------------------------------- /.nycrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@istanbuljs/nyc-config-typescript", 3 | "all": true, 4 | "check-coverage": true, 5 | "include": ["src/**/*.ts"], 6 | "exclude": ["src/index.ts", "src/**/*.test.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "singleQuote": true, 4 | "tabWidth": 3, 5 | "useTabs": true, 6 | "printWidth": 120, 7 | "arrowParens": "always", 8 | "trailingComma": "all" 9 | } 10 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.codeActionsOnSave": { 3 | "source.fixAll.eslint": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | A collection of a few small lightweight typesafe utilities. 2 | 3 | ## Motivation 4 | 5 | Sometimes you will encounter situations were the types will **not** match what you expect from a function. This means you need to explicitly specify a type by yourself to gain the full power of TypeScript. 6 | 7 | In this collection you will find some useful functions that are fully typed. 8 | 9 | ## Install 10 | 11 | ``` 12 | $ npm install --save-dev typesafe-utils 13 | ``` 14 | 15 | ## Overview 16 | - [filter functions](#filter functions) 17 | - is 18 | - [is](#is) 19 | - [isNot](#isNot) 20 | - [isProperty](#isProperty) 21 | - [isPropertyNot](#isPropertyNot) 22 | - isTruthy 23 | - [isTruthy](#isTruthy) 24 | - [isFalsy](#isFalsy) 25 | - [isPropertyTruthy](#isPropertyTruthy) 26 | - [isPropertyFalsy](#isPropertyFalsy) 27 | - [arePropertiesTruthy](#arePropertiesTruthy) 28 | - [arePropertiesFalsy](#arePropertiesFalsy) 29 | - isUndefined 30 | - [isUndefined](#isUndefined) 31 | - [isNotUndefined](#isNotUndefined) 32 | - [isPropertyUndefined](#isPropertyUndefined) 33 | - [isPropertyNotUndefined](#isPropertyNotUndefined) 34 | - [arePropertiesUndefined](#arePropertiesUndefined) 35 | - [arePropertiesNotUndefined](#arePropertiesNotUndefined) 36 | - isNull 37 | - [isNull](#isNull) 38 | - [isNotNull](#isNotNull) 39 | - [isPropertyNull](#isPropertyNull) 40 | - [isPropertyNotNull](#isPropertyNotNull) 41 | - [arePropertiesNull](#arePropertiesNull) 42 | - [arePropertiesNotNull](#arePropertiesNotNull) 43 | - boolean 44 | - [isBoolean](#isBoolean) 45 | - isTrue 46 | - [isTrue](#isTrue) 47 | - [isNotTrue](#isNotTrue)* 48 | - [isPropertyTrue](#isPropertyTrue) 49 | - [isPropertyNotTrue](#isPropertyNotTrue)* 50 | - [arePropertiesTrue](#arePropertiesTrue) 51 | - [arePropertiesNotTrue](#arePropertiesNotTrue)* 52 | - isFalse 53 | - [isFalse](#isFalse) 54 | - [isNotFalse](#isNotFalse)* 55 | - [isPropertyFalse](#isPropertyFalse) 56 | - [isPropertyNotFalse](#isPropertyNotFalse)* 57 | - [arePropertiesFalse](#arePropertiesFalse) 58 | - [arePropertiesNotFalse](#arePropertiesNotFalse)* 59 | - number 60 | - [isNumber](#isNumber) 61 | - isZero 62 | - [isZero](#isZero) 63 | - [isNotZero](#isNotZero)* 64 | - [isPropertyZero](#isPropertyZero) 65 | - [isPropertyNotZero](#isPropertyNotZero)* 66 | - [arePropertiesZero](#arePropertiesZero) 67 | - [arePropertiesNotZero](#arePropertiesNotZero)* 68 | - string 69 | - [isString](#isString) 70 | - isEmpty 71 | - [isEmpty](#isEmpty) 72 | - [isNotEmpty](#isNotEmpty) 73 | - [isPropertyEmpty](#isPropertyEmpty) 74 | - [isPropertyNotEmpty](#isPropertyNotEmpty) 75 | - [arePropertiesEmpty](#arePropertiesEmpty) 76 | - [arePropertiesNotEmpty](#arePropertiesNotEmpty) 77 | - array 78 | - [isArray](#isArray) 79 | - [isArrayNotEmpty](#isArrayNotEmpty) 80 | - [isArrayEmpty](#isArrayEmpty) 81 | - object 82 | - [isObject](#isObject) 83 | - [isPrimitiveObject](#isPrimitiveObject) 84 | - duplicates 85 | - [filterDuplicates](#filterDuplicates) 86 | - [filterDuplicatesByKey](#filterDuplicatesByKey) 87 | - logical operators 88 | - [and](#and)* 89 | - [or](#or)* 90 | - [not](#not)* 91 | - typeguards 92 | - [createFilter](#TypeGuardInverted)* 93 | 94 | - [sorting functions](#sorting functions) 95 | - number 96 | - [sortNumberASC](#sortNumberASC) 97 | - [sortNumberDESC](#sortNumberDESC) 98 | - [sortNumberPropertyASC](#sortNumberPropertyASC) 99 | - [sortNumberPropertyDESC](#sortNumberPropertyDESC) 100 | - string 101 | - [sortStringASC](#sortStringASC) 102 | - [sortStringDESC](#sortStringDESC) 103 | - [sortStringPropertyASC](#sortStringPropertyASC) 104 | - [sortStringPropertyDESC](#sortStringPropertyDESC) 105 | - date 106 | - [sortDateASC](#sortDateASC) 107 | - [sortDateDESC](#sortDateDESC) 108 | - [sortDatePropertyASC](#sortDatePropertyASC) 109 | - [sortDatePropertyDESC](#sortDatePropertyDESC) 110 | 111 | - [mapping functions](#mapping functions) 112 | - [pick](#pick) 113 | 114 | - [other](#other) 115 | - [deepClone](#deepClone) 116 | - [uniqueArray](#uniqueArray) 117 | 118 | - [types](#types) 119 | - [Truthy](#truthy) 120 | - [Falsy](#falsy) 121 | - [TypeGuard](#typeguard) 122 | - [TypeGuardWithReturnType](#typeguardwithreturntype) 123 | - [TypeGuardInverted](#typeguardinverted) 124 | - [TypeGuardInvertedWithReturnType](#typeguardinvertedwithreturntype) 125 | 126 | | * not automatically 100% typesafe. It's better than nothing but to be 100% typesafe you need to pass generics yourself. 127 | 128 | ## filter functions 129 | 130 | A bunch of utilities that return true or false. Useful for array filter functions. 131 | 132 | > Motivation: When you filter an Array, the return type is **not** always what you expect. Typescript will tell you the result of a filter function is the exact type you pass to the filter function. But that is **not** always true. If you filter out falsy values, the return type should should **not** contain. 133 | 134 | ```TypeScript 135 | // BASIC example -------------------------------------------------------------- 136 | 137 | const result = [true, false].filter(bool => !!bool) 138 | // => result: boolean[] => [true] 139 | 140 | 141 | import { isTruthy } from 'typesafe-utils' 142 | const typesafeResult = [true, false].filter(isTruthy) 143 | // => typesafeResult: true[] => [true] 144 | 145 | 146 | // ADVANCED example ----------------------------------------------------------- 147 | 148 | const result = ['text', null, 'another text', undefined].filter(value => value !== '') 149 | // => result: (string | null | undefined)[] => ['text', 'another text'] 150 | 151 | 152 | import { isNotEmpty } from 'typesafe-utils' 153 | const typesafeResult = ['text', null, 'another text', undefined].filter(isNotEmpty) 154 | // => typesafeResult: string[] => ['text', 'another text'] 155 | ``` 156 | 157 | 158 | 159 | ### is 160 | 161 | returns `true` iff value is equals to the property you pass to the function 162 | 163 | #### Usage 164 | ```TypeScript 165 | import { is } from 'typesafe-utils' 166 | 167 | const result = [1, 15, 10, 43].filter(is(10)) 168 | // result: number[] => [10] 169 | ``` 170 | 171 | ### isNot 172 | 173 | returns `true` iff value is **not** equal to the property you pass to the function 174 | 175 | #### Usage 176 | ```TypeScript 177 | import { isNot } from 'typesafe-utils' 178 | 179 | const result = ['text', 'forbidden', 'blabla'].filter(isNot('forbidden')) 180 | // result: string[] => ['text', 'blabla'] 181 | ``` 182 | 183 | ### isProperty 184 | 185 | returns `true` iff the attribute of the object equals the property you pass to the function 186 | 187 | #### Usage 188 | ```TypeScript 189 | import { isProperty } from 'typesafe-utils' 190 | 191 | type Product = { 192 | id: number 193 | } 194 | 195 | const items: Product[] = [ 196 | { id: 1 }, 197 | { id: 3 } 198 | ] 199 | const result = items.filter(isProperty('id', 3)) 200 | // result: Product[] => [{ id: 3 }] 201 | ``` 202 | 203 | ### isPropertyNot 204 | 205 | returns `true` iff the attribute of the object is **not** equal to the property you pass to the function 206 | 207 | #### Usage 208 | ```TypeScript 209 | import { isPropertyNot } from 'typesafe-utils' 210 | 211 | type Product = { 212 | id: number 213 | } 214 | 215 | const items: Product[] = [ 216 | { id: 156 }, 217 | { id: 123 } 218 | ] 219 | const result = items.filter(isPropertyNot('id', 123)) 220 | // result: Product[] => [{ id: 156 }] 221 | ``` 222 | 223 | 224 | 225 | ### isTruthy 226 | 227 | returns `true` iff value is **not** `false | '' | 0 | null | undefined` 228 | 229 | #### Usage 230 | ```TypeScript 231 | import { isTruthy } from 'typesafe-utils' 232 | 233 | const result = [true, false, undefined, null].filter(isTruthy) 234 | // result: true[] => [true] 235 | ``` 236 | 237 | ### isFalsy 238 | 239 | returns `true` iff value is `false | '' | 0 | null | undefined` 240 | 241 | #### Usage 242 | ```TypeScript 243 | import { isFalsy } from 'typesafe-utils' 244 | 245 | const result = [true, false, 'text', 123, null].filter(isFalsy) 246 | // result: (false | null)[] => [false, null] 247 | ``` 248 | 249 | ### isPropertyTruthy 250 | 251 | returns `true` iff the attribute of the object is truthy 252 | 253 | #### Usage 254 | ```TypeScript 255 | import { isPropertyTruthy } from 'typesafe-utils' 256 | 257 | type Product = { 258 | id: number 259 | } 260 | 261 | const items: Product[] = [ 262 | { id: 1 }, 263 | { id: null }, 264 | { id: undefined } 265 | ] 266 | const result = items.filter(isPropertyTruthy('id')) 267 | // result: Product[] => [{ id: 1 }] 268 | ``` 269 | 270 | ### isPropertyFalsy 271 | 272 | returns `true` iff the attribute of the object is falsy 273 | 274 | #### Usage 275 | ```TypeScript 276 | import { isPropertyFalsy } from 'typesafe-utils' 277 | 278 | type Product = { 279 | id: number 280 | } 281 | 282 | const items: Product[] = [ 283 | { id: 5 }, 284 | { id: null } 285 | ] 286 | const result = items.filter(isPropertyFalsy('id')) 287 | // result: Product[] => [{ id: null }] 288 | ``` 289 | 290 | ### arePropertiesTruthy 291 | 292 | returns `true` iff all attributes of the object are truthy 293 | 294 | #### Usage 295 | ```TypeScript 296 | import { arePropertiesTruthy } from 'typesafe-utils' 297 | 298 | type Product = { 299 | id: number 300 | name: string 301 | } 302 | 303 | const items: Product[] = [ ... ] 304 | 305 | const result = items.filter(arePropertiesTruthy('id', 'name')) 306 | ``` 307 | 308 | ### arePropertiesFalsy 309 | 310 | returns `true` iff all attributes of the object are falsy 311 | 312 | #### Usage 313 | ```TypeScript 314 | import { arePropertiesFalsy } from 'typesafe-utils' 315 | 316 | type Product = { 317 | id: number 318 | name: string 319 | } 320 | 321 | const items: Product[] = [ ... ] 322 | 323 | const result = items.filter(arePropertiesFalsy('id', 'name')) 324 | ``` 325 | 326 | 327 | 328 | ### isUndefined 329 | 330 | returns `true` iff value is `undefined` 331 | 332 | #### Usage 333 | ```TypeScript 334 | import { isUndefined } from 'typesafe-utils' 335 | 336 | const result = [undefined, null, true].filter(isUndefined) 337 | // result: undefined[] => [undefined] 338 | ``` 339 | 340 | ### isNotUndefined 341 | 342 | returns `true` iff value is **not** `undefined` 343 | 344 | #### Usage 345 | ```TypeScript 346 | import { isNotUndefined } from 'typesafe-utils' 347 | 348 | const result = [null, undefined].filter(isNotUndefined) 349 | // result: null[] => [null] 350 | ``` 351 | 352 | ### isPropertyUndefined 353 | 354 | returns `true` iff the attribute of the object is `undefined` 355 | 356 | #### Usage 357 | ```TypeScript 358 | import { isPropertyUndefined } from 'typesafe-utils' 359 | 360 | type Product = { 361 | id: number | undefined 362 | } 363 | 364 | const items: Product[] = [ 365 | { id: 1 }, 366 | { id: undefined } 367 | ] 368 | const result = items.filter(isPropertyUndefined('id')) 369 | // result: Product[] => [{ id: undefined }] 370 | ``` 371 | 372 | ### isPropertyNotUndefined 373 | 374 | returns `true` iff the attribute of the object is **not** `undefined` 375 | 376 | #### Usage 377 | ```TypeScript 378 | import { isPropertyNotUndefined } from 'typesafe-utils' 379 | 380 | type Product = { 381 | id: number 382 | } 383 | 384 | const items: Product[] = [ 385 | { id: 5 }, 386 | { id: undefined } 387 | ] 388 | const result = items.filter(isPropertyNotUndefined('id')) 389 | // result: Product[] => [{ id: 5 }] 390 | ``` 391 | 392 | ### arePropertiesUndefined 393 | 394 | returns `true` iff all attributes of the object are `undefined` 395 | 396 | #### Usage 397 | ```TypeScript 398 | import { arePropertiesUndefined } from 'typesafe-utils' 399 | 400 | type Product = { 401 | id: number 402 | name: string 403 | } 404 | 405 | const items: Product[] = [ ... ] 406 | 407 | const result = items.filter(arePropertiesUndefined('id', 'name')) 408 | ``` 409 | 410 | ### arePropertiesNotUndefined 411 | 412 | returns `true` iff all attributes of the object are **not** `undefined` 413 | 414 | #### Usage 415 | ```TypeScript 416 | import { arePropertiesNotUndefined } from 'typesafe-utils' 417 | 418 | type Product = { 419 | id: number 420 | name: string 421 | } 422 | 423 | const items: Product[] = [ ... ] 424 | 425 | const result = items.filter(arePropertiesNotUndefined('id', 'name')) 426 | ``` 427 | 428 | 429 | 430 | ### isNull 431 | 432 | returns `true` iff value is `null` 433 | 434 | #### Usage 435 | ```TypeScript 436 | import { isNull } from 'typesafe-utils' 437 | 438 | const result = [null, undefined].filter(isNull) 439 | // result: null[] => [null] 440 | ``` 441 | 442 | ### isNotNull 443 | 444 | returns `true` iff value is **not** `null` 445 | 446 | #### Usage 447 | ```TypeScript 448 | import { isNotNull } from 'typesafe-utils' 449 | 450 | const result = [false, null].filter(isNotNull) 451 | // result: boolean[] => [false] 452 | ``` 453 | 454 | ### isPropertyNull 455 | 456 | returns `true` iff the attribute of the object is `null` 457 | 458 | #### Usage 459 | ```TypeScript 460 | import { isPropertyNull } from 'typesafe-utils' 461 | 462 | type Product = { 463 | id: number | null 464 | } 465 | 466 | const items: Product[] = [ 467 | { id: 0 }, 468 | { id: null } 469 | ] 470 | const result = items.filter(isPropertyNull('id')) 471 | // result: Product[] => [{ id: null }] 472 | ``` 473 | 474 | ### isPropertyNotNull 475 | 476 | returns `true` iff the attribute of the object is **not** `null` 477 | 478 | #### Usage 479 | ```TypeScript 480 | import { isPropertyNotNull } from 'typesafe-utils' 481 | 482 | type Product = { 483 | id: number 484 | } 485 | 486 | const items: Product[] = [ 487 | { id: 5 }, 488 | { id: null } 489 | ] 490 | const result = items.filter(isPropertyNotNull('id')) 491 | // result: Product[] => [{ id: 5 }] 492 | ``` 493 | 494 | ### arePropertiesNull 495 | 496 | returns `true` iff all attributes of the object are `null` 497 | 498 | #### Usage 499 | ```TypeScript 500 | import { arePropertiesNull } from 'typesafe-utils' 501 | 502 | type Product = { 503 | id: number 504 | name: string 505 | } 506 | 507 | const items: Product[] = [ ... ] 508 | 509 | const result = items.filter(arePropertiesNull('id', 'name')) 510 | ``` 511 | 512 | ### arePropertiesNotNull 513 | 514 | returns `true` iff all attributes of the object are **not** `null` 515 | 516 | #### Usage 517 | ```TypeScript 518 | import { arePropertiesNotNull } from 'typesafe-utils' 519 | 520 | type Product = { 521 | id: number 522 | name: string 523 | } 524 | 525 | const items: Product[] = [ ... ] 526 | 527 | const result = items.filter(arePropertiesNotNull('id', 'name')) 528 | ``` 529 | 530 | 531 | 532 | ### isBoolean 533 | 534 | returns `true` iff value is of type `boolean` 535 | 536 | #### Usage 537 | ```TypeScript 538 | import { isBoolean } from 'typesafe-utils' 539 | 540 | const result = [true, 'some text', 1, false].filter(isBoolean) 541 | // result: boolean[] => [true, false] 542 | ``` 543 | 544 | ### isTrue 545 | 546 | returns `true` iff value is `true` 547 | 548 | #### Usage 549 | ```TypeScript 550 | import { isTrue } from 'typesafe-utils' 551 | 552 | const result = [true, 'some text', 1].filter(isTrue) 553 | // result: true[] => [true] 554 | ``` 555 | 556 | ### isNotTrue 557 | 558 | returns `true` iff value is **not** `true` 559 | 560 | > Note: it is currently **not** possible to make this function fully typesafe.\ 561 | > `[true, 123].filter(isNotTrue)` will have the type `(false | number)[]` 562 | 563 | #### Usage 564 | ```TypeScript 565 | import { isNotTrue } from 'typesafe-utils' 566 | 567 | const result = [true, false].filter(isNotTrue) 568 | // result: false[] => [false] 569 | ``` 570 | 571 | ### isPropertyTrue 572 | 573 | returns `true` iff the attribute of the object is `true` 574 | 575 | #### Usage 576 | ```TypeScript 577 | import { isPropertyTrue } from 'typesafe-utils' 578 | 579 | type Product = { 580 | available: boolean | null 581 | } 582 | 583 | const items: Product[] = [ 584 | { available: true }, 585 | { available: null } 586 | ] 587 | const result = items.filter(isPropertyTrue('available')) 588 | // result: Product[] => [{ available: true }] 589 | ``` 590 | 591 | ### isPropertyNotTrue 592 | 593 | returns `true` iff the attribute of the object is **not** `true` 594 | 595 | #### Usage 596 | ```TypeScript 597 | import { isPropertyNotTrue } from 'typesafe-utils' 598 | 599 | type Product = { 600 | id: number 601 | } 602 | 603 | const items: Product[] = [ 604 | { available: true }, 605 | { available: false } 606 | ] 607 | const result = items.filter(isPropertyNotTrue('available')) 608 | // result: Product[] => [{ available: false }] 609 | ``` 610 | 611 | ### arePropertiesTrue 612 | 613 | returns `true` iff all attributes of the object are `true` 614 | 615 | #### Usage 616 | ```TypeScript 617 | import { arePropertiesTrue } from 'typesafe-utils' 618 | 619 | type Product = { 620 | count: number 621 | available: string 622 | } 623 | 624 | const items: Product[] = [ ... ] 625 | 626 | const result = items.filter(arePropertiesTrue('count', 'available')) 627 | ``` 628 | 629 | ### arePropertiesNotTrue 630 | 631 | returns `true` iff all attributes of the object are **not** `true` 632 | 633 | #### Usage 634 | ```TypeScript 635 | import { arePropertiesNotTrue } from 'typesafe-utils' 636 | 637 | type Product = { 638 | count: number 639 | available: string 640 | } 641 | 642 | const items: Product[] = [ ... ] 643 | 644 | const result = items.filter(arePropertiesNotTrue('count', 'available')) 645 | ``` 646 | 647 | 648 | 649 | ### isFalse 650 | 651 | returns `true` iff value is `false` 652 | 653 | #### Usage 654 | ```TypeScript 655 | import { isFalse } from 'typesafe-utils' 656 | 657 | const result = [0, false, undefined].filter(isFalse) 658 | // result: false[] => [false] 659 | ``` 660 | 661 | ### isNotFalse 662 | 663 | returns `true` iff value is **not** `false` 664 | 665 | > Note: it is currently **not** possible to make this function fully typesafe.\ 666 | > `[false, 123].filter(isNotFalse)` will have the type `(true | number)[]` 667 | 668 | #### Usage 669 | ```TypeScript 670 | import { isNotFalse } from 'typesafe-utils' 671 | 672 | const result = [false, null].filter(isNotFalse) 673 | // result: null[] => [null] 674 | ``` 675 | 676 | ### isPropertyFalse 677 | 678 | returns `true` iff the attribute of the object is `false` 679 | 680 | #### Usage 681 | ```TypeScript 682 | import { isPropertyFalse } from 'typesafe-utils' 683 | 684 | type Product = { 685 | available: boolean | null 686 | } 687 | 688 | const items: Product[] = [ 689 | { available: false }, 690 | { available: true }, 691 | { available: null } 692 | ] 693 | const result = items.filter(isPropertyFalse('available')) 694 | // result: Product[] => [{ available: false }] 695 | ``` 696 | 697 | ### isPropertyNotFalse 698 | 699 | returns `true` iff the attribute of the object is **not** `false` 700 | 701 | #### Usage 702 | ```TypeScript 703 | import { isPropertyNotFalse } from 'typesafe-utils' 704 | 705 | type Product = { 706 | id: number 707 | } 708 | 709 | const items: Product[] = [ 710 | { available: true }, 711 | { available: false } 712 | ] 713 | const result = items.filter(isPropertyNotFalse('available')) 714 | // result: Product[] => [{ available: true }] 715 | ``` 716 | 717 | ### arePropertiesFalse 718 | 719 | returns `true` iff all attributes of the object are `false` 720 | 721 | #### Usage 722 | ```TypeScript 723 | import { arePropertiesFalse } from 'typesafe-utils' 724 | 725 | type Product = { 726 | count: number 727 | available: string 728 | } 729 | 730 | const items: Product[] = [ ... ] 731 | 732 | const result = items.filter(arePropertiesFalse('count', 'available')) 733 | ``` 734 | 735 | ### arePropertiesNotFalse 736 | 737 | returns `true` iff all attributes of the object are **not** `false` 738 | 739 | #### Usage 740 | ```TypeScript 741 | import { arePropertiesNotFalse } from 'typesafe-utils' 742 | 743 | type Product = { 744 | count: number 745 | available: string 746 | } 747 | 748 | const items: Product[] = [ ... ] 749 | 750 | const result = items.filter(arePropertiesNotFalse('count', 'available')) 751 | ``` 752 | 753 | 754 | 755 | ### isNumber 756 | 757 | returns `true` iff value is of type `number` 758 | 759 | #### Usage 760 | ```TypeScript 761 | import { isNumber } from 'typesafe-utils' 762 | 763 | const result = [0, false, undefined, 5].filter(isNumber) 764 | // result: number[] => [0, 5] 765 | ``` 766 | 767 | ### isZero 768 | 769 | returns `true` iff value is `0` 770 | 771 | #### Usage 772 | ```TypeScript 773 | import { isZero } from 'typesafe-utils' 774 | 775 | const result = [0, false, undefined, 5].filter(isZero) 776 | // result: 0[] => [0] 777 | ``` 778 | 779 | ### isNotZero 780 | 781 | returns `true` iff value is **not** `0` 782 | 783 | > Note: it is currently **not** possible to make this function fully typesafe.\ 784 | > `[0, null].filter(isNotTrue)` will have the type `(number | null)[]` 785 | 786 | #### Usage 787 | ```TypeScript 788 | import { isNotZero } from 'typesafe-utils' 789 | 790 | const result = [0, 123].filter(isNotZero) 791 | // result: number[] => [123] 792 | ``` 793 | 794 | ### isPropertyZero 795 | 796 | returns `true` iff the attribute of the object is `0` 797 | 798 | #### Usage 799 | ```TypeScript 800 | import { isPropertyZero } from 'typesafe-utils' 801 | 802 | type Product = { 803 | price: number 804 | } 805 | 806 | const items: Product[] = [ 807 | { price: 0 }, 808 | { price: 4 }, 809 | { price: 15 } 810 | ] 811 | const result = items.filter(isPropertyZero('price')) 812 | // result: Product[] => [{ price: 0 }] 813 | ``` 814 | 815 | ### isPropertyNotZero 816 | 817 | returns `true` iff the attribute of the object is **not** `0` 818 | 819 | #### Usage 820 | ```TypeScript 821 | import { isPropertyNotZero } from 'typesafe-utils' 822 | 823 | type Product = { 824 | price: number 825 | } 826 | 827 | const items: Product[] = [ 828 | { price: 0 }, 829 | { price: 12 } 830 | ] 831 | const result = items.filter(isPropertyNotZero('price')) 832 | // result: Product[] => [{ price: 23 }] 833 | ``` 834 | 835 | ### arePropertiesZero 836 | 837 | returns `true` iff all attributes of the object are `0` 838 | 839 | #### Usage 840 | ```TypeScript 841 | import { arePropertiesZero } from 'typesafe-utils' 842 | 843 | type Product = { 844 | count: number 845 | speed: string 846 | } 847 | 848 | const items: Product[] = [ ... ] 849 | 850 | const result = items.filter(arePropertiesZero('count', 'speed')) 851 | ``` 852 | 853 | ### arePropertiesNotZero 854 | 855 | returns `true` iff all attributes of the object are **not** `0` 856 | 857 | #### Usage 858 | ```TypeScript 859 | import { arePropertiesNotZero } from 'typesafe-utils' 860 | 861 | type Product = { 862 | count: number 863 | speed: string 864 | } 865 | 866 | const items: Product[] = [ ... ] 867 | 868 | const result = items.filter(arePropertiesNotZero('count', 'speed')) 869 | ``` 870 | 871 | 872 | 873 | ### isString 874 | 875 | returns `true` iff value is of type `string` 876 | 877 | #### Usage 878 | ```TypeScript 879 | import { isString } from 'typesafe-utils' 880 | 881 | const result = ['', false, null, 'text'].filter(isString) 882 | // result: string[] => ['', 'text] 883 | ``` 884 | 885 | ### isEmpty 886 | 887 | returns `true` iff value is `''` 888 | 889 | #### Usage 890 | ```TypeScript 891 | import { isEmpty } from 'typesafe-utils' 892 | 893 | const result = ['', false, null, 'text'].filter(isEmpty) 894 | // result: ''[] => [''] 895 | ``` 896 | 897 | ### isNotEmpty 898 | 899 | returns `true` iff value is **not** `''` 900 | 901 | #### Usage 902 | ```TypeScript 903 | import { isNotEmpty } from 'typesafe-utils' 904 | 905 | const result = ['', 5].filter(isNotEmpty) 906 | // result: number[] => [5] 907 | ``` 908 | 909 | ### isPropertyEmpty 910 | 911 | returns `true` iff the attribute of the object is `''` 912 | 913 | #### Usage 914 | ```TypeScript 915 | import { isPropertyEmpty } from 'typesafe-utils' 916 | 917 | type Product = { 918 | label: string 919 | } 920 | 921 | const items: Product[] = [ 922 | { label: '' }, 923 | { label: 'label-1' } 924 | ] 925 | const result = items.filter(isPropertyEmpty('label')) 926 | // result: Product[] => [{ label: '' }] 927 | ``` 928 | 929 | ### isPropertyNotEmpty 930 | 931 | returns `true` iff the attribute of the object is **not** `''` 932 | 933 | #### Usage 934 | ```TypeScript 935 | import { isPropertyNotEmpty } from 'typesafe-utils' 936 | 937 | type Product = { 938 | label: string 939 | } 940 | 941 | const items: Product[] = [ 942 | { label: 'label-123' }, 943 | { label: '' } 944 | ] 945 | const result = items.filter(isPropertyNotEmpty('label')) 946 | // result: Product[] => [{ label: 'label-123' }] 947 | ``` 948 | 949 | 950 | ### arePropertiesEmpty 951 | 952 | returns `true` iff all attributes of the object are `''` 953 | 954 | #### Usage 955 | ```TypeScript 956 | import { arePropertiesEmpty } from 'typesafe-utils' 957 | 958 | type Person = { 959 | name: number 960 | firstName: string 961 | } 962 | 963 | const items: Person[] = [ ... ] 964 | 965 | const result = items.filter(arePropertiesEmpty('name', 'firstName')) 966 | ``` 967 | 968 | ### arePropertiesNotEmpty 969 | 970 | returns `true` iff all attributes of the object are **not** `''` 971 | 972 | #### Usage 973 | ```TypeScript 974 | import { arePropertiesNotEmpty } from 'typesafe-utils' 975 | 976 | type Person = { 977 | name: number 978 | firstName: string 979 | } 980 | 981 | const items: Person[] = [ ... ] 982 | 983 | const result = items.filter(arePropertiesNotEmpty('name', 'firstName')) 984 | ``` 985 | 986 | 987 | 988 | ### isArray 989 | 990 | returns `true` iff value is of type `Array` 991 | 992 | #### Usage 993 | ```TypeScript 994 | import { isArray } from 'typesafe-utils' 995 | 996 | const result = [[], null, 123, [0, 1]].filter(isArray) 997 | // result: number[][] => [[], [0, 1]] 998 | ``` 999 | 1000 | ### isArrayNotEmpty 1001 | 1002 | returns `true` iff an array contains at least one item 1003 | 1004 | #### Usage 1005 | ```TypeScript 1006 | import { isArrayNotEmpty } from 'typesafe-utils' 1007 | 1008 | const nonEmptyArray = ['hi'] 1009 | 1010 | if (!!nonEmptyArray.length) { 1011 | nonEmptyArray[0].toUpperCase() // ERROR: Object is possibly 'undefined' 1012 | } 1013 | 1014 | if (isArrayNotEmpty(nonEmptyArray)) { 1015 | // TypeScript will know that the array contains at least 1 item, so it will not complain 1016 | nonEmptyArray[0].toUpperCase() 1017 | } 1018 | ``` 1019 | 1020 | ### isArrayEmpty 1021 | 1022 | returns `true` iff an array contains no items 1023 | 1024 | #### Usage 1025 | ```TypeScript 1026 | import { isArrayEmpty } from 'typesafe-utils' 1027 | 1028 | const emptyArray: string[] = [] 1029 | if (isArrayEmpty(emptyArray)) { 1030 | // emptyArray does not contain any items 1031 | } 1032 | ``` 1033 | 1034 | 1035 | 1036 | ### isObject 1037 | 1038 | returns `true` iff value is of type `object` 1039 | 1040 | #### Usage 1041 | ```TypeScript 1042 | import { isObject } from 'typesafe-utils' 1043 | 1044 | type SomeType = { 1045 | prop?: number 1046 | } 1047 | 1048 | const now = new Date() 1049 | const result = [{}, now, null, { prop: 123 }].filter(isObject) 1050 | // result: (SomeType | Date)[] => [{}, now, { prop: 123 }] 1051 | ``` 1052 | 1053 | ### isPrimitiveObject 1054 | 1055 | returns `true` iff value is of the primitive type `object` and not derived from a `class` like `Date` or else. 1056 | 1057 | #### Usage 1058 | ```TypeScript 1059 | import { isPrimitiveObject } from 'typesafe-utils' 1060 | 1061 | type SomeType = { 1062 | prop?: number 1063 | } 1064 | 1065 | const now = new Date() 1066 | const result = [{}, now, null, { prop: 123 }].filter(isPrimitiveObject) 1067 | // result: SomeType[] => [{}, { prop: 123 }] 1068 | ``` 1069 | 1070 | 1071 | 1072 | 1073 | ### filterDuplicates 1074 | 1075 | Removes duplicates from an array. Only the first occurrence of an item will be kept. 1076 | 1077 | #### Usage 1078 | 1079 | ```TypeScript 1080 | import { filterDuplicates } from 'typesafe-utils' 1081 | 1082 | const items = [1, 2, 3, 5, 8, 1] 1083 | const filteredItems = items.filter(filterDuplicates) 1084 | // filteredItems: number[] => [1, 2, 3, 5, 8] 1085 | ``` 1086 | 1087 | ### filterDuplicatesByKey 1088 | 1089 | Removes duplicates from an array by its key. Only the first occurrence of an item will be kept. 1090 | 1091 | > Motivation: It is less error-prone if you can only pass the keys an object provides to a filter function. With this function you get full types support. 1092 | 1093 | #### Usage 1094 | 1095 | ```TypeScript 1096 | import { filterDuplicatesByKey } from 'typesafe-utils' 1097 | 1098 | type Product = { 1099 | id: number 1100 | name: string 1101 | } 1102 | 1103 | const items: Product[] = [ 1104 | { id: 1, name: 'name-1' }, 1105 | { id: 2, name: 'name-2' }, 1106 | { id: 3, name: 'name-1' }, 1107 | { id: 4, name: 'name-2' } 1108 | ] 1109 | const filteredItems = items.filter(filterDuplicatesByKey('name')) 1110 | // filteredItems: Product[] => [{ id: 1, name: 'name-1' }, { id: 2, name: 'name-2' }] 1111 | 1112 | 1113 | const willThrowAnError = items.filter(filterDuplicatesByKey('price')) 1114 | // throws: Argument of type '"price"' is **not** assignable to parameter of type '"id" | "name"' 1115 | ``` 1116 | 1117 | ### and 1118 | 1119 | Combines (`&&`) multiple filter functions. 1120 | 1121 | #### Usage 1122 | 1123 | ```TypeScript 1124 | import { and, isString } from 'typesafe-utils' 1125 | 1126 | const items = [null, "test", undefined, "hi"] 1127 | const isShortString = and(isString, (value) => value.length < 3) 1128 | const filteredItems = items.filter(isShortString) 1129 | // filteredItems: string[] => ['hi'] 1130 | ``` 1131 | 1132 | ### or 1133 | 1134 | Combines (`||`) multiple filter functions. 1135 | 1136 | #### Usage 1137 | 1138 | ```TypeScript 1139 | import { or } from 'typesafe-utils' 1140 | 1141 | const items = [10, 2, 3, 5, 8, 1] 1142 | const isFiveOrTen = or((value) => value === 5, (value) => value === 10) 1143 | const filteredItems = items.filter(isFiveOrTen) 1144 | // filteredItems: number[] => [10, 5] 1145 | ``` 1146 | 1147 | 1148 | ### not 1149 | 1150 | Inverts a filter function. 1151 | 1152 | #### Usage 1153 | 1154 | ```TypeScript 1155 | import { not, filterDuplicates } from 'typesafe-utils' 1156 | 1157 | type Product = { 1158 | id: number 1159 | name: string 1160 | } 1161 | 1162 | const items: Product[] = [ 1163 | { id: 1, name: 'name-1' }, 1164 | { id: 2, name: 'name-2' }, 1165 | { id: 3, name: 'name-1' }, 1166 | { id: 4, name: 'name-2' } 1167 | ] 1168 | const filteredItems = items.filter(not(filterDuplicatesByKey('name'))) 1169 | // filteredItems: Product[] => [{ id: 3, name: 'name-1' }, { id: 4, name: 'name-2' }] 1170 | 1171 | 1172 | // The `not` function takes two optional type arguments. 1173 | // The first is the type you expect the filter function to return. 1174 | // The second is the Type of the Array you want to filter. 1175 | // e.g. 1176 | const notNull = [1, 5, null].filter(not((value => value === null))) 1177 | // notNull: number[] => [1, 5] 1178 | 1179 | ``` 1180 | 1181 | 1182 | 1183 | ### createFilter 1184 | 1185 | Creates a typeguard filter. 1186 | 1187 | #### Usage 1188 | 1189 | ```TypeScript 1190 | import { createFilter } from 'typesafe-utils' 1191 | 1192 | interface Item { 1193 | id: number 1194 | } 1195 | 1196 | interface ItemWithName extends Item { 1197 | name: string 1198 | } 1199 | 1200 | const items: (Item | ItemWithName | undefined)[] = [ 1201 | { id: 1 }, 1202 | undefined 1203 | { id: 3, name: 'name-1' }, 1204 | { id: 4 } 1205 | ] 1206 | 1207 | const filterHasName = createFilter((item) => !!item?.name) 1208 | const filteredItems = items.filter(filterHasName) 1209 | // filteredItems: ItemWithName[] => [{ id: 3, name: 'name-1' }] 1210 | ``` 1211 | 1212 | 1213 | 1214 | 1215 | ## sorting functions 1216 | 1217 | ### sortNumberASC 1218 | 1219 | sort `number` in **ASC** order 1220 | 1221 | #### Usage 1222 | ```TypeScript 1223 | import { sortNumberASC } from 'typesafe-utils' 1224 | 1225 | const items = [4, -1, 3, 0] 1226 | const result = items.sort(sortNumberASC) 1227 | // result: number[] => [-1, 0, 3, 4] 1228 | ``` 1229 | 1230 | ### sortNumberDESC 1231 | 1232 | sort `number` in **DESC** order 1233 | 1234 | #### Usage 1235 | ```TypeScript 1236 | import { sortNumberDESC } from 'typesafe-utils' 1237 | 1238 | const items = [2, -5, 0] 1239 | const result = items.sort(sortNumberDESC) 1240 | // result: number[] => [2, 0, -5] 1241 | ``` 1242 | 1243 | ### sortNumberPropertyASC 1244 | 1245 | sort property of type `number` in **ASC** order 1246 | 1247 | #### Usage 1248 | ```TypeScript 1249 | import { sortNumberPropertyASC } from 'typesafe-utils' 1250 | 1251 | type Car { 1252 | speed: number 1253 | } 1254 | 1255 | const items: Car[] = [ 1256 | { speed: 113 }, 1257 | { speed: 100 }, 1258 | { speed: 95 } 1259 | ] 1260 | const result = items.sort(sortNumberPropertyASC('speed')) 1261 | // result: Car[] => [{ speed: 95 }, { speed: 100 }, { speed: 113 }} 1262 | ``` 1263 | 1264 | ### sortNumberPropertyDESC 1265 | 1266 | sort property of type `number` in **DESC** order 1267 | 1268 | #### Usage 1269 | ```TypeScript 1270 | import { sortNumberPropertyDESC } from 'typesafe-utils' 1271 | 1272 | type Car { 1273 | speed: number 1274 | } 1275 | 1276 | const items: Car[] = [ 1277 | { speed: 70 } 1278 | { speed: 87 } 1279 | ] 1280 | const result = items.sort(sortNumberPropertyDESC('speed')) 1281 | // result: Car[] => [{ speed: 87 }, { speed: 70 }] 1282 | ``` 1283 | 1284 | ### sortStringASC 1285 | 1286 | sort `string` in **ASC** order 1287 | 1288 | #### Usage 1289 | ```TypeScript 1290 | import { sortStringASC } from 'typesafe-utils' 1291 | 1292 | const items = ['Hi', 'apples'] 1293 | const result = items.sort(sortStringASC) 1294 | // result: string[] => ['apples', Hi'] 1295 | ``` 1296 | 1297 | ### sortStringDESC 1298 | 1299 | sort `string` in **DESC** order 1300 | 1301 | #### Usage 1302 | ```TypeScript 1303 | import { sortStringDESC } from 'typesafe-utils' 1304 | 1305 | const items = ['apple', 'banana'] 1306 | const result = items.sort(sortStringDESC) 1307 | // result: string[] => ['banana', 'apple'] 1308 | ``` 1309 | 1310 | ### sortStringPropertyASC 1311 | 1312 | sort property of type `string` in **ASC** order 1313 | 1314 | #### Usage 1315 | ```TypeScript 1316 | import { sortStringPropertyASC } from 'typesafe-utils' 1317 | 1318 | type Car { 1319 | color: string 1320 | } 1321 | 1322 | const items: Car[] = [ 1323 | { color: 'green' }, 1324 | { color: 'brown' } 1325 | ] 1326 | 1327 | const result = items.sort(sortStringPropertyASC('color')) 1328 | // result: Car[] => [{ color: 'brown' }, { color: 'green' }] 1329 | ``` 1330 | 1331 | ### sortStringPropertyDESC 1332 | 1333 | sort property of type `string` in **DESC** order 1334 | 1335 | #### Usage 1336 | ```TypeScript 1337 | import { sortStringPropertyDESC } from 'typesafe-utils' 1338 | 1339 | type Car { 1340 | color: string 1341 | } 1342 | 1343 | const items: Car[] = [ 1344 | { color: 'red' }, 1345 | { color: 'blue' } 1346 | ] 1347 | const result = items.sort(sortStringPropertyDESC('color')) 1348 | // result: Car[] => [{ color: 'red' }, { color: 'blue' }] 1349 | ``` 1350 | 1351 | ### sortDateASC 1352 | 1353 | sort `Date` in **ASC** order 1354 | 1355 | #### Usage 1356 | ```TypeScript 1357 | import { sortDateASC } from 'typesafe-utils' 1358 | 1359 | const today = new Date() 1360 | const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000) 1361 | 1362 | const items = [tomorrow, today] 1363 | const result = items.sort(sortDateASC) 1364 | // result: Date[] => [today, tomorrow] 1365 | ``` 1366 | 1367 | ### sortDateDESC 1368 | 1369 | sort `Date` in **DESC** order 1370 | 1371 | #### Usage 1372 | ```TypeScript 1373 | import { sortDateDESC } from 'typesafe-utils' 1374 | 1375 | const today = new Date() 1376 | const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000) 1377 | 1378 | const items = [today, tomorrow] 1379 | const result = items.sort(sortDateDESC) 1380 | // result: Date[] => [tomorrow, today] 1381 | ``` 1382 | 1383 | ### sortDatePropertyASC 1384 | 1385 | sort property of type `Date` in **ASC** order 1386 | 1387 | #### Usage 1388 | ```TypeScript 1389 | import { sortDatePropertyASC } from 'typesafe-utils' 1390 | 1391 | type Smartphone = { 1392 | releaseDate: Date 1393 | } 1394 | 1395 | const today = new Date() 1396 | const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000) 1397 | 1398 | const items: Smartphone[] = [ 1399 | { releaseDate: tomorrow }, 1400 | { releaseDate: today } 1401 | ] 1402 | 1403 | const items: Smartphone[] = [] 1404 | const result = items.sort(sortDatePropertyASC('releaseDate')) 1405 | // result: Smartphone[]=> [{ releaseDate: today }, { releaseDate: tomorrow }] 1406 | ``` 1407 | 1408 | ### sortDatePropertyDESC 1409 | 1410 | sort property of type `Date` in **DESC** order 1411 | 1412 | #### Usage 1413 | ```TypeScript 1414 | import { sortDatePropertyDESC } from 'typesafe-utils' 1415 | 1416 | type Smartphone = { 1417 | releaseDate: Date 1418 | } 1419 | 1420 | const today = new Date() 1421 | const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000) 1422 | 1423 | const items: Smartphone[] = [ 1424 | { releaseDate: today }, 1425 | { releaseDate: tomorrow } 1426 | ] 1427 | const result = items.sort(sortDatePropertyDESC('releaseDate')) 1428 | // result: Smartphone[] => [{ releaseDate: tomorrow }, { releaseDate: today }] 1429 | ``` 1430 | 1431 | 1432 | 1433 | 1434 | ## mapping functions 1435 | 1436 | ### pick 1437 | 1438 | Picks an attribute from an Object. 1439 | 1440 | #### Usage 1441 | 1442 | ```TypeScript 1443 | import { pick } from 'typesafe-utils' 1444 | 1445 | interface Item { 1446 | id: number 1447 | name: string 1448 | price: number 1449 | } 1450 | 1451 | const items: Item[] = [ 1452 | { id: 1, name: '', price: 123 }, 1453 | { id: 3, name: '', price: 0 }, 1454 | { id: 7, name: '', price: 12 }, 1455 | ] 1456 | 1457 | const ids = items.map(pick('id')) 1458 | // ids: number[] => [ 1, 3, 7 ] 1459 | ``` 1460 | 1461 | 1462 | 1463 | 1464 | ## other 1465 | 1466 | ### deepClone 1467 | 1468 | Creates a deep copy of an object containing primitive values. 1469 | 1470 | > Motivation: I have seen a variety of clone-functions that return any. There you would need to always specify the type by ourself. Using this function, you will get a correctly typed object back. 1471 | 1472 | #### Usage 1473 | 1474 | ```TypeScript 1475 | import { deepClone } from 'typesafe-utils' 1476 | 1477 | const objectToClone: MyTypedObject = { ... } 1478 | const clonedObject = deepClone(objectToClone) 1479 | // => clonedObject: MyTypedObject => { ... } 1480 | ``` 1481 | 1482 | 1483 | ### uniqueArray 1484 | 1485 | Removes duplicates from an array. 1486 | 1487 | #### Usage 1488 | 1489 | ```TypeScript 1490 | import { uniqueArray } from 'typesafe-utils' 1491 | 1492 | const unique = uniqueArray('John', 'Max', 'John') 1493 | // => unique: string[] => ['John', 'Max'] 1494 | ``` 1495 | 1496 | 1497 | 1498 | 1499 | ## Types 1500 | 1501 | ### Truthy 1502 | 1503 | Contains all `Truthy` values (everything excluding [Falsy](#falsy) values) 1504 | 1505 | #### Usage 1506 | 1507 | ```TypeScript 1508 | import { Truthy } from 'typesafe-utils' 1509 | 1510 | export const isTruthy = (value: T): value is Truthy => !!value 1511 | 1512 | const truthy = [123, undefined].filter(isTruthy) // => number[] 1513 | const notTruthy = [false, true].filter(isTruthy) // => never[] 1514 | ``` 1515 | 1516 | 1517 | ### Falsy 1518 | 1519 | Contains all `Falsy` values (false | '' | 0 | null | undefined) 1520 | 1521 | #### Usage 1522 | 1523 | ```TypeScript 1524 | import { Falsy } from 'typesafe-utils' 1525 | 1526 | export const isFalsy = (value: T): value is Falsy => !value 1527 | 1528 | const falsy = [undefined, ''].filter(isFalsy) // => undefined[] 1529 | const notFalsy = [0, ''].filter(isFalsy) // => never[] 1530 | ``` 1531 | 1532 | 1533 | ### TypeGuard 1534 | ### TypeGuardWithReturnType 1535 | 1536 | Allows you to write custom `TypeGuard` functions. 1537 | 1538 | #### Usage 1539 | 1540 | ```TypeScript 1541 | import { TypeGuard } from 'typesafe-utils' 1542 | 1543 | type Project { 1544 | id: number 1545 | // ... 1546 | } 1547 | 1548 | const isProject = (value: T): value is TypeGuard => value?.hasOwnProperty('id') 1549 | 1550 | const p1 = isProject({ id: 1 }) // => true 1551 | const p2 = isProject(true) // => false 1552 | ``` 1553 | 1554 | 1555 | ### TypeGuardInverted 1556 | ### TypeGuardInvertedWithReturnType 1557 | 1558 | Allows you to write custom inverted `TypeGuard` functions. 1559 | 1560 | #### Usage 1561 | 1562 | ```TypeScript 1563 | import { TypeGuardInverted } from 'typesafe-utils' 1564 | 1565 | type Project { 1566 | id: number 1567 | // ... 1568 | } 1569 | 1570 | const isNotProject = (value: T): value is TypeGuardInverted => !value?.hasOwnProperty('id') 1571 | 1572 | const p1 = isNotProject({ id: 1 }) // => false 1573 | const p2 = isNotProject(null) // => true 1574 | ``` 1575 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typesafe-utils", 3 | "version": "1.16.2", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.12.11", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", 10 | "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.10.4" 14 | } 15 | }, 16 | "@babel/compat-data": { 17 | "version": "7.15.0", 18 | "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", 19 | "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", 20 | "dev": true 21 | }, 22 | "@babel/core": { 23 | "version": "7.15.0", 24 | "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz", 25 | "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==", 26 | "dev": true, 27 | "requires": { 28 | "@babel/code-frame": "^7.14.5", 29 | "@babel/generator": "^7.15.0", 30 | "@babel/helper-compilation-targets": "^7.15.0", 31 | "@babel/helper-module-transforms": "^7.15.0", 32 | "@babel/helpers": "^7.14.8", 33 | "@babel/parser": "^7.15.0", 34 | "@babel/template": "^7.14.5", 35 | "@babel/traverse": "^7.15.0", 36 | "@babel/types": "^7.15.0", 37 | "convert-source-map": "^1.7.0", 38 | "debug": "^4.1.0", 39 | "gensync": "^1.0.0-beta.2", 40 | "json5": "^2.1.2", 41 | "semver": "^6.3.0", 42 | "source-map": "^0.5.0" 43 | }, 44 | "dependencies": { 45 | "@babel/code-frame": { 46 | "version": "7.14.5", 47 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", 48 | "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", 49 | "dev": true, 50 | "requires": { 51 | "@babel/highlight": "^7.14.5" 52 | } 53 | }, 54 | "semver": { 55 | "version": "6.3.0", 56 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 57 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 58 | "dev": true 59 | } 60 | } 61 | }, 62 | "@babel/generator": { 63 | "version": "7.15.0", 64 | "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", 65 | "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", 66 | "dev": true, 67 | "requires": { 68 | "@babel/types": "^7.15.0", 69 | "jsesc": "^2.5.1", 70 | "source-map": "^0.5.0" 71 | } 72 | }, 73 | "@babel/helper-compilation-targets": { 74 | "version": "7.15.0", 75 | "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", 76 | "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", 77 | "dev": true, 78 | "requires": { 79 | "@babel/compat-data": "^7.15.0", 80 | "@babel/helper-validator-option": "^7.14.5", 81 | "browserslist": "^4.16.6", 82 | "semver": "^6.3.0" 83 | }, 84 | "dependencies": { 85 | "semver": { 86 | "version": "6.3.0", 87 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 88 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 89 | "dev": true 90 | } 91 | } 92 | }, 93 | "@babel/helper-function-name": { 94 | "version": "7.14.5", 95 | "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", 96 | "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", 97 | "dev": true, 98 | "requires": { 99 | "@babel/helper-get-function-arity": "^7.14.5", 100 | "@babel/template": "^7.14.5", 101 | "@babel/types": "^7.14.5" 102 | } 103 | }, 104 | "@babel/helper-get-function-arity": { 105 | "version": "7.14.5", 106 | "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", 107 | "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", 108 | "dev": true, 109 | "requires": { 110 | "@babel/types": "^7.14.5" 111 | } 112 | }, 113 | "@babel/helper-hoist-variables": { 114 | "version": "7.14.5", 115 | "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", 116 | "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", 117 | "dev": true, 118 | "requires": { 119 | "@babel/types": "^7.14.5" 120 | } 121 | }, 122 | "@babel/helper-member-expression-to-functions": { 123 | "version": "7.15.0", 124 | "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", 125 | "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", 126 | "dev": true, 127 | "requires": { 128 | "@babel/types": "^7.15.0" 129 | } 130 | }, 131 | "@babel/helper-module-imports": { 132 | "version": "7.14.5", 133 | "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", 134 | "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", 135 | "dev": true, 136 | "requires": { 137 | "@babel/types": "^7.14.5" 138 | } 139 | }, 140 | "@babel/helper-module-transforms": { 141 | "version": "7.15.0", 142 | "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", 143 | "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", 144 | "dev": true, 145 | "requires": { 146 | "@babel/helper-module-imports": "^7.14.5", 147 | "@babel/helper-replace-supers": "^7.15.0", 148 | "@babel/helper-simple-access": "^7.14.8", 149 | "@babel/helper-split-export-declaration": "^7.14.5", 150 | "@babel/helper-validator-identifier": "^7.14.9", 151 | "@babel/template": "^7.14.5", 152 | "@babel/traverse": "^7.15.0", 153 | "@babel/types": "^7.15.0" 154 | } 155 | }, 156 | "@babel/helper-optimise-call-expression": { 157 | "version": "7.14.5", 158 | "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", 159 | "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", 160 | "dev": true, 161 | "requires": { 162 | "@babel/types": "^7.14.5" 163 | } 164 | }, 165 | "@babel/helper-replace-supers": { 166 | "version": "7.15.0", 167 | "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", 168 | "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", 169 | "dev": true, 170 | "requires": { 171 | "@babel/helper-member-expression-to-functions": "^7.15.0", 172 | "@babel/helper-optimise-call-expression": "^7.14.5", 173 | "@babel/traverse": "^7.15.0", 174 | "@babel/types": "^7.15.0" 175 | } 176 | }, 177 | "@babel/helper-simple-access": { 178 | "version": "7.14.8", 179 | "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz", 180 | "integrity": "sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==", 181 | "dev": true, 182 | "requires": { 183 | "@babel/types": "^7.14.8" 184 | } 185 | }, 186 | "@babel/helper-split-export-declaration": { 187 | "version": "7.14.5", 188 | "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", 189 | "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", 190 | "dev": true, 191 | "requires": { 192 | "@babel/types": "^7.14.5" 193 | } 194 | }, 195 | "@babel/helper-validator-identifier": { 196 | "version": "7.14.9", 197 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", 198 | "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", 199 | "dev": true 200 | }, 201 | "@babel/helper-validator-option": { 202 | "version": "7.14.5", 203 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", 204 | "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", 205 | "dev": true 206 | }, 207 | "@babel/helpers": { 208 | "version": "7.15.3", 209 | "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.3.tgz", 210 | "integrity": "sha512-HwJiz52XaS96lX+28Tnbu31VeFSQJGOeKHJeaEPQlTl7PnlhFElWPj8tUXtqFIzeN86XxXoBr+WFAyK2PPVz6g==", 211 | "dev": true, 212 | "requires": { 213 | "@babel/template": "^7.14.5", 214 | "@babel/traverse": "^7.15.0", 215 | "@babel/types": "^7.15.0" 216 | } 217 | }, 218 | "@babel/highlight": { 219 | "version": "7.14.5", 220 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", 221 | "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", 222 | "dev": true, 223 | "requires": { 224 | "@babel/helper-validator-identifier": "^7.14.5", 225 | "chalk": "^2.0.0", 226 | "js-tokens": "^4.0.0" 227 | }, 228 | "dependencies": { 229 | "ansi-styles": { 230 | "version": "3.2.1", 231 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 232 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 233 | "dev": true, 234 | "requires": { 235 | "color-convert": "^1.9.0" 236 | } 237 | }, 238 | "chalk": { 239 | "version": "2.4.2", 240 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 241 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 242 | "dev": true, 243 | "requires": { 244 | "ansi-styles": "^3.2.1", 245 | "escape-string-regexp": "^1.0.5", 246 | "supports-color": "^5.3.0" 247 | } 248 | }, 249 | "color-convert": { 250 | "version": "1.9.3", 251 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 252 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 253 | "dev": true, 254 | "requires": { 255 | "color-name": "1.1.3" 256 | } 257 | }, 258 | "color-name": { 259 | "version": "1.1.3", 260 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 261 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 262 | "dev": true 263 | }, 264 | "escape-string-regexp": { 265 | "version": "1.0.5", 266 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 267 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 268 | "dev": true 269 | }, 270 | "has-flag": { 271 | "version": "3.0.0", 272 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 273 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 274 | "dev": true 275 | }, 276 | "supports-color": { 277 | "version": "5.5.0", 278 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 279 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 280 | "dev": true, 281 | "requires": { 282 | "has-flag": "^3.0.0" 283 | } 284 | } 285 | } 286 | }, 287 | "@babel/parser": { 288 | "version": "7.15.3", 289 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.3.tgz", 290 | "integrity": "sha512-O0L6v/HvqbdJawj0iBEfVQMc3/6WP+AeOsovsIgBFyJaG+W2w7eqvZB7puddATmWuARlm1SX7DwxJ/JJUnDpEA==", 291 | "dev": true 292 | }, 293 | "@babel/template": { 294 | "version": "7.14.5", 295 | "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", 296 | "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", 297 | "dev": true, 298 | "requires": { 299 | "@babel/code-frame": "^7.14.5", 300 | "@babel/parser": "^7.14.5", 301 | "@babel/types": "^7.14.5" 302 | }, 303 | "dependencies": { 304 | "@babel/code-frame": { 305 | "version": "7.14.5", 306 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", 307 | "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", 308 | "dev": true, 309 | "requires": { 310 | "@babel/highlight": "^7.14.5" 311 | } 312 | } 313 | } 314 | }, 315 | "@babel/traverse": { 316 | "version": "7.15.0", 317 | "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", 318 | "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", 319 | "dev": true, 320 | "requires": { 321 | "@babel/code-frame": "^7.14.5", 322 | "@babel/generator": "^7.15.0", 323 | "@babel/helper-function-name": "^7.14.5", 324 | "@babel/helper-hoist-variables": "^7.14.5", 325 | "@babel/helper-split-export-declaration": "^7.14.5", 326 | "@babel/parser": "^7.15.0", 327 | "@babel/types": "^7.15.0", 328 | "debug": "^4.1.0", 329 | "globals": "^11.1.0" 330 | }, 331 | "dependencies": { 332 | "@babel/code-frame": { 333 | "version": "7.14.5", 334 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", 335 | "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", 336 | "dev": true, 337 | "requires": { 338 | "@babel/highlight": "^7.14.5" 339 | } 340 | }, 341 | "globals": { 342 | "version": "11.12.0", 343 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 344 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 345 | "dev": true 346 | } 347 | } 348 | }, 349 | "@babel/types": { 350 | "version": "7.15.0", 351 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", 352 | "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", 353 | "dev": true, 354 | "requires": { 355 | "@babel/helper-validator-identifier": "^7.14.9", 356 | "to-fast-properties": "^2.0.0" 357 | } 358 | }, 359 | "@cspotcode/source-map-consumer": { 360 | "version": "0.8.0", 361 | "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", 362 | "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", 363 | "dev": true 364 | }, 365 | "@cspotcode/source-map-support": { 366 | "version": "0.6.1", 367 | "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.6.1.tgz", 368 | "integrity": "sha512-DX3Z+T5dt1ockmPdobJS/FAsQPW4V4SrWEhD2iYQT2Cb2tQsiMnYxrcUH9By/Z3B+v0S5LMBkQtV/XOBbpLEOg==", 369 | "dev": true, 370 | "requires": { 371 | "@cspotcode/source-map-consumer": "0.8.0" 372 | } 373 | }, 374 | "@eslint/eslintrc": { 375 | "version": "0.4.3", 376 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", 377 | "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", 378 | "dev": true, 379 | "requires": { 380 | "ajv": "^6.12.4", 381 | "debug": "^4.1.1", 382 | "espree": "^7.3.0", 383 | "globals": "^13.9.0", 384 | "ignore": "^4.0.6", 385 | "import-fresh": "^3.2.1", 386 | "js-yaml": "^3.13.1", 387 | "minimatch": "^3.0.4", 388 | "strip-json-comments": "^3.1.1" 389 | } 390 | }, 391 | "@humanwhocodes/config-array": { 392 | "version": "0.5.0", 393 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", 394 | "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", 395 | "dev": true, 396 | "requires": { 397 | "@humanwhocodes/object-schema": "^1.2.0", 398 | "debug": "^4.1.1", 399 | "minimatch": "^3.0.4" 400 | } 401 | }, 402 | "@humanwhocodes/object-schema": { 403 | "version": "1.2.0", 404 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", 405 | "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", 406 | "dev": true 407 | }, 408 | "@istanbuljs/load-nyc-config": { 409 | "version": "1.1.0", 410 | "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", 411 | "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", 412 | "dev": true, 413 | "requires": { 414 | "camelcase": "^5.3.1", 415 | "find-up": "^4.1.0", 416 | "get-package-type": "^0.1.0", 417 | "js-yaml": "^3.13.1", 418 | "resolve-from": "^5.0.0" 419 | }, 420 | "dependencies": { 421 | "resolve-from": { 422 | "version": "5.0.0", 423 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", 424 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", 425 | "dev": true 426 | } 427 | } 428 | }, 429 | "@istanbuljs/nyc-config-typescript": { 430 | "version": "1.0.1", 431 | "resolved": "https://registry.npmjs.org/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.1.tgz", 432 | "integrity": "sha512-/gz6LgVpky205LuoOfwEZmnUtaSmdk0QIMcNFj9OvxhiMhPpKftMgZmGN7jNj7jR+lr8IB1Yks3QSSSNSxfoaQ==", 433 | "dev": true, 434 | "requires": { 435 | "@istanbuljs/schema": "^0.1.2" 436 | } 437 | }, 438 | "@istanbuljs/schema": { 439 | "version": "0.1.3", 440 | "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", 441 | "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", 442 | "dev": true 443 | }, 444 | "@nodelib/fs.scandir": { 445 | "version": "2.1.5", 446 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", 447 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", 448 | "dev": true, 449 | "requires": { 450 | "@nodelib/fs.stat": "2.0.5", 451 | "run-parallel": "^1.1.9" 452 | } 453 | }, 454 | "@nodelib/fs.stat": { 455 | "version": "2.0.5", 456 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", 457 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", 458 | "dev": true 459 | }, 460 | "@nodelib/fs.walk": { 461 | "version": "1.2.8", 462 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", 463 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", 464 | "dev": true, 465 | "requires": { 466 | "@nodelib/fs.scandir": "2.1.5", 467 | "fastq": "^1.6.0" 468 | } 469 | }, 470 | "@tsconfig/node10": { 471 | "version": "1.0.8", 472 | "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", 473 | "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", 474 | "dev": true 475 | }, 476 | "@tsconfig/node12": { 477 | "version": "1.0.9", 478 | "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", 479 | "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", 480 | "dev": true 481 | }, 482 | "@tsconfig/node14": { 483 | "version": "1.0.1", 484 | "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", 485 | "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", 486 | "dev": true 487 | }, 488 | "@tsconfig/node16": { 489 | "version": "1.0.2", 490 | "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", 491 | "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", 492 | "dev": true 493 | }, 494 | "@types/json-schema": { 495 | "version": "7.0.9", 496 | "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", 497 | "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", 498 | "dev": true 499 | }, 500 | "@types/node": { 501 | "version": "16.7.1", 502 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.7.1.tgz", 503 | "integrity": "sha512-ncRdc45SoYJ2H4eWU9ReDfp3vtFqDYhjOsKlFFUDEn8V1Bgr2RjYal8YT5byfadWIRluhPFU6JiDOl0H6Sl87A==", 504 | "dev": true 505 | }, 506 | "@typescript-eslint/eslint-plugin": { 507 | "version": "4.29.3", 508 | "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.3.tgz", 509 | "integrity": "sha512-tBgfA3K/3TsZY46ROGvoRxQr1wBkclbVqRQep97MjVHJzcRBURRY3sNFqLk0/Xr//BY5hM9H2p/kp+6qim85SA==", 510 | "dev": true, 511 | "requires": { 512 | "@typescript-eslint/experimental-utils": "4.29.3", 513 | "@typescript-eslint/scope-manager": "4.29.3", 514 | "debug": "^4.3.1", 515 | "functional-red-black-tree": "^1.0.1", 516 | "regexpp": "^3.1.0", 517 | "semver": "^7.3.5", 518 | "tsutils": "^3.21.0" 519 | } 520 | }, 521 | "@typescript-eslint/experimental-utils": { 522 | "version": "4.29.3", 523 | "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.3.tgz", 524 | "integrity": "sha512-ffIvbytTVWz+3keg+Sy94FG1QeOvmV9dP2YSdLFHw/ieLXWCa3U1TYu8IRCOpMv2/SPS8XqhM1+ou1YHsdzKrg==", 525 | "dev": true, 526 | "requires": { 527 | "@types/json-schema": "^7.0.7", 528 | "@typescript-eslint/scope-manager": "4.29.3", 529 | "@typescript-eslint/types": "4.29.3", 530 | "@typescript-eslint/typescript-estree": "4.29.3", 531 | "eslint-scope": "^5.1.1", 532 | "eslint-utils": "^3.0.0" 533 | } 534 | }, 535 | "@typescript-eslint/parser": { 536 | "version": "4.29.3", 537 | "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.3.tgz", 538 | "integrity": "sha512-jrHOV5g2u8ROghmspKoW7pN8T/qUzk0+DITun0MELptvngtMrwUJ1tv5zMI04CYVEUsSrN4jV7AKSv+I0y0EfQ==", 539 | "dev": true, 540 | "requires": { 541 | "@typescript-eslint/scope-manager": "4.29.3", 542 | "@typescript-eslint/types": "4.29.3", 543 | "@typescript-eslint/typescript-estree": "4.29.3", 544 | "debug": "^4.3.1" 545 | } 546 | }, 547 | "@typescript-eslint/scope-manager": { 548 | "version": "4.29.3", 549 | "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.3.tgz", 550 | "integrity": "sha512-x+w8BLXO7iWPkG5mEy9bA1iFRnk36p/goVlYobVWHyDw69YmaH9q6eA+Fgl7kYHmFvWlebUTUfhtIg4zbbl8PA==", 551 | "dev": true, 552 | "requires": { 553 | "@typescript-eslint/types": "4.29.3", 554 | "@typescript-eslint/visitor-keys": "4.29.3" 555 | } 556 | }, 557 | "@typescript-eslint/types": { 558 | "version": "4.29.3", 559 | "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.3.tgz", 560 | "integrity": "sha512-s1eV1lKNgoIYLAl1JUba8NhULmf+jOmmeFO1G5MN/RBCyyzg4TIOfIOICVNC06lor+Xmy4FypIIhFiJXOknhIg==", 561 | "dev": true 562 | }, 563 | "@typescript-eslint/typescript-estree": { 564 | "version": "4.29.3", 565 | "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.3.tgz", 566 | "integrity": "sha512-45oQJA0bxna4O5TMwz55/TpgjX1YrAPOI/rb6kPgmdnemRZx/dB0rsx+Ku8jpDvqTxcE1C/qEbVHbS3h0hflag==", 567 | "dev": true, 568 | "requires": { 569 | "@typescript-eslint/types": "4.29.3", 570 | "@typescript-eslint/visitor-keys": "4.29.3", 571 | "debug": "^4.3.1", 572 | "globby": "^11.0.3", 573 | "is-glob": "^4.0.1", 574 | "semver": "^7.3.5", 575 | "tsutils": "^3.21.0" 576 | } 577 | }, 578 | "@typescript-eslint/visitor-keys": { 579 | "version": "4.29.3", 580 | "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.3.tgz", 581 | "integrity": "sha512-MGGfJvXT4asUTeVs0Q2m+sY63UsfnA+C/FDgBKV3itLBmM9H0u+URcneePtkd0at1YELmZK6HSolCqM4Fzs6yA==", 582 | "dev": true, 583 | "requires": { 584 | "@typescript-eslint/types": "4.29.3", 585 | "eslint-visitor-keys": "^2.0.0" 586 | } 587 | }, 588 | "acorn": { 589 | "version": "7.4.1", 590 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", 591 | "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", 592 | "dev": true 593 | }, 594 | "acorn-jsx": { 595 | "version": "5.3.2", 596 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", 597 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", 598 | "dev": true 599 | }, 600 | "acorn-walk": { 601 | "version": "8.1.1", 602 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.1.1.tgz", 603 | "integrity": "sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==", 604 | "dev": true 605 | }, 606 | "aggregate-error": { 607 | "version": "3.1.0", 608 | "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", 609 | "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", 610 | "dev": true, 611 | "requires": { 612 | "clean-stack": "^2.0.0", 613 | "indent-string": "^4.0.0" 614 | } 615 | }, 616 | "ajv": { 617 | "version": "6.12.6", 618 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 619 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 620 | "dev": true, 621 | "requires": { 622 | "fast-deep-equal": "^3.1.1", 623 | "fast-json-stable-stringify": "^2.0.0", 624 | "json-schema-traverse": "^0.4.1", 625 | "uri-js": "^4.2.2" 626 | } 627 | }, 628 | "ansi-colors": { 629 | "version": "4.1.1", 630 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", 631 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", 632 | "dev": true 633 | }, 634 | "ansi-regex": { 635 | "version": "5.0.0", 636 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 637 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 638 | "dev": true 639 | }, 640 | "ansi-styles": { 641 | "version": "4.3.0", 642 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 643 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 644 | "dev": true, 645 | "requires": { 646 | "color-convert": "^2.0.1" 647 | } 648 | }, 649 | "append-transform": { 650 | "version": "2.0.0", 651 | "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", 652 | "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", 653 | "dev": true, 654 | "requires": { 655 | "default-require-extensions": "^3.0.0" 656 | } 657 | }, 658 | "archy": { 659 | "version": "1.0.0", 660 | "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", 661 | "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", 662 | "dev": true 663 | }, 664 | "arg": { 665 | "version": "4.1.3", 666 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", 667 | "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", 668 | "dev": true 669 | }, 670 | "argparse": { 671 | "version": "1.0.10", 672 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 673 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 674 | "dev": true, 675 | "requires": { 676 | "sprintf-js": "~1.0.2" 677 | } 678 | }, 679 | "array-union": { 680 | "version": "2.1.0", 681 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 682 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 683 | "dev": true 684 | }, 685 | "astral-regex": { 686 | "version": "2.0.0", 687 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", 688 | "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", 689 | "dev": true 690 | }, 691 | "balanced-match": { 692 | "version": "1.0.2", 693 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 694 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 695 | "dev": true 696 | }, 697 | "brace-expansion": { 698 | "version": "1.1.11", 699 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 700 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 701 | "dev": true, 702 | "requires": { 703 | "balanced-match": "^1.0.0", 704 | "concat-map": "0.0.1" 705 | } 706 | }, 707 | "braces": { 708 | "version": "3.0.2", 709 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 710 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 711 | "dev": true, 712 | "requires": { 713 | "fill-range": "^7.0.1" 714 | } 715 | }, 716 | "browserslist": { 717 | "version": "4.16.8", 718 | "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.8.tgz", 719 | "integrity": "sha512-sc2m9ohR/49sWEbPj14ZSSZqp+kbi16aLao42Hmn3Z8FpjuMaq2xCA2l4zl9ITfyzvnvyE0hcg62YkIGKxgaNQ==", 720 | "dev": true, 721 | "requires": { 722 | "caniuse-lite": "^1.0.30001251", 723 | "colorette": "^1.3.0", 724 | "electron-to-chromium": "^1.3.811", 725 | "escalade": "^3.1.1", 726 | "node-releases": "^1.1.75" 727 | } 728 | }, 729 | "caching-transform": { 730 | "version": "4.0.0", 731 | "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", 732 | "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", 733 | "dev": true, 734 | "requires": { 735 | "hasha": "^5.0.0", 736 | "make-dir": "^3.0.0", 737 | "package-hash": "^4.0.0", 738 | "write-file-atomic": "^3.0.0" 739 | } 740 | }, 741 | "callsites": { 742 | "version": "3.1.0", 743 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 744 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 745 | "dev": true 746 | }, 747 | "camelcase": { 748 | "version": "5.3.1", 749 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 750 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 751 | "dev": true 752 | }, 753 | "caniuse-lite": { 754 | "version": "1.0.30001251", 755 | "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz", 756 | "integrity": "sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A==", 757 | "dev": true 758 | }, 759 | "chalk": { 760 | "version": "4.1.2", 761 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 762 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 763 | "dev": true, 764 | "requires": { 765 | "ansi-styles": "^4.1.0", 766 | "supports-color": "^7.1.0" 767 | } 768 | }, 769 | "clean-stack": { 770 | "version": "2.2.0", 771 | "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", 772 | "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", 773 | "dev": true 774 | }, 775 | "cliui": { 776 | "version": "6.0.0", 777 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", 778 | "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", 779 | "dev": true, 780 | "requires": { 781 | "string-width": "^4.2.0", 782 | "strip-ansi": "^6.0.0", 783 | "wrap-ansi": "^6.2.0" 784 | } 785 | }, 786 | "color-convert": { 787 | "version": "2.0.1", 788 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 789 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 790 | "dev": true, 791 | "requires": { 792 | "color-name": "~1.1.4" 793 | } 794 | }, 795 | "color-name": { 796 | "version": "1.1.4", 797 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 798 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 799 | "dev": true 800 | }, 801 | "colorette": { 802 | "version": "1.3.0", 803 | "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.3.0.tgz", 804 | "integrity": "sha512-ecORCqbSFP7Wm8Y6lyqMJjexBQqXSF7SSeaTyGGphogUjBlFP9m9o08wy86HL2uB7fMTxtOUzLMk7ogKcxMg1w==", 805 | "dev": true 806 | }, 807 | "commondir": { 808 | "version": "1.0.1", 809 | "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", 810 | "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", 811 | "dev": true 812 | }, 813 | "concat-map": { 814 | "version": "0.0.1", 815 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 816 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 817 | "dev": true 818 | }, 819 | "convert-source-map": { 820 | "version": "1.8.0", 821 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", 822 | "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", 823 | "dev": true, 824 | "requires": { 825 | "safe-buffer": "~5.1.1" 826 | } 827 | }, 828 | "create-require": { 829 | "version": "1.1.1", 830 | "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", 831 | "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", 832 | "dev": true 833 | }, 834 | "cross-spawn": { 835 | "version": "7.0.3", 836 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 837 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 838 | "dev": true, 839 | "requires": { 840 | "path-key": "^3.1.0", 841 | "shebang-command": "^2.0.0", 842 | "which": "^2.0.1" 843 | } 844 | }, 845 | "debug": { 846 | "version": "4.3.2", 847 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", 848 | "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", 849 | "dev": true, 850 | "requires": { 851 | "ms": "2.1.2" 852 | } 853 | }, 854 | "decamelize": { 855 | "version": "1.2.0", 856 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 857 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 858 | "dev": true 859 | }, 860 | "deep-is": { 861 | "version": "0.1.3", 862 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 863 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 864 | "dev": true 865 | }, 866 | "default-require-extensions": { 867 | "version": "3.0.0", 868 | "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", 869 | "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", 870 | "dev": true, 871 | "requires": { 872 | "strip-bom": "^4.0.0" 873 | } 874 | }, 875 | "dequal": { 876 | "version": "2.0.2", 877 | "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.2.tgz", 878 | "integrity": "sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==", 879 | "dev": true 880 | }, 881 | "diff": { 882 | "version": "4.0.2", 883 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 884 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 885 | "dev": true 886 | }, 887 | "dir-glob": { 888 | "version": "3.0.1", 889 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 890 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 891 | "dev": true, 892 | "requires": { 893 | "path-type": "^4.0.0" 894 | } 895 | }, 896 | "doctrine": { 897 | "version": "3.0.0", 898 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 899 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 900 | "dev": true, 901 | "requires": { 902 | "esutils": "^2.0.2" 903 | } 904 | }, 905 | "electron-to-chromium": { 906 | "version": "1.3.817", 907 | "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.817.tgz", 908 | "integrity": "sha512-Vw0Faepf2Id9Kf2e97M/c99qf168xg86JLKDxivvlpBQ9KDtjSeX0v+TiuSE25PqeQfTz+NJs375b64ca3XOIQ==", 909 | "dev": true 910 | }, 911 | "emoji-regex": { 912 | "version": "8.0.0", 913 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 914 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 915 | "dev": true 916 | }, 917 | "enquirer": { 918 | "version": "2.3.6", 919 | "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", 920 | "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", 921 | "dev": true, 922 | "requires": { 923 | "ansi-colors": "^4.1.1" 924 | } 925 | }, 926 | "es6-error": { 927 | "version": "4.1.1", 928 | "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", 929 | "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", 930 | "dev": true 931 | }, 932 | "escalade": { 933 | "version": "3.1.1", 934 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", 935 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", 936 | "dev": true 937 | }, 938 | "escape-string-regexp": { 939 | "version": "4.0.0", 940 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 941 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 942 | "dev": true 943 | }, 944 | "eslint": { 945 | "version": "7.32.0", 946 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", 947 | "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", 948 | "dev": true, 949 | "requires": { 950 | "@babel/code-frame": "7.12.11", 951 | "@eslint/eslintrc": "^0.4.3", 952 | "@humanwhocodes/config-array": "^0.5.0", 953 | "ajv": "^6.10.0", 954 | "chalk": "^4.0.0", 955 | "cross-spawn": "^7.0.2", 956 | "debug": "^4.0.1", 957 | "doctrine": "^3.0.0", 958 | "enquirer": "^2.3.5", 959 | "escape-string-regexp": "^4.0.0", 960 | "eslint-scope": "^5.1.1", 961 | "eslint-utils": "^2.1.0", 962 | "eslint-visitor-keys": "^2.0.0", 963 | "espree": "^7.3.1", 964 | "esquery": "^1.4.0", 965 | "esutils": "^2.0.2", 966 | "fast-deep-equal": "^3.1.3", 967 | "file-entry-cache": "^6.0.1", 968 | "functional-red-black-tree": "^1.0.1", 969 | "glob-parent": "^5.1.2", 970 | "globals": "^13.6.0", 971 | "ignore": "^4.0.6", 972 | "import-fresh": "^3.0.0", 973 | "imurmurhash": "^0.1.4", 974 | "is-glob": "^4.0.0", 975 | "js-yaml": "^3.13.1", 976 | "json-stable-stringify-without-jsonify": "^1.0.1", 977 | "levn": "^0.4.1", 978 | "lodash.merge": "^4.6.2", 979 | "minimatch": "^3.0.4", 980 | "natural-compare": "^1.4.0", 981 | "optionator": "^0.9.1", 982 | "progress": "^2.0.0", 983 | "regexpp": "^3.1.0", 984 | "semver": "^7.2.1", 985 | "strip-ansi": "^6.0.0", 986 | "strip-json-comments": "^3.1.0", 987 | "table": "^6.0.9", 988 | "text-table": "^0.2.0", 989 | "v8-compile-cache": "^2.0.3" 990 | }, 991 | "dependencies": { 992 | "eslint-utils": { 993 | "version": "2.1.0", 994 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", 995 | "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", 996 | "dev": true, 997 | "requires": { 998 | "eslint-visitor-keys": "^1.1.0" 999 | }, 1000 | "dependencies": { 1001 | "eslint-visitor-keys": { 1002 | "version": "1.3.0", 1003 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 1004 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 1005 | "dev": true 1006 | } 1007 | } 1008 | } 1009 | } 1010 | }, 1011 | "eslint-config-prettier": { 1012 | "version": "8.3.0", 1013 | "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz", 1014 | "integrity": "sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==", 1015 | "dev": true 1016 | }, 1017 | "eslint-plugin-prettier": { 1018 | "version": "3.4.1", 1019 | "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz", 1020 | "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==", 1021 | "dev": true, 1022 | "requires": { 1023 | "prettier-linter-helpers": "^1.0.0" 1024 | } 1025 | }, 1026 | "eslint-scope": { 1027 | "version": "5.1.1", 1028 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", 1029 | "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", 1030 | "dev": true, 1031 | "requires": { 1032 | "esrecurse": "^4.3.0", 1033 | "estraverse": "^4.1.1" 1034 | } 1035 | }, 1036 | "eslint-utils": { 1037 | "version": "3.0.0", 1038 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", 1039 | "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", 1040 | "dev": true, 1041 | "requires": { 1042 | "eslint-visitor-keys": "^2.0.0" 1043 | } 1044 | }, 1045 | "eslint-visitor-keys": { 1046 | "version": "2.1.0", 1047 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", 1048 | "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", 1049 | "dev": true 1050 | }, 1051 | "espree": { 1052 | "version": "7.3.1", 1053 | "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", 1054 | "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", 1055 | "dev": true, 1056 | "requires": { 1057 | "acorn": "^7.4.0", 1058 | "acorn-jsx": "^5.3.1", 1059 | "eslint-visitor-keys": "^1.3.0" 1060 | }, 1061 | "dependencies": { 1062 | "eslint-visitor-keys": { 1063 | "version": "1.3.0", 1064 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", 1065 | "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", 1066 | "dev": true 1067 | } 1068 | } 1069 | }, 1070 | "esprima": { 1071 | "version": "4.0.1", 1072 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 1073 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 1074 | "dev": true 1075 | }, 1076 | "esquery": { 1077 | "version": "1.4.0", 1078 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", 1079 | "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", 1080 | "dev": true, 1081 | "requires": { 1082 | "estraverse": "^5.1.0" 1083 | }, 1084 | "dependencies": { 1085 | "estraverse": { 1086 | "version": "5.2.0", 1087 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", 1088 | "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", 1089 | "dev": true 1090 | } 1091 | } 1092 | }, 1093 | "esrecurse": { 1094 | "version": "4.3.0", 1095 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", 1096 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", 1097 | "dev": true, 1098 | "requires": { 1099 | "estraverse": "^5.2.0" 1100 | }, 1101 | "dependencies": { 1102 | "estraverse": { 1103 | "version": "5.2.0", 1104 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", 1105 | "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", 1106 | "dev": true 1107 | } 1108 | } 1109 | }, 1110 | "estraverse": { 1111 | "version": "4.3.0", 1112 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 1113 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 1114 | "dev": true 1115 | }, 1116 | "esutils": { 1117 | "version": "2.0.3", 1118 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 1119 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 1120 | "dev": true 1121 | }, 1122 | "fast-deep-equal": { 1123 | "version": "3.1.3", 1124 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1125 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1126 | "dev": true 1127 | }, 1128 | "fast-diff": { 1129 | "version": "1.2.0", 1130 | "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", 1131 | "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", 1132 | "dev": true 1133 | }, 1134 | "fast-glob": { 1135 | "version": "3.2.7", 1136 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", 1137 | "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", 1138 | "dev": true, 1139 | "requires": { 1140 | "@nodelib/fs.stat": "^2.0.2", 1141 | "@nodelib/fs.walk": "^1.2.3", 1142 | "glob-parent": "^5.1.2", 1143 | "merge2": "^1.3.0", 1144 | "micromatch": "^4.0.4" 1145 | } 1146 | }, 1147 | "fast-json-stable-stringify": { 1148 | "version": "2.1.0", 1149 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", 1150 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", 1151 | "dev": true 1152 | }, 1153 | "fast-levenshtein": { 1154 | "version": "2.0.6", 1155 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 1156 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 1157 | "dev": true 1158 | }, 1159 | "fastq": { 1160 | "version": "1.12.0", 1161 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.12.0.tgz", 1162 | "integrity": "sha512-VNX0QkHK3RsXVKr9KrlUv/FoTa0NdbYoHHl7uXHv2rzyHSlxjdNAKug2twd9luJxpcyNeAgf5iPPMutJO67Dfg==", 1163 | "dev": true, 1164 | "requires": { 1165 | "reusify": "^1.0.4" 1166 | } 1167 | }, 1168 | "file-entry-cache": { 1169 | "version": "6.0.1", 1170 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", 1171 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", 1172 | "dev": true, 1173 | "requires": { 1174 | "flat-cache": "^3.0.4" 1175 | } 1176 | }, 1177 | "fill-range": { 1178 | "version": "7.0.1", 1179 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 1180 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 1181 | "dev": true, 1182 | "requires": { 1183 | "to-regex-range": "^5.0.1" 1184 | } 1185 | }, 1186 | "find-cache-dir": { 1187 | "version": "3.3.1", 1188 | "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", 1189 | "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", 1190 | "dev": true, 1191 | "requires": { 1192 | "commondir": "^1.0.1", 1193 | "make-dir": "^3.0.2", 1194 | "pkg-dir": "^4.1.0" 1195 | } 1196 | }, 1197 | "find-up": { 1198 | "version": "4.1.0", 1199 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 1200 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 1201 | "dev": true, 1202 | "requires": { 1203 | "locate-path": "^5.0.0", 1204 | "path-exists": "^4.0.0" 1205 | } 1206 | }, 1207 | "flat-cache": { 1208 | "version": "3.0.4", 1209 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", 1210 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", 1211 | "dev": true, 1212 | "requires": { 1213 | "flatted": "^3.1.0", 1214 | "rimraf": "^3.0.2" 1215 | } 1216 | }, 1217 | "flatted": { 1218 | "version": "3.2.2", 1219 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", 1220 | "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", 1221 | "dev": true 1222 | }, 1223 | "foreground-child": { 1224 | "version": "2.0.0", 1225 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", 1226 | "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", 1227 | "dev": true, 1228 | "requires": { 1229 | "cross-spawn": "^7.0.0", 1230 | "signal-exit": "^3.0.2" 1231 | } 1232 | }, 1233 | "fromentries": { 1234 | "version": "1.3.2", 1235 | "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", 1236 | "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", 1237 | "dev": true 1238 | }, 1239 | "fs.realpath": { 1240 | "version": "1.0.0", 1241 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1242 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 1243 | "dev": true 1244 | }, 1245 | "functional-red-black-tree": { 1246 | "version": "1.0.1", 1247 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 1248 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 1249 | "dev": true 1250 | }, 1251 | "gensync": { 1252 | "version": "1.0.0-beta.2", 1253 | "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", 1254 | "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", 1255 | "dev": true 1256 | }, 1257 | "get-caller-file": { 1258 | "version": "2.0.5", 1259 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1260 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 1261 | "dev": true 1262 | }, 1263 | "get-package-type": { 1264 | "version": "0.1.0", 1265 | "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", 1266 | "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", 1267 | "dev": true 1268 | }, 1269 | "glob": { 1270 | "version": "7.1.7", 1271 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", 1272 | "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", 1273 | "dev": true, 1274 | "requires": { 1275 | "fs.realpath": "^1.0.0", 1276 | "inflight": "^1.0.4", 1277 | "inherits": "2", 1278 | "minimatch": "^3.0.4", 1279 | "once": "^1.3.0", 1280 | "path-is-absolute": "^1.0.0" 1281 | } 1282 | }, 1283 | "glob-parent": { 1284 | "version": "5.1.2", 1285 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1286 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1287 | "dev": true, 1288 | "requires": { 1289 | "is-glob": "^4.0.1" 1290 | } 1291 | }, 1292 | "globals": { 1293 | "version": "13.11.0", 1294 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", 1295 | "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", 1296 | "dev": true, 1297 | "requires": { 1298 | "type-fest": "^0.20.2" 1299 | } 1300 | }, 1301 | "globby": { 1302 | "version": "11.0.4", 1303 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", 1304 | "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", 1305 | "dev": true, 1306 | "requires": { 1307 | "array-union": "^2.1.0", 1308 | "dir-glob": "^3.0.1", 1309 | "fast-glob": "^3.1.1", 1310 | "ignore": "^5.1.4", 1311 | "merge2": "^1.3.0", 1312 | "slash": "^3.0.0" 1313 | }, 1314 | "dependencies": { 1315 | "ignore": { 1316 | "version": "5.1.8", 1317 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", 1318 | "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", 1319 | "dev": true 1320 | } 1321 | } 1322 | }, 1323 | "graceful-fs": { 1324 | "version": "4.2.8", 1325 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", 1326 | "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", 1327 | "dev": true 1328 | }, 1329 | "has-flag": { 1330 | "version": "4.0.0", 1331 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1332 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1333 | "dev": true 1334 | }, 1335 | "hasha": { 1336 | "version": "5.2.2", 1337 | "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", 1338 | "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", 1339 | "dev": true, 1340 | "requires": { 1341 | "is-stream": "^2.0.0", 1342 | "type-fest": "^0.8.0" 1343 | }, 1344 | "dependencies": { 1345 | "type-fest": { 1346 | "version": "0.8.1", 1347 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", 1348 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", 1349 | "dev": true 1350 | } 1351 | } 1352 | }, 1353 | "html-escaper": { 1354 | "version": "2.0.2", 1355 | "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", 1356 | "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", 1357 | "dev": true 1358 | }, 1359 | "ignore": { 1360 | "version": "4.0.6", 1361 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 1362 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 1363 | "dev": true 1364 | }, 1365 | "import-fresh": { 1366 | "version": "3.3.0", 1367 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", 1368 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", 1369 | "dev": true, 1370 | "requires": { 1371 | "parent-module": "^1.0.0", 1372 | "resolve-from": "^4.0.0" 1373 | } 1374 | }, 1375 | "imurmurhash": { 1376 | "version": "0.1.4", 1377 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1378 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1379 | "dev": true 1380 | }, 1381 | "indent-string": { 1382 | "version": "4.0.0", 1383 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", 1384 | "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", 1385 | "dev": true 1386 | }, 1387 | "inflight": { 1388 | "version": "1.0.6", 1389 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1390 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1391 | "dev": true, 1392 | "requires": { 1393 | "once": "^1.3.0", 1394 | "wrappy": "1" 1395 | } 1396 | }, 1397 | "inherits": { 1398 | "version": "2.0.4", 1399 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1400 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1401 | "dev": true 1402 | }, 1403 | "is-extglob": { 1404 | "version": "2.1.1", 1405 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1406 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1407 | "dev": true 1408 | }, 1409 | "is-fullwidth-code-point": { 1410 | "version": "3.0.0", 1411 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1412 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1413 | "dev": true 1414 | }, 1415 | "is-glob": { 1416 | "version": "4.0.1", 1417 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 1418 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 1419 | "dev": true, 1420 | "requires": { 1421 | "is-extglob": "^2.1.1" 1422 | } 1423 | }, 1424 | "is-number": { 1425 | "version": "7.0.0", 1426 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1427 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1428 | "dev": true 1429 | }, 1430 | "is-stream": { 1431 | "version": "2.0.1", 1432 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", 1433 | "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", 1434 | "dev": true 1435 | }, 1436 | "is-typedarray": { 1437 | "version": "1.0.0", 1438 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1439 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 1440 | "dev": true 1441 | }, 1442 | "is-windows": { 1443 | "version": "1.0.2", 1444 | "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", 1445 | "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", 1446 | "dev": true 1447 | }, 1448 | "isexe": { 1449 | "version": "2.0.0", 1450 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 1451 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 1452 | "dev": true 1453 | }, 1454 | "istanbul-lib-coverage": { 1455 | "version": "3.0.0", 1456 | "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", 1457 | "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", 1458 | "dev": true 1459 | }, 1460 | "istanbul-lib-hook": { 1461 | "version": "3.0.0", 1462 | "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", 1463 | "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", 1464 | "dev": true, 1465 | "requires": { 1466 | "append-transform": "^2.0.0" 1467 | } 1468 | }, 1469 | "istanbul-lib-instrument": { 1470 | "version": "4.0.3", 1471 | "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", 1472 | "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", 1473 | "dev": true, 1474 | "requires": { 1475 | "@babel/core": "^7.7.5", 1476 | "@istanbuljs/schema": "^0.1.2", 1477 | "istanbul-lib-coverage": "^3.0.0", 1478 | "semver": "^6.3.0" 1479 | }, 1480 | "dependencies": { 1481 | "semver": { 1482 | "version": "6.3.0", 1483 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1484 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1485 | "dev": true 1486 | } 1487 | } 1488 | }, 1489 | "istanbul-lib-processinfo": { 1490 | "version": "2.0.2", 1491 | "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", 1492 | "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", 1493 | "dev": true, 1494 | "requires": { 1495 | "archy": "^1.0.0", 1496 | "cross-spawn": "^7.0.0", 1497 | "istanbul-lib-coverage": "^3.0.0-alpha.1", 1498 | "make-dir": "^3.0.0", 1499 | "p-map": "^3.0.0", 1500 | "rimraf": "^3.0.0", 1501 | "uuid": "^3.3.3" 1502 | } 1503 | }, 1504 | "istanbul-lib-report": { 1505 | "version": "3.0.0", 1506 | "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", 1507 | "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", 1508 | "dev": true, 1509 | "requires": { 1510 | "istanbul-lib-coverage": "^3.0.0", 1511 | "make-dir": "^3.0.0", 1512 | "supports-color": "^7.1.0" 1513 | } 1514 | }, 1515 | "istanbul-lib-source-maps": { 1516 | "version": "4.0.0", 1517 | "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", 1518 | "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", 1519 | "dev": true, 1520 | "requires": { 1521 | "debug": "^4.1.1", 1522 | "istanbul-lib-coverage": "^3.0.0", 1523 | "source-map": "^0.6.1" 1524 | }, 1525 | "dependencies": { 1526 | "source-map": { 1527 | "version": "0.6.1", 1528 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1529 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1530 | "dev": true 1531 | } 1532 | } 1533 | }, 1534 | "istanbul-reports": { 1535 | "version": "3.0.2", 1536 | "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", 1537 | "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", 1538 | "dev": true, 1539 | "requires": { 1540 | "html-escaper": "^2.0.0", 1541 | "istanbul-lib-report": "^3.0.0" 1542 | } 1543 | }, 1544 | "js-tokens": { 1545 | "version": "4.0.0", 1546 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1547 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1548 | "dev": true 1549 | }, 1550 | "js-yaml": { 1551 | "version": "3.14.1", 1552 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", 1553 | "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", 1554 | "dev": true, 1555 | "requires": { 1556 | "argparse": "^1.0.7", 1557 | "esprima": "^4.0.0" 1558 | } 1559 | }, 1560 | "jsesc": { 1561 | "version": "2.5.2", 1562 | "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", 1563 | "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", 1564 | "dev": true 1565 | }, 1566 | "json-schema-traverse": { 1567 | "version": "0.4.1", 1568 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 1569 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 1570 | "dev": true 1571 | }, 1572 | "json-stable-stringify-without-jsonify": { 1573 | "version": "1.0.1", 1574 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 1575 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 1576 | "dev": true 1577 | }, 1578 | "json5": { 1579 | "version": "2.2.0", 1580 | "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", 1581 | "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", 1582 | "dev": true, 1583 | "requires": { 1584 | "minimist": "^1.2.5" 1585 | } 1586 | }, 1587 | "kleur": { 1588 | "version": "4.1.4", 1589 | "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", 1590 | "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==", 1591 | "dev": true 1592 | }, 1593 | "levn": { 1594 | "version": "0.4.1", 1595 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", 1596 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", 1597 | "dev": true, 1598 | "requires": { 1599 | "prelude-ls": "^1.2.1", 1600 | "type-check": "~0.4.0" 1601 | } 1602 | }, 1603 | "locate-path": { 1604 | "version": "5.0.0", 1605 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 1606 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 1607 | "dev": true, 1608 | "requires": { 1609 | "p-locate": "^4.1.0" 1610 | } 1611 | }, 1612 | "lodash.clonedeep": { 1613 | "version": "4.5.0", 1614 | "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", 1615 | "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", 1616 | "dev": true 1617 | }, 1618 | "lodash.flattendeep": { 1619 | "version": "4.4.0", 1620 | "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", 1621 | "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", 1622 | "dev": true 1623 | }, 1624 | "lodash.merge": { 1625 | "version": "4.6.2", 1626 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1627 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1628 | "dev": true 1629 | }, 1630 | "lodash.truncate": { 1631 | "version": "4.4.2", 1632 | "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", 1633 | "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", 1634 | "dev": true 1635 | }, 1636 | "lru-cache": { 1637 | "version": "6.0.0", 1638 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1639 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1640 | "dev": true, 1641 | "requires": { 1642 | "yallist": "^4.0.0" 1643 | } 1644 | }, 1645 | "make-dir": { 1646 | "version": "3.1.0", 1647 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 1648 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 1649 | "dev": true, 1650 | "requires": { 1651 | "semver": "^6.0.0" 1652 | }, 1653 | "dependencies": { 1654 | "semver": { 1655 | "version": "6.3.0", 1656 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1657 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1658 | "dev": true 1659 | } 1660 | } 1661 | }, 1662 | "make-error": { 1663 | "version": "1.3.6", 1664 | "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", 1665 | "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", 1666 | "dev": true 1667 | }, 1668 | "merge2": { 1669 | "version": "1.4.1", 1670 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", 1671 | "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", 1672 | "dev": true 1673 | }, 1674 | "micromatch": { 1675 | "version": "4.0.4", 1676 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", 1677 | "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", 1678 | "dev": true, 1679 | "requires": { 1680 | "braces": "^3.0.1", 1681 | "picomatch": "^2.2.3" 1682 | } 1683 | }, 1684 | "minimatch": { 1685 | "version": "3.0.4", 1686 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1687 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1688 | "dev": true, 1689 | "requires": { 1690 | "brace-expansion": "^1.1.7" 1691 | } 1692 | }, 1693 | "minimist": { 1694 | "version": "1.2.5", 1695 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1696 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1697 | "dev": true 1698 | }, 1699 | "mri": { 1700 | "version": "1.1.6", 1701 | "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.6.tgz", 1702 | "integrity": "sha512-oi1b3MfbyGa7FJMP9GmLTttni5JoICpYBRlq+x5V16fZbLsnL9N3wFqqIm/nIG43FjUFkFh9Epzp/kzUGUnJxQ==", 1703 | "dev": true 1704 | }, 1705 | "ms": { 1706 | "version": "2.1.2", 1707 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1708 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1709 | "dev": true 1710 | }, 1711 | "natural-compare": { 1712 | "version": "1.4.0", 1713 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1714 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1715 | "dev": true 1716 | }, 1717 | "node-preload": { 1718 | "version": "0.2.1", 1719 | "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", 1720 | "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", 1721 | "dev": true, 1722 | "requires": { 1723 | "process-on-spawn": "^1.0.0" 1724 | } 1725 | }, 1726 | "node-releases": { 1727 | "version": "1.1.75", 1728 | "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.75.tgz", 1729 | "integrity": "sha512-Qe5OUajvqrqDSy6wrWFmMwfJ0jVgwiw4T3KqmbTcZ62qW0gQkheXYhcFM1+lOVcGUoRxcEcfyvFMAnDgaF1VWw==", 1730 | "dev": true 1731 | }, 1732 | "nyc": { 1733 | "version": "15.1.0", 1734 | "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", 1735 | "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", 1736 | "dev": true, 1737 | "requires": { 1738 | "@istanbuljs/load-nyc-config": "^1.0.0", 1739 | "@istanbuljs/schema": "^0.1.2", 1740 | "caching-transform": "^4.0.0", 1741 | "convert-source-map": "^1.7.0", 1742 | "decamelize": "^1.2.0", 1743 | "find-cache-dir": "^3.2.0", 1744 | "find-up": "^4.1.0", 1745 | "foreground-child": "^2.0.0", 1746 | "get-package-type": "^0.1.0", 1747 | "glob": "^7.1.6", 1748 | "istanbul-lib-coverage": "^3.0.0", 1749 | "istanbul-lib-hook": "^3.0.0", 1750 | "istanbul-lib-instrument": "^4.0.0", 1751 | "istanbul-lib-processinfo": "^2.0.2", 1752 | "istanbul-lib-report": "^3.0.0", 1753 | "istanbul-lib-source-maps": "^4.0.0", 1754 | "istanbul-reports": "^3.0.2", 1755 | "make-dir": "^3.0.0", 1756 | "node-preload": "^0.2.1", 1757 | "p-map": "^3.0.0", 1758 | "process-on-spawn": "^1.0.0", 1759 | "resolve-from": "^5.0.0", 1760 | "rimraf": "^3.0.0", 1761 | "signal-exit": "^3.0.2", 1762 | "spawn-wrap": "^2.0.0", 1763 | "test-exclude": "^6.0.0", 1764 | "yargs": "^15.0.2" 1765 | }, 1766 | "dependencies": { 1767 | "resolve-from": { 1768 | "version": "5.0.0", 1769 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", 1770 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", 1771 | "dev": true 1772 | } 1773 | } 1774 | }, 1775 | "once": { 1776 | "version": "1.4.0", 1777 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1778 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1779 | "dev": true, 1780 | "requires": { 1781 | "wrappy": "1" 1782 | } 1783 | }, 1784 | "optionator": { 1785 | "version": "0.9.1", 1786 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", 1787 | "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", 1788 | "dev": true, 1789 | "requires": { 1790 | "deep-is": "^0.1.3", 1791 | "fast-levenshtein": "^2.0.6", 1792 | "levn": "^0.4.1", 1793 | "prelude-ls": "^1.2.1", 1794 | "type-check": "^0.4.0", 1795 | "word-wrap": "^1.2.3" 1796 | } 1797 | }, 1798 | "p-limit": { 1799 | "version": "2.3.0", 1800 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 1801 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 1802 | "dev": true, 1803 | "requires": { 1804 | "p-try": "^2.0.0" 1805 | } 1806 | }, 1807 | "p-locate": { 1808 | "version": "4.1.0", 1809 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 1810 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 1811 | "dev": true, 1812 | "requires": { 1813 | "p-limit": "^2.2.0" 1814 | } 1815 | }, 1816 | "p-map": { 1817 | "version": "3.0.0", 1818 | "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", 1819 | "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", 1820 | "dev": true, 1821 | "requires": { 1822 | "aggregate-error": "^3.0.0" 1823 | } 1824 | }, 1825 | "p-try": { 1826 | "version": "2.2.0", 1827 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1828 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 1829 | "dev": true 1830 | }, 1831 | "package-hash": { 1832 | "version": "4.0.0", 1833 | "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", 1834 | "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", 1835 | "dev": true, 1836 | "requires": { 1837 | "graceful-fs": "^4.1.15", 1838 | "hasha": "^5.0.0", 1839 | "lodash.flattendeep": "^4.4.0", 1840 | "release-zalgo": "^1.0.0" 1841 | } 1842 | }, 1843 | "parent-module": { 1844 | "version": "1.0.1", 1845 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1846 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1847 | "dev": true, 1848 | "requires": { 1849 | "callsites": "^3.0.0" 1850 | } 1851 | }, 1852 | "path-exists": { 1853 | "version": "4.0.0", 1854 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1855 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1856 | "dev": true 1857 | }, 1858 | "path-is-absolute": { 1859 | "version": "1.0.1", 1860 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1861 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1862 | "dev": true 1863 | }, 1864 | "path-key": { 1865 | "version": "3.1.1", 1866 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1867 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1868 | "dev": true 1869 | }, 1870 | "path-type": { 1871 | "version": "4.0.0", 1872 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 1873 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 1874 | "dev": true 1875 | }, 1876 | "picomatch": { 1877 | "version": "2.3.0", 1878 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", 1879 | "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", 1880 | "dev": true 1881 | }, 1882 | "pkg-dir": { 1883 | "version": "4.2.0", 1884 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 1885 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 1886 | "dev": true, 1887 | "requires": { 1888 | "find-up": "^4.0.0" 1889 | } 1890 | }, 1891 | "prelude-ls": { 1892 | "version": "1.2.1", 1893 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", 1894 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", 1895 | "dev": true 1896 | }, 1897 | "prettier": { 1898 | "version": "2.3.2", 1899 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz", 1900 | "integrity": "sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==", 1901 | "dev": true 1902 | }, 1903 | "prettier-linter-helpers": { 1904 | "version": "1.0.0", 1905 | "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", 1906 | "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", 1907 | "dev": true, 1908 | "requires": { 1909 | "fast-diff": "^1.1.2" 1910 | } 1911 | }, 1912 | "process-on-spawn": { 1913 | "version": "1.0.0", 1914 | "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", 1915 | "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", 1916 | "dev": true, 1917 | "requires": { 1918 | "fromentries": "^1.2.0" 1919 | } 1920 | }, 1921 | "progress": { 1922 | "version": "2.0.3", 1923 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1924 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1925 | "dev": true 1926 | }, 1927 | "punycode": { 1928 | "version": "2.1.1", 1929 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1930 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1931 | "dev": true 1932 | }, 1933 | "queue-microtask": { 1934 | "version": "1.2.3", 1935 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", 1936 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", 1937 | "dev": true 1938 | }, 1939 | "regexpp": { 1940 | "version": "3.2.0", 1941 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", 1942 | "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", 1943 | "dev": true 1944 | }, 1945 | "release-zalgo": { 1946 | "version": "1.0.0", 1947 | "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", 1948 | "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", 1949 | "dev": true, 1950 | "requires": { 1951 | "es6-error": "^4.0.1" 1952 | } 1953 | }, 1954 | "require-directory": { 1955 | "version": "2.1.1", 1956 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1957 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1958 | "dev": true 1959 | }, 1960 | "require-from-string": { 1961 | "version": "2.0.2", 1962 | "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", 1963 | "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", 1964 | "dev": true 1965 | }, 1966 | "require-main-filename": { 1967 | "version": "2.0.0", 1968 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 1969 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 1970 | "dev": true 1971 | }, 1972 | "resolve-from": { 1973 | "version": "4.0.0", 1974 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1975 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1976 | "dev": true 1977 | }, 1978 | "reusify": { 1979 | "version": "1.0.4", 1980 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 1981 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 1982 | "dev": true 1983 | }, 1984 | "rimraf": { 1985 | "version": "3.0.2", 1986 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1987 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1988 | "dev": true, 1989 | "requires": { 1990 | "glob": "^7.1.3" 1991 | } 1992 | }, 1993 | "run-parallel": { 1994 | "version": "1.2.0", 1995 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", 1996 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", 1997 | "dev": true, 1998 | "requires": { 1999 | "queue-microtask": "^1.2.2" 2000 | } 2001 | }, 2002 | "sade": { 2003 | "version": "1.7.4", 2004 | "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz", 2005 | "integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==", 2006 | "dev": true, 2007 | "requires": { 2008 | "mri": "^1.1.0" 2009 | } 2010 | }, 2011 | "safe-buffer": { 2012 | "version": "5.1.2", 2013 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 2014 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 2015 | "dev": true 2016 | }, 2017 | "semver": { 2018 | "version": "7.3.5", 2019 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", 2020 | "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", 2021 | "dev": true, 2022 | "requires": { 2023 | "lru-cache": "^6.0.0" 2024 | } 2025 | }, 2026 | "set-blocking": { 2027 | "version": "2.0.0", 2028 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 2029 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 2030 | "dev": true 2031 | }, 2032 | "shebang-command": { 2033 | "version": "2.0.0", 2034 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2035 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2036 | "dev": true, 2037 | "requires": { 2038 | "shebang-regex": "^3.0.0" 2039 | } 2040 | }, 2041 | "shebang-regex": { 2042 | "version": "3.0.0", 2043 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2044 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2045 | "dev": true 2046 | }, 2047 | "signal-exit": { 2048 | "version": "3.0.3", 2049 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 2050 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", 2051 | "dev": true 2052 | }, 2053 | "slash": { 2054 | "version": "3.0.0", 2055 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 2056 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 2057 | "dev": true 2058 | }, 2059 | "slice-ansi": { 2060 | "version": "4.0.0", 2061 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", 2062 | "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", 2063 | "dev": true, 2064 | "requires": { 2065 | "ansi-styles": "^4.0.0", 2066 | "astral-regex": "^2.0.0", 2067 | "is-fullwidth-code-point": "^3.0.0" 2068 | } 2069 | }, 2070 | "source-map": { 2071 | "version": "0.5.7", 2072 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 2073 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", 2074 | "dev": true 2075 | }, 2076 | "spawn-wrap": { 2077 | "version": "2.0.0", 2078 | "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", 2079 | "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", 2080 | "dev": true, 2081 | "requires": { 2082 | "foreground-child": "^2.0.0", 2083 | "is-windows": "^1.0.2", 2084 | "make-dir": "^3.0.0", 2085 | "rimraf": "^3.0.0", 2086 | "signal-exit": "^3.0.2", 2087 | "which": "^2.0.1" 2088 | } 2089 | }, 2090 | "sprintf-js": { 2091 | "version": "1.0.3", 2092 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2093 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 2094 | "dev": true 2095 | }, 2096 | "string-width": { 2097 | "version": "4.2.2", 2098 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", 2099 | "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", 2100 | "dev": true, 2101 | "requires": { 2102 | "emoji-regex": "^8.0.0", 2103 | "is-fullwidth-code-point": "^3.0.0", 2104 | "strip-ansi": "^6.0.0" 2105 | } 2106 | }, 2107 | "strip-ansi": { 2108 | "version": "6.0.0", 2109 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2110 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2111 | "dev": true, 2112 | "requires": { 2113 | "ansi-regex": "^5.0.0" 2114 | } 2115 | }, 2116 | "strip-bom": { 2117 | "version": "4.0.0", 2118 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", 2119 | "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", 2120 | "dev": true 2121 | }, 2122 | "strip-json-comments": { 2123 | "version": "3.1.1", 2124 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2125 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2126 | "dev": true 2127 | }, 2128 | "supports-color": { 2129 | "version": "7.2.0", 2130 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2131 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2132 | "dev": true, 2133 | "requires": { 2134 | "has-flag": "^4.0.0" 2135 | } 2136 | }, 2137 | "table": { 2138 | "version": "6.7.1", 2139 | "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", 2140 | "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", 2141 | "dev": true, 2142 | "requires": { 2143 | "ajv": "^8.0.1", 2144 | "lodash.clonedeep": "^4.5.0", 2145 | "lodash.truncate": "^4.4.2", 2146 | "slice-ansi": "^4.0.0", 2147 | "string-width": "^4.2.0", 2148 | "strip-ansi": "^6.0.0" 2149 | }, 2150 | "dependencies": { 2151 | "ajv": { 2152 | "version": "8.6.2", 2153 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", 2154 | "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", 2155 | "dev": true, 2156 | "requires": { 2157 | "fast-deep-equal": "^3.1.1", 2158 | "json-schema-traverse": "^1.0.0", 2159 | "require-from-string": "^2.0.2", 2160 | "uri-js": "^4.2.2" 2161 | } 2162 | }, 2163 | "json-schema-traverse": { 2164 | "version": "1.0.0", 2165 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", 2166 | "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", 2167 | "dev": true 2168 | } 2169 | } 2170 | }, 2171 | "test-exclude": { 2172 | "version": "6.0.0", 2173 | "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", 2174 | "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", 2175 | "dev": true, 2176 | "requires": { 2177 | "@istanbuljs/schema": "^0.1.2", 2178 | "glob": "^7.1.4", 2179 | "minimatch": "^3.0.4" 2180 | } 2181 | }, 2182 | "text-table": { 2183 | "version": "0.2.0", 2184 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2185 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 2186 | "dev": true 2187 | }, 2188 | "to-fast-properties": { 2189 | "version": "2.0.0", 2190 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", 2191 | "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", 2192 | "dev": true 2193 | }, 2194 | "to-regex-range": { 2195 | "version": "5.0.1", 2196 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2197 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2198 | "dev": true, 2199 | "requires": { 2200 | "is-number": "^7.0.0" 2201 | } 2202 | }, 2203 | "totalist": { 2204 | "version": "2.0.0", 2205 | "resolved": "https://registry.npmjs.org/totalist/-/totalist-2.0.0.tgz", 2206 | "integrity": "sha512-+Y17F0YzxfACxTyjfhnJQEe7afPA0GSpYlFkl2VFMxYP7jshQf9gXV7cH47EfToBumFThfKBvfAcoUn6fdNeRQ==", 2207 | "dev": true 2208 | }, 2209 | "ts-node": { 2210 | "version": "10.2.1", 2211 | "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.2.1.tgz", 2212 | "integrity": "sha512-hCnyOyuGmD5wHleOQX6NIjJtYVIO8bPP8F2acWkB4W06wdlkgyvJtubO/I9NkI88hCFECbsEgoLc0VNkYmcSfw==", 2213 | "dev": true, 2214 | "requires": { 2215 | "@cspotcode/source-map-support": "0.6.1", 2216 | "@tsconfig/node10": "^1.0.7", 2217 | "@tsconfig/node12": "^1.0.7", 2218 | "@tsconfig/node14": "^1.0.0", 2219 | "@tsconfig/node16": "^1.0.2", 2220 | "acorn": "^8.4.1", 2221 | "acorn-walk": "^8.1.1", 2222 | "arg": "^4.1.0", 2223 | "create-require": "^1.1.0", 2224 | "diff": "^4.0.1", 2225 | "make-error": "^1.1.1", 2226 | "yn": "3.1.1" 2227 | }, 2228 | "dependencies": { 2229 | "acorn": { 2230 | "version": "8.4.1", 2231 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", 2232 | "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", 2233 | "dev": true 2234 | } 2235 | } 2236 | }, 2237 | "tslib": { 2238 | "version": "1.14.1", 2239 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", 2240 | "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", 2241 | "dev": true 2242 | }, 2243 | "tsutils": { 2244 | "version": "3.21.0", 2245 | "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", 2246 | "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", 2247 | "dev": true, 2248 | "requires": { 2249 | "tslib": "^1.8.1" 2250 | } 2251 | }, 2252 | "type-check": { 2253 | "version": "0.4.0", 2254 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", 2255 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", 2256 | "dev": true, 2257 | "requires": { 2258 | "prelude-ls": "^1.2.1" 2259 | } 2260 | }, 2261 | "type-fest": { 2262 | "version": "0.20.2", 2263 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", 2264 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", 2265 | "dev": true 2266 | }, 2267 | "typedarray-to-buffer": { 2268 | "version": "3.1.5", 2269 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 2270 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 2271 | "dev": true, 2272 | "requires": { 2273 | "is-typedarray": "^1.0.0" 2274 | } 2275 | }, 2276 | "typescript": { 2277 | "version": "4.3.5", 2278 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", 2279 | "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", 2280 | "dev": true 2281 | }, 2282 | "uri-js": { 2283 | "version": "4.4.1", 2284 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", 2285 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", 2286 | "dev": true, 2287 | "requires": { 2288 | "punycode": "^2.1.0" 2289 | } 2290 | }, 2291 | "uuid": { 2292 | "version": "3.4.0", 2293 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", 2294 | "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", 2295 | "dev": true 2296 | }, 2297 | "uvu": { 2298 | "version": "0.5.1", 2299 | "resolved": "https://registry.npmjs.org/uvu/-/uvu-0.5.1.tgz", 2300 | "integrity": "sha512-JGxttnOGDFs77FaZ0yMUHIzczzQ5R1IlDeNW6Wymw6gAscwMdAffVOP6TlxLIfReZyK8tahoGwWZaTCJzNFDkg==", 2301 | "dev": true, 2302 | "requires": { 2303 | "dequal": "^2.0.0", 2304 | "diff": "^5.0.0", 2305 | "kleur": "^4.0.3", 2306 | "sade": "^1.7.3", 2307 | "totalist": "^2.0.0" 2308 | }, 2309 | "dependencies": { 2310 | "diff": { 2311 | "version": "5.0.0", 2312 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 2313 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 2314 | "dev": true 2315 | } 2316 | } 2317 | }, 2318 | "v8-compile-cache": { 2319 | "version": "2.3.0", 2320 | "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", 2321 | "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", 2322 | "dev": true 2323 | }, 2324 | "watchlist": { 2325 | "version": "0.2.3", 2326 | "resolved": "https://registry.npmjs.org/watchlist/-/watchlist-0.2.3.tgz", 2327 | "integrity": "sha512-xStuPg489QXZbRirnmIMo7OaKFnGkvTQn7tCUC/sVmVVEvDQQnnVl/k9D5yg3nXgpebgPHpfApBLHMpEbAqvSQ==", 2328 | "dev": true, 2329 | "requires": { 2330 | "mri": "^1.1.5" 2331 | } 2332 | }, 2333 | "which": { 2334 | "version": "2.0.2", 2335 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2336 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2337 | "dev": true, 2338 | "requires": { 2339 | "isexe": "^2.0.0" 2340 | } 2341 | }, 2342 | "which-module": { 2343 | "version": "2.0.0", 2344 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 2345 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 2346 | "dev": true 2347 | }, 2348 | "word-wrap": { 2349 | "version": "1.2.3", 2350 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 2351 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 2352 | "dev": true 2353 | }, 2354 | "wrap-ansi": { 2355 | "version": "6.2.0", 2356 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 2357 | "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 2358 | "dev": true, 2359 | "requires": { 2360 | "ansi-styles": "^4.0.0", 2361 | "string-width": "^4.1.0", 2362 | "strip-ansi": "^6.0.0" 2363 | } 2364 | }, 2365 | "wrappy": { 2366 | "version": "1.0.2", 2367 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2368 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2369 | "dev": true 2370 | }, 2371 | "write-file-atomic": { 2372 | "version": "3.0.3", 2373 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", 2374 | "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", 2375 | "dev": true, 2376 | "requires": { 2377 | "imurmurhash": "^0.1.4", 2378 | "is-typedarray": "^1.0.0", 2379 | "signal-exit": "^3.0.2", 2380 | "typedarray-to-buffer": "^3.1.5" 2381 | } 2382 | }, 2383 | "y18n": { 2384 | "version": "4.0.3", 2385 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", 2386 | "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", 2387 | "dev": true 2388 | }, 2389 | "yallist": { 2390 | "version": "4.0.0", 2391 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2392 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2393 | "dev": true 2394 | }, 2395 | "yargs": { 2396 | "version": "15.4.1", 2397 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", 2398 | "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", 2399 | "dev": true, 2400 | "requires": { 2401 | "cliui": "^6.0.0", 2402 | "decamelize": "^1.2.0", 2403 | "find-up": "^4.1.0", 2404 | "get-caller-file": "^2.0.1", 2405 | "require-directory": "^2.1.1", 2406 | "require-main-filename": "^2.0.0", 2407 | "set-blocking": "^2.0.0", 2408 | "string-width": "^4.2.0", 2409 | "which-module": "^2.0.0", 2410 | "y18n": "^4.0.0", 2411 | "yargs-parser": "^18.1.2" 2412 | } 2413 | }, 2414 | "yargs-parser": { 2415 | "version": "18.1.3", 2416 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", 2417 | "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", 2418 | "dev": true, 2419 | "requires": { 2420 | "camelcase": "^5.0.0", 2421 | "decamelize": "^1.2.0" 2422 | } 2423 | }, 2424 | "yn": { 2425 | "version": "3.1.1", 2426 | "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", 2427 | "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", 2428 | "dev": true 2429 | } 2430 | } 2431 | } 2432 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typesafe-utils", 3 | "version": "1.16.2", 4 | "description": "A few small typesafe utilities", 5 | "homepage": "https://github.com/ivanhofer/typesafe-utils", 6 | "repository": "https://github.com/ivanhofer/typesafe-utils", 7 | "author": "ivanhofer", 8 | "keywords": [ 9 | "typescript", 10 | "utilities", 11 | "lightweight", 12 | "small", 13 | "typesafe", 14 | "utils" 15 | ], 16 | "license": "MIT", 17 | "main": "lib/cjs/index.js", 18 | "module": "lib/esm/index.js", 19 | "files": [ 20 | "/lib" 21 | ], 22 | "types": "lib/esm/index.d.ts", 23 | "scripts": { 24 | "build": "tsc && tsc -p tsconfig-cjs.json", 25 | "lint": "eslint src", 26 | "lint:fix": "eslint src --fix", 27 | "test": "uvu -r ts-node/register src .*\\.test\\..*", 28 | "test:watch": "watchlist src -- npm test", 29 | "coverage": "nyc npm run test", 30 | "coverage:output-report": "nyc report > coverage-report.txt" 31 | }, 32 | "devDependencies": { 33 | "@istanbuljs/nyc-config-typescript": "^1.0.1", 34 | "@types/node": "^16.7.1", 35 | "@typescript-eslint/eslint-plugin": "^4.29.3", 36 | "@typescript-eslint/parser": "^4.29.3", 37 | "eslint": "^7.32.0", 38 | "eslint-config-prettier": "^8.3.0", 39 | "eslint-plugin-prettier": "^3.4.1", 40 | "nyc": "^15.1.0", 41 | "prettier": "^2.3.2", 42 | "ts-node": "^10.2.1", 43 | "typescript": "^4.3.5", 44 | "uvu": "^0.5.1", 45 | "watchlist": "^0.2.3" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/deepClone/deepClone.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import { deepClone } from './deepClone' 3 | import * as assert from 'uvu/assert' 4 | 5 | const test = suite('deepClone') 6 | 7 | const check = (toClone: T) => assert.equal(deepClone(toClone), toClone) 8 | 9 | // primitives --------------------------------------------------------------------------------------------------------- 10 | 11 | test('null', () => check(null)) 12 | 13 | test('undefined', () => check(undefined)) 14 | 15 | test('boolean true', () => check(true)) 16 | test('boolean false', () => check(false)) 17 | 18 | test('number 0', () => check(0)) 19 | test('number 1', () => check(1)) 20 | test('number -123', () => check(-123)) 21 | 22 | test('infinity', () => check(Infinity)) 23 | test('negativ infinity', () => check(-Infinity)) 24 | 25 | test('string', () => check('test')) 26 | test('string with spaces', () => check('this is a with some spaces')) 27 | 28 | // arrays ------------------------------------------------------------------------------------------------------------- 29 | 30 | test('empty array', () => check([])) 31 | test('array with single value', () => check([5])) 32 | test('array with multiple value', () => check([1, 5, 8])) 33 | test('array with mixed values', () => check([null, 'test', 3])) 34 | 35 | test('nested empty arrays', () => check([[[[]], []]])) 36 | test('nested arrays with values', () => check([[true], [123, [5]]])) 37 | 38 | // objects ------------------------------------------------------------------------------------------------------------ 39 | 40 | test('empty object', () => check({})) 41 | test('object with single attribute', () => check({ prop: 'test' })) 42 | test('object with multiple attributes', () => check({ a: 2, b: Infinity })) 43 | 44 | test('nested empty objects', () => check({ a: { b: { c: { d: {} } } } })) 45 | 46 | test.run() 47 | -------------------------------------------------------------------------------- /src/deepClone/deepClone.ts: -------------------------------------------------------------------------------- 1 | type ObjectEntriesType = [keyof T, T[keyof T]][] 2 | 3 | export const deepClone = (toClone: T): T => { 4 | if (!toClone || typeof toClone !== 'object') { 5 | return toClone 6 | } 7 | 8 | if (Array.isArray(toClone)) { 9 | return ([...((toClone as unknown) as T[])].map(deepClone) as unknown) as T 10 | } 11 | 12 | return (>Object.entries(toClone)).reduce( 13 | (obj, [key, value]) => ({ ...obj, [key]: deepClone(value) }), 14 | {} as T, 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /src/filter/filter.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { createFilter } from './filter' 4 | 5 | const test = suite('filter') 6 | 7 | // filter --------------------------------------------------------------------------------------------------- 8 | 9 | test(`filter for 1`, () => { 10 | const items = [1, 2, 3, 5, 8, 1] 11 | const filterFor1 = createFilter<1, number>((item) => item === 1) 12 | const filteredItems = items.filter(filterFor1) 13 | 14 | assert.ok(filteredItems.length === 2) 15 | }) 16 | 17 | test(`filter for id not null`, () => { 18 | type T = { id: number | null } 19 | const item1: T = { id: 1 } 20 | const item2: T = { id: null } 21 | const items = [item1, item2, item1] 22 | const filterForIdNotNull = createFilter<{ id: number }, T>((item) => item.id !== null) 23 | const filteredItems = items.filter(filterForIdNotNull) 24 | 25 | assert.ok(filteredItems.length === 2) 26 | assert.ok(filteredItems.includes(item1 as any)) 27 | }) 28 | 29 | test.run() 30 | -------------------------------------------------------------------------------- /src/filter/filter.ts: -------------------------------------------------------------------------------- 1 | import { InferType } from '../types' 2 | 3 | type Filter = InputType extends ReturnType 4 | ? InputType 5 | : InputType extends unknown 6 | ? ReturnType 7 | : never 8 | 9 | export const createFilter = ( 10 | filterFn: (item: InferType) => boolean, 11 | ): InferType<(item: InferType) => item is Filter, InferType>> => 12 | filterFn as unknown as any 13 | -------------------------------------------------------------------------------- /src/filterDuplicates/filterDuplicates.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { filterDuplicates, filterDuplicatesByKey } from './filterDuplicates' 4 | 5 | const test = suite('filterDuplicates') 6 | 7 | // filterDuplicates --------------------------------------------------------------------------------------------------- 8 | 9 | test(`filter duplicate numbers`, () => { 10 | const items = [1, 2, 3, 5, 8, 1] 11 | const filteredItems = items.filter(filterDuplicates) 12 | 13 | assert.ok(filteredItems.length === 5) 14 | assert.ok(filteredItems.filter((nr) => nr === 1).length === 1) 15 | }) 16 | 17 | test(`filter duplicate objects`, () => { 18 | const item1 = { id: 1 } 19 | const item2 = { id: 2 } 20 | const items = [item1, item2, item1] 21 | const filteredItems = items.filter(filterDuplicates) 22 | 23 | assert.ok(filteredItems.length === 2) 24 | assert.ok(filteredItems.includes(item2)) 25 | assert.ok(filteredItems.filter((item) => item === item1).length === 1) 26 | }) 27 | 28 | // filterDuplicatesByKey ---------------------------------------------------------------------------------------------- 29 | 30 | test(`filter duplicate IDs`, () => { 31 | const items = [{ id: 1 }, { id: 2 }, { id: 1 }] 32 | const filteredItems = items.filter(filterDuplicatesByKey('id')) 33 | 34 | assert.ok(filteredItems.length === 2) 35 | assert.ok(filteredItems.filter(({ id }) => id === 1).length === 1) 36 | }) 37 | 38 | test(`filter duplicate names`, () => { 39 | const items = [ 40 | { id: 1, name: 'name-1' }, 41 | { id: 2, name: 'name-2' }, 42 | { id: 3, name: 'name-1' }, 43 | { id: 4, name: 'name-2' }, 44 | ] 45 | const filteredItems = items.filter(filterDuplicatesByKey('name')) 46 | 47 | assert.ok(filteredItems.length === 2) 48 | assert.ok(filteredItems.filter(({ name }) => name === 'name-1').length === 1) 49 | const item2 = filteredItems.find(({ name }) => name === 'name-2') 50 | assert.ok(item2 && item2.id === 2) 51 | }) 52 | 53 | test.run() 54 | -------------------------------------------------------------------------------- /src/filterDuplicates/filterDuplicates.ts: -------------------------------------------------------------------------------- 1 | export const filterDuplicates = (value: T, i: number, a: T[]): boolean => a.findIndex((t) => t === value) === i 2 | 3 | export const filterDuplicatesByKey = (key: K) => ( 4 | value: T, 5 | i: number, 6 | a: T[], 7 | ): boolean => a.findIndex((t) => t[key] === value[key]) === i 8 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export type { TypeGuard, TypeGuardWithReturnType, TypeGuardInverted, TypeGuardInvertedWithReturnType } from './types' 2 | export type { Truthy, Falsy } from './isTruthy/isTruthy' 3 | 4 | export { deepClone } from './deepClone/deepClone' 5 | 6 | export { createFilter } from './filter/filter' 7 | 8 | export { filterDuplicates, filterDuplicatesByKey } from './filterDuplicates/filterDuplicates' 9 | 10 | export { is, isNot, isProperty, isPropertyNot } from './is/is' 11 | 12 | export { isArray, isArrayEmpty, isArrayNotEmpty } from './isArray/isArray' 13 | 14 | export { 15 | isEmpty, 16 | isNotEmpty, 17 | isPropertyEmpty, 18 | isPropertyNotEmpty, 19 | arePropertiesEmpty, 20 | arePropertiesNotEmpty, 21 | } from './isEmpty/isEmpty' 22 | 23 | export { 24 | isFalse, 25 | isNotFalse, 26 | isPropertyFalse, 27 | isPropertyNotFalse, 28 | arePropertiesFalse, 29 | arePropertiesNotFalse, 30 | } from './isFalse/isFalse' 31 | 32 | export { 33 | isNull, 34 | isNotNull, 35 | isPropertyNull, 36 | isPropertyNotNull, 37 | arePropertiesNull, 38 | arePropertiesNotNull, 39 | } from './isNull/isNull' 40 | 41 | export { 42 | isTrue, 43 | isNotTrue, 44 | isPropertyTrue, 45 | isPropertyNotTrue, 46 | arePropertiesTrue, 47 | arePropertiesNotTrue, 48 | } from './isTrue/isTrue' 49 | 50 | export { 51 | isTruthy, 52 | isFalsy, 53 | isPropertyTruthy, 54 | isPropertyFalsy, 55 | arePropertiesTruthy, 56 | arePropertiesFalsy, 57 | } from './isTruthy/isTruthy' 58 | 59 | export { 60 | isUndefined, 61 | isNotUndefined, 62 | isPropertyUndefined, 63 | isPropertyNotUndefined, 64 | arePropertiesUndefined, 65 | arePropertiesNotUndefined, 66 | } from './isUndefined/isUndefined' 67 | 68 | export { 69 | isZero, 70 | isNotZero, 71 | isPropertyZero, 72 | isPropertyNotZero, 73 | arePropertiesZero, 74 | arePropertiesNotZero, 75 | } from './isZero/isZero' 76 | 77 | export { isObject, isPrimitiveObject } from './isObject/isObject' 78 | 79 | export { isString } from './isString/isString' 80 | 81 | export { isNumber } from './isNumber/isNumber' 82 | 83 | export { isBoolean } from './isBoolean/isBoolean' 84 | 85 | export { and, or, not } from './logical/logical' 86 | 87 | export { pick } from './pick/pick' 88 | 89 | export { 90 | sortNumberASC, 91 | sortNumberDESC, 92 | sortNumberPropertyASC, 93 | sortNumberPropertyDESC, 94 | sortStringASC, 95 | sortStringDESC, 96 | sortStringPropertyASC, 97 | sortStringPropertyDESC, 98 | sortDateASC, 99 | sortDateDESC, 100 | sortDatePropertyASC, 101 | sortDatePropertyDESC, 102 | } from './sorting/sorting' 103 | 104 | export { uniqueArray } from './uniqueArray/uniqueArray' 105 | -------------------------------------------------------------------------------- /src/is/is.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { is, isNot, isProperty, isPropertyNot } from './is' 4 | 5 | const test = suite('is') 6 | 7 | // is ----------------------------------------------------------------------------------------------------------------- 8 | 9 | test(`is 5`, () => { 10 | const items = [1, 5, 8, 5, 33] 11 | const filteredItems = items.filter(is(5)) 12 | 13 | assert.ok(filteredItems.length === 2) 14 | }) 15 | 16 | // isNot -------------------------------------------------------------------------------------------------------------- 17 | 18 | test(`isNot 'text'`, () => { 19 | const items = ['text', 'another-text', null, ''] 20 | const filteredItems = items.filter(isNot('text')) 21 | 22 | assert.ok(filteredItems.length === 3) 23 | }) 24 | 25 | // isProperty --------------------------------------------------------------------------------------------------------- 26 | 27 | test(`isProperty id 42`, () => { 28 | const items = [{ id: 46 }, { id: 42 }, { id: undefined }] 29 | const filteredItems = items.filter(isProperty('id', 42)) 30 | 31 | assert.ok(filteredItems.length === 1) 32 | }) 33 | 34 | // isPropertyNot ------------------------------------------------------------------------------------------------------ 35 | 36 | test(`isPropertyNot id null`, () => { 37 | const items = [{ id: 1 }, { id: null }, { id: undefined }] 38 | const filteredItems = items.filter(isPropertyNot('id', null)) 39 | 40 | assert.ok(filteredItems.length === 2) 41 | }) 42 | 43 | test.run() 44 | -------------------------------------------------------------------------------- /src/is/is.ts: -------------------------------------------------------------------------------- 1 | import { TypeGuard } from '../types' 2 | 3 | export const is = (item: T) => (value: U): value is TypeGuard => value === item 4 | 5 | export const isNot = (item: T) => (value: U): value is U => value !== item 6 | 7 | export const isProperty = (property: K, item: T[K]) => (value: T): boolean => 8 | value[property] === item 9 | 10 | export const isPropertyNot = (property: K, item: T[K]) => (value: T): boolean => 11 | value[property] !== item 12 | -------------------------------------------------------------------------------- /src/isArray/isArray.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { isArray, isArrayEmpty, isArrayNotEmpty } from './isArray' 4 | 5 | const test = suite('isArray') 6 | 7 | // isArray ------------------------------------------------------------------------------------------------------------ 8 | 9 | const items = ['test', { prop: 0 }, null, undefined, true, {}, [123, 77], 0, 123, false, '', []] 10 | 11 | test(`isArray`, () => { 12 | const filteredItems = items.filter(isArray) 13 | 14 | assert.ok(filteredItems.length === 2) 15 | assert.ok(filteredItems[0] && filteredItems[0].length === 2) 16 | assert.ok(filteredItems[1] && filteredItems[1].length === 0) 17 | }) 18 | 19 | const onlyArrays = items.filter(isArray) 20 | onlyArrays[0] && onlyArrays[0][0] && onlyArrays[0][0].toFixed() 21 | 22 | // isArrayEmpty ------------------------------------------------------------------------------------------------------- 23 | 24 | test(`isArrayEmpty`, () => { 25 | assert.equal(isArrayEmpty([]), true) 26 | assert.equal(isArrayEmpty([123, 123]), false) 27 | }) 28 | 29 | const emptyArray: string[] = [] 30 | if (isArrayEmpty(emptyArray)) { 31 | emptyArray.length === 0 32 | } 33 | 34 | // isArrayNotEmpty ---------------------------------------------------------------------------------------------------- 35 | 36 | test(`isArrayNotEmpty`, () => { 37 | assert.equal(isArrayNotEmpty([]), false) 38 | assert.equal(isArrayNotEmpty([123, 123]), true) 39 | }) 40 | 41 | const nonEmptyArray = ['hi'] 42 | if (isArrayNotEmpty(nonEmptyArray)) { 43 | nonEmptyArray[0].toUpperCase() 44 | } 45 | 46 | test.run() 47 | -------------------------------------------------------------------------------- /src/isArray/isArray.ts: -------------------------------------------------------------------------------- 1 | 2 | export type TypeGuard = Type extends Guard ? Type extends ReturnType ? Type : ReturnType : never 3 | 4 | export const isArray = (value: T): value is TypeGuard, T> => Array.isArray(value) 5 | 6 | type NotEmptyArray = [T, ...T[]] 7 | 8 | export const isArrayNotEmpty = (array: T[]): array is NotEmptyArray => !!array?.length 9 | 10 | export const isArrayEmpty = (array: T[]): array is [] => !array?.length 11 | -------------------------------------------------------------------------------- /src/isBoolean/isBoolean.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { isBoolean } from './isBoolean' 4 | 5 | const test = suite('isBoolean') 6 | 7 | // isBoolean ---------------------------------------------------------------------------------------------------------- 8 | 9 | const items = ['test', { prop: 0 }, null, undefined, true, {}, 0, 123, false, ''] 10 | 11 | test(`isBoolean`, () => { 12 | const filteredItems = items.filter(isBoolean) 13 | 14 | assert.ok(filteredItems.length === 2) 15 | assert.is(filteredItems[0], true) 16 | assert.is(filteredItems[1], false) 17 | }) 18 | 19 | const onlyBooleans = items.filter(isBoolean) 20 | onlyBooleans[0] && onlyBooleans[0] === true 21 | 22 | test.run() 23 | -------------------------------------------------------------------------------- /src/isBoolean/isBoolean.ts: -------------------------------------------------------------------------------- 1 | import { TypeGuard } from '../types' 2 | 3 | export const isBoolean = (value: T): value is TypeGuard => typeof value === 'boolean' 4 | -------------------------------------------------------------------------------- /src/isEmpty/isEmpty.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { Everything } from '../types' 4 | 5 | import { 6 | arePropertiesEmpty, 7 | arePropertiesNotEmpty, 8 | isEmpty, 9 | isNotEmpty, 10 | isPropertyEmpty, 11 | isPropertyNotEmpty, 12 | } from './isEmpty' 13 | 14 | const test = suite('empty') 15 | 16 | const emptyValues = [''] 17 | const notEmptyValues = [-Infinity, -1, 1, Infinity, 'test', true, [], {}, undefined, null, 0, false] 18 | 19 | // isEmpty ------------------------------------------------------------------------------------------------------------ 20 | 21 | emptyValues.forEach((value) => test(`isEmpty ${value}`, () => assert.ok(isEmpty(value)))) 22 | notEmptyValues.forEach((value) => test(`! isEmpty ${value}`, () => assert.not(isEmpty(value)))) 23 | 24 | const _emptyType: ''[] = [...emptyValues, notEmptyValues].filter(isEmpty) 25 | const _neverType: never[] = notEmptyValues.filter(isEmpty) 26 | 27 | // isNotEmpty --------------------------------------------------------------------------------------------------------- 28 | 29 | notEmptyValues.forEach((value) => test(`isNotEmpty ${value}`, () => assert.ok(isNotEmpty(value)))) 30 | emptyValues.forEach((value) => test(`! isNotEmpty ${value}`, () => assert.not(isNotEmpty(value)))) 31 | 32 | const _allNotType: Exclude[] = [...emptyValues, ...notEmptyValues].filter(isNotEmpty) 33 | const _neverNotType: never[] = emptyValues.filter(isNotEmpty) 34 | 35 | // isPropertyEmpty ---------------------------------------------------------------------------------------------------- 36 | 37 | test(`isPropertyEmpty name`, () => { 38 | const items = [{ name: 'name-1' }, { name: '' }, { name: undefined }] 39 | const filteredItems = items.filter(isPropertyEmpty('name')) 40 | 41 | assert.ok(filteredItems.length === 1) 42 | }) 43 | 44 | // isPropertyNotEmpty ------------------------------------------------------------------------------------------------- 45 | 46 | test(`isPropertyNotEmpty name`, () => { 47 | const items = [{ name: null }, { name: 'name-2' }, { name: '' }] 48 | const filteredItems = items.filter(isPropertyNotEmpty('name')) 49 | 50 | assert.ok(filteredItems.length === 2) 51 | }) 52 | 53 | // arePropertiesEmpty ------------------------------------------------------------------------------------------------- 54 | 55 | test(`arePropertiesEmpty name role`, () => { 56 | const items = [ 57 | { name: 'name-1', role: 'ADMIN' }, 58 | { name: 'name-1', role: '' }, 59 | { name: '', role: '' }, 60 | { name: '', role: 'ADMIN' }, 61 | ] 62 | const filteredItems = items.filter(arePropertiesEmpty('name', 'role')) 63 | 64 | assert.ok(filteredItems.length === 1) 65 | }) 66 | 67 | // arePropertiesNotEmpty ---------------------------------------------------------------------------------------------- 68 | 69 | test(`arePropertiesEmpty name role`, () => { 70 | const items = [ 71 | { name: 'name-1', role: 'ADMIN' }, 72 | { name: 'name-1', role: '' }, 73 | { name: '', role: '' }, 74 | { name: '', role: 'ADMIN' }, 75 | ] 76 | const filteredItems = items.filter(arePropertiesNotEmpty('name', 'role')) 77 | 78 | assert.ok(filteredItems.length === 1) 79 | }) 80 | 81 | test.run() 82 | -------------------------------------------------------------------------------- /src/isEmpty/isEmpty.ts: -------------------------------------------------------------------------------- 1 | import { TypeGuard, TypeGuardWithReturnType, TypeGuardInverted } from '../types' 2 | 3 | export const isEmpty = (value: T | ''): value is TypeGuardWithReturnType => value === '' 4 | 5 | export const isNotEmpty = (value: T): value is TypeGuardInverted => value !== '' 6 | 7 | export const isPropertyEmpty = (property: K) => (value: T): boolean => 8 | value[property] === '' 9 | 10 | export const isPropertyNotEmpty = (property: K) => (value: T): boolean => 11 | value[property] !== '' 12 | 13 | export const arePropertiesEmpty = (...properties: K[]) => (value: T): boolean => 14 | properties.every((property) => value[property] === '') 15 | 16 | export const arePropertiesNotEmpty = (...properties: K[]) => (value: T): boolean => 17 | properties.every((property) => value[property] !== '') 18 | -------------------------------------------------------------------------------- /src/isFalse/isFalse.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { Everything } from '../types' 4 | 5 | import { 6 | arePropertiesFalse, 7 | arePropertiesNotFalse, 8 | isFalse, 9 | isNotFalse, 10 | isPropertyFalse, 11 | isPropertyNotFalse, 12 | } from './isFalse' 13 | 14 | const test = suite('false') 15 | 16 | const falseValues = [false] 17 | const notFalseValues = [-Infinity, -1, 1, Infinity, 'test', true, [], {}, undefined, null, 0, ''] 18 | 19 | // isFalse ------------------------------------------------------------------------------------------------------------ 20 | 21 | falseValues.forEach((value) => test(`isFalse ${value}`, () => assert.ok(isFalse(value)))) 22 | notFalseValues.forEach((value) => test(`! isFalse ${value}`, () => assert.not(isFalse(value)))) 23 | 24 | const _falseType: false[] = [...falseValues, notFalseValues].filter(isFalse) 25 | const _neverType: never[] = notFalseValues.filter(isFalse) 26 | 27 | // isNotFalse --------------------------------------------------------------------------------------------------------- 28 | 29 | notFalseValues.forEach((value) => test(`isNotFalse ${value}`, () => assert.ok(isNotFalse(value)))) 30 | falseValues.forEach((value) => test(`! isNotFalse ${value}`, () => assert.not(isNotFalse(value)))) 31 | 32 | const _allNotType: Exclude[] = [...falseValues, ...notFalseValues].filter(isNotFalse) 33 | // const _neverNotType: never[] = falseValues.filter(isNotFalse) 34 | 35 | // isPropertyFalse ---------------------------------------------------------------------------------------------------- 36 | 37 | test(`isPropertyTrue available`, () => { 38 | const items = [{ available: false }, { available: '' }, { available: undefined }] 39 | const filteredItems = items.filter(isPropertyFalse('available')) 40 | 41 | assert.ok(filteredItems.length === 1) 42 | }) 43 | 44 | // isPropertyNotFalse ------------------------------------------------------------------------------------------------- 45 | 46 | test(`isPropertyNotFalse available`, () => { 47 | const items = [{ available: false }, { available: true }, { available: null }] 48 | const filteredItems = items.filter(isPropertyNotFalse('available')) 49 | 50 | assert.ok(filteredItems.length === 2) 51 | }) 52 | 53 | // arePropertiesFalse ------------------------------------------------------------------------------------------------- 54 | 55 | test(`arePropertiesFalse available inStock`, () => { 56 | const items = [ 57 | { available: true, inStock: false }, 58 | { available: false, inStock: false }, 59 | { available: true, inStock: true }, 60 | { available: null, inStock: false }, 61 | ] 62 | const filteredItems = items.filter(arePropertiesFalse('available', 'inStock')) 63 | 64 | assert.ok(filteredItems.length === 1) 65 | }) 66 | 67 | // arePropertiesNotFalse ---------------------------------------------------------------------------------------------- 68 | 69 | test(`arePropertiesNotFalse available inStock`, () => { 70 | const items = [ 71 | { available: true, inStock: false }, 72 | { available: false, inStock: false }, 73 | { available: true, inStock: true }, 74 | { available: null, inStock: true }, 75 | ] 76 | const filteredItems = items.filter(arePropertiesNotFalse('available', 'inStock')) 77 | 78 | assert.ok(filteredItems.length === 2) 79 | }) 80 | 81 | test.run() 82 | -------------------------------------------------------------------------------- /src/isFalse/isFalse.ts: -------------------------------------------------------------------------------- 1 | import { TypeGuard, TypeGuardInverted } from '../types' 2 | 3 | export const isFalse = (value: T): value is TypeGuard => value === false 4 | 5 | export const isNotFalse = (value: T): value is TypeGuardInverted => value !== false 6 | 7 | export const isPropertyFalse = (property: K) => (value: T): boolean => 8 | value[property] === false 9 | 10 | export const isPropertyNotFalse = (property: K) => (value: T): boolean => 11 | value[property] !== false 12 | 13 | export const arePropertiesFalse = (...properties: K[]) => (value: T): boolean => 14 | properties.every((property) => value[property] === false) 15 | 16 | export const arePropertiesNotFalse = (...properties: K[]) => (value: T): boolean => 17 | properties.every((property) => value[property] !== false) 18 | -------------------------------------------------------------------------------- /src/isNull/isNull.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | 4 | import { isNull, isNotNull, isPropertyNull, isPropertyNotNull, arePropertiesNotNull, arePropertiesNull } from './isNull' 5 | 6 | const test = suite('null') 7 | 8 | const nullValues = [null] 9 | const notNullValues = [-Infinity, -1, 1, Infinity, 'test', true, [], {}, undefined, 0, '', false] 10 | 11 | // isNull ------------------------------------------------------------------------------------------------------------- 12 | 13 | nullValues.forEach((value) => test(`isNull ${value}`, () => assert.ok(isNull(value)))) 14 | notNullValues.forEach((value) => test(`! isNull ${value}`, () => assert.not(isNull(value)))) 15 | 16 | const _nullType: null[] = [...nullValues, notNullValues].filter(isNull) 17 | const _neverType: never[] = notNullValues.filter(isNull) 18 | 19 | // isNotNull ---------------------------------------------------------------------------------------------------------- 20 | 21 | notNullValues.forEach((value) => test(`isNotNull ${value}`, () => assert.ok(isNotNull(value)))) 22 | nullValues.forEach((value) => test(`! isNotNull ${value}`, () => assert.not(isNotNull(value)))) 23 | 24 | const _allNotType: ({} | undefined)[] = [...nullValues, ...notNullValues].filter(isNotNull) 25 | const _neverNotType: never[] = nullValues.filter(isNotNull) 26 | 27 | // isPropertyNull ----------------------------------------------------------------------------------------------------- 28 | 29 | test(`isPropertyNotNull id`, () => { 30 | const items = [{ id: 0 }, { id: undefined }, { id: null }] 31 | const filteredItems = items.filter(isPropertyNull('id')) 32 | 33 | assert.ok(filteredItems.length === 1) 34 | }) 35 | 36 | // isPropertyNotUndefined --------------------------------------------------------------------------------------------- 37 | 38 | test(`isPropertyNotNull id`, () => { 39 | const items = [{ id: undefined }, { id: 1 }, { id: null }] 40 | const filteredItems = items.filter(isPropertyNotNull('id')) 41 | 42 | assert.ok(filteredItems.length === 2) 43 | }) 44 | 45 | // arePropertiesNull -------------------------------------------------------------------------------------------------- 46 | 47 | test(`arePropertiesNull id name`, () => { 48 | const items = [ 49 | { id: null, name: 'name-1' }, 50 | { id: 0, name: null }, 51 | { id: undefined, name: 'name-1' }, 52 | { id: null, name: null }, 53 | ] 54 | const filteredItems = items.filter(arePropertiesNull('id', 'name')) 55 | 56 | assert.ok(filteredItems.length === 1) 57 | }) 58 | 59 | // arePropertiesNotNull --------------------------------------------------------------------------------------------- 60 | 61 | test(`arePropertiesNotNull id name`, () => { 62 | const items = [ 63 | { id: null, name: 'name-1' }, 64 | { id: 0, name: null }, 65 | { id: undefined, name: 'name-1' }, 66 | { id: null, name: null }, 67 | ] 68 | const filteredItems = items.filter(arePropertiesNotNull('id', 'name')) 69 | 70 | assert.ok(filteredItems.length === 1) 71 | }) 72 | 73 | test.run() 74 | -------------------------------------------------------------------------------- /src/isNull/isNull.ts: -------------------------------------------------------------------------------- 1 | import { TypeGuard, TypeGuardInverted } from '../types' 2 | 3 | export const isNull = (value: T): value is TypeGuard => value === null 4 | 5 | export const isNotNull = (value: T): value is TypeGuardInverted => value !== null 6 | 7 | export const isPropertyNull = (property: K) => (value: T): boolean => 8 | value[property] === null 9 | 10 | export const isPropertyNotNull = (property: K) => (value: T): boolean => 11 | value[property] !== null 12 | 13 | export const arePropertiesNull = (...properties: K[]) => (value: T): boolean => 14 | properties.every((property) => value[property] === null) 15 | 16 | export const arePropertiesNotNull = (...properties: K[]) => (value: T): boolean => 17 | properties.every((property) => value[property] !== null) 18 | -------------------------------------------------------------------------------- /src/isNumber/isNumber.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { isNumber } from './isNumber' 4 | 5 | const test = suite('isNumber') 6 | 7 | // isNumber ----------------------------------------------------------------------------------------------------------- 8 | 9 | const items = ['test', { prop: 0 }, null, undefined, true, {}, 0, 123, false, ''] 10 | 11 | test(`isNumber`, () => { 12 | const filteredItems = items.filter(isNumber) 13 | 14 | assert.ok(filteredItems.length === 2) 15 | assert.is(filteredItems[0], 0) 16 | assert.is(filteredItems[1], 123) 17 | }) 18 | 19 | const onlyNumbers = items.filter(isNumber) 20 | onlyNumbers[0] && onlyNumbers[0].toFixed() 21 | 22 | test.run() 23 | -------------------------------------------------------------------------------- /src/isNumber/isNumber.ts: -------------------------------------------------------------------------------- 1 | import { TypeGuard } from '../types' 2 | 3 | export const isNumber = (value: T): value is TypeGuard => typeof value === 'number' 4 | -------------------------------------------------------------------------------- /src/isObject/isObject.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { isObject, isPrimitiveObject } from './isObject' 4 | 5 | const test = suite('isObject') 6 | 7 | // isObject ----------------------------------------------------------------------------------------------------------- 8 | 9 | const now = new Date() 10 | const items = ['test', { prop: 0 } as SomeObject, null, undefined, true, {}, 0, 123, false, ''] 11 | 12 | type SomeObject = { 13 | prop?: number 14 | } 15 | 16 | test(`isObject`, () => { 17 | const filteredItems = [...items, now].filter(isObject) 18 | 19 | assert.ok(filteredItems.length === 3) 20 | assert.equal(filteredItems[0], { prop: 0 }) 21 | assert.equal(filteredItems[1], {}) 22 | assert.equal(filteredItems[2], now) 23 | }) 24 | 25 | test(`isPrimitiveObject`, () => { 26 | const filteredItems = items.filter(isPrimitiveObject) 27 | 28 | assert.ok(filteredItems.length === 2) 29 | assert.equal(filteredItems[0], { prop: 0 }) 30 | assert.equal(filteredItems[1], {}) 31 | }) 32 | 33 | const onlyObjects = items.filter(isPrimitiveObject) 34 | onlyObjects[0] && onlyObjects[0].prop 35 | 36 | test.run() 37 | -------------------------------------------------------------------------------- /src/isObject/isObject.ts: -------------------------------------------------------------------------------- 1 | import { TypeGuard } from '../types' 2 | 3 | export const isObject = (value: T): value is TypeGuard => value && typeof value === 'object' 4 | 5 | export const isPrimitiveObject = (value: T): value is TypeGuard => 6 | isObject(value) && ((value)).constructor === Object 7 | -------------------------------------------------------------------------------- /src/isString/isString.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { isString } from './isString' 4 | 5 | const test = suite('isString') 6 | 7 | // isString ----------------------------------------------------------------------------------------------------------- 8 | 9 | const items = ['test', { prop: 0 }, null, undefined, true, {}, 0, 123, false, ''] 10 | 11 | test(`isString`, () => { 12 | const filteredItems = items.filter(isString) 13 | 14 | assert.ok(filteredItems.length === 2) 15 | assert.is(filteredItems[0], 'test') 16 | assert.is(filteredItems[1], '') 17 | }) 18 | 19 | const onlyStrings = items.filter(isString) 20 | onlyStrings[0] && onlyStrings[0].toLowerCase() 21 | 22 | test.run() 23 | -------------------------------------------------------------------------------- /src/isString/isString.ts: -------------------------------------------------------------------------------- 1 | import { TypeGuard } from '../types' 2 | 3 | export const isString = (value: T): value is TypeGuard => typeof value === 'string' 4 | -------------------------------------------------------------------------------- /src/isTrue/isTrue.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { Everything } from '../types' 4 | 5 | import { isTrue, isNotTrue, isPropertyNotTrue, isPropertyTrue, arePropertiesTrue, arePropertiesNotTrue } from './isTrue' 6 | 7 | const test = suite('true') 8 | 9 | const trueValues = [true] 10 | const notTrueValues = [-Infinity, -1, 1, Infinity, 'test', [], {}, undefined, null, 0, '', false] 11 | 12 | // isTrue ------------------------------------------------------------------------------------------------------------- 13 | 14 | trueValues.forEach((value) => test(`isTrue ${value}`, () => assert.ok(isTrue(value)))) 15 | notTrueValues.forEach((value) => test(`! isTrue ${value}`, () => assert.not(isTrue(value)))) 16 | 17 | const _trueType: true[] = [...trueValues, notTrueValues].filter(isTrue) 18 | const _neverType: never[] = notTrueValues.filter(isTrue) 19 | 20 | // isNotTrue ---------------------------------------------------------------------------------------------------------- 21 | 22 | notTrueValues.forEach((value) => test(`isNotTrue ${value}`, () => assert.ok(isNotTrue(value)))) 23 | trueValues.forEach((value) => test(`! isNotTrue ${value}`, () => assert.not(isNotTrue(value)))) 24 | 25 | const _allNotType: Exclude[] = [...trueValues, ...notTrueValues].filter(isNotTrue) 26 | // const _neverNotType: never[] = trueValues.filter(isNotTrue) 27 | 28 | // isPropertyTrue ----------------------------------------------------------------------------------------------------- 29 | 30 | test(`isPropertyTrue available`, () => { 31 | const items = [{ available: true }, { available: 'some-id' }, { available: null }] 32 | const filteredItems = items.filter(isPropertyTrue('available')) 33 | 34 | assert.ok(filteredItems.length === 1) 35 | }) 36 | 37 | // isPropertyNotTrue -------------------------------------------------------------------------------------------------- 38 | 39 | test(`isPropertyNotTrue available`, () => { 40 | const items = [{ available: 0 }, { available: true }, { available: null }] 41 | const filteredItems = items.filter(isPropertyNotTrue('available')) 42 | 43 | assert.ok(filteredItems.length === 2) 44 | }) 45 | 46 | // arePropertiesTrue -------------------------------------------------------------------------------------------------- 47 | 48 | test(`arePropertiesTrue available inStock`, () => { 49 | const items = [ 50 | { available: 'some-id', inStock: true }, 51 | { available: true, inStock: true }, 52 | { available: 'some-id', inStock: false }, 53 | { available: null, inStock: true }, 54 | ] 55 | const filteredItems = items.filter(arePropertiesTrue('available', 'inStock')) 56 | 57 | assert.ok(filteredItems.length === 1) 58 | }) 59 | 60 | // arePropertiesNotTrue ----------------------------------------------------------------------------------------------- 61 | 62 | test(`arePropertiesNotTrue available inStock`, () => { 63 | const items = [ 64 | { available: 'some-id', inStock: true }, 65 | { available: true, inStock: true }, 66 | { available: 'some-id', inStock: false }, 67 | { available: null, inStock: true }, 68 | ] 69 | const filteredItems = items.filter(arePropertiesNotTrue('available', 'inStock')) 70 | 71 | assert.ok(filteredItems.length === 1) 72 | }) 73 | 74 | test.run() 75 | -------------------------------------------------------------------------------- /src/isTrue/isTrue.ts: -------------------------------------------------------------------------------- 1 | import { TypeGuard, TypeGuardInverted } from '../types' 2 | 3 | export const isTrue = (value: T): value is TypeGuard => value === true 4 | 5 | export const isNotTrue = (value: T): value is TypeGuardInverted => value !== true 6 | 7 | export const isPropertyTrue = (property: K) => (value: T): boolean => 8 | value[property] === true 9 | 10 | export const isPropertyNotTrue = (property: K) => (value: T): boolean => 11 | value[property] !== true 12 | 13 | export const arePropertiesTrue = (...properties: K[]) => (value: T): boolean => 14 | properties.every((property) => value[property] === true) 15 | 16 | export const arePropertiesNotTrue = (...properties: K[]) => (value: T): boolean => 17 | properties.every((property) => value[property] !== true) 18 | -------------------------------------------------------------------------------- /src/isTruthy/isTruthy.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | 4 | import { 5 | isTruthy, 6 | isFalsy, 7 | isPropertyTruthy, 8 | isPropertyFalsy, 9 | arePropertiesFalsy, 10 | arePropertiesTruthy, 11 | } from './isTruthy' 12 | 13 | const test = suite('truthy') 14 | 15 | const truthyValues = [-Infinity, -1, 1, Infinity, 'test', true, [], {}] 16 | const falsyValues = [undefined, null, 0, '', false] 17 | 18 | // isTruthy ----------------------------------------------------------------------------------------------------------- 19 | 20 | truthyValues.forEach((value) => test(`isTruthy ${value}`, () => assert.ok(isTruthy(value)))) 21 | falsyValues.forEach((value) => test(`! isTruthy ${value}`, () => assert.not(isTruthy(value)))) 22 | 23 | const _truthyType: {}[] = [...truthyValues, falsyValues].filter(isTruthy) 24 | const _notFalsyType: (string | number | true)[] = falsyValues.filter(isTruthy) 25 | 26 | // isFalsy ------------------------------------------------------------------------------------------------------------ 27 | 28 | falsyValues.forEach((value) => test(`isFalsy ${value}`, () => assert.ok(isFalsy(value)))) 29 | truthyValues.forEach((value) => test(`! isFalsy ${value}`, () => assert.not(isFalsy(value)))) 30 | 31 | // const _allNotType: (null | undefined | '' | 0 | false)[] = [...truthyValues, ...falsyValues].filter(isFalsy) 32 | const _neverNotType: never[] = truthyValues.filter(isFalsy) 33 | 34 | // isPropertyTruthy --------------------------------------------------------------------------------------------------- 35 | 36 | test(`isPropertyTruthy id`, () => { 37 | const items = [{ id: 0 }, { id: 1 }, { id: null }] 38 | const filteredItems = items.filter(isPropertyTruthy('id')) 39 | 40 | assert.ok(filteredItems.length === 1) 41 | }) 42 | 43 | // isPropertyFalsy ---------------------------------------------------------------------------------------------------- 44 | 45 | test(`isPropertyFalsy id`, () => { 46 | const items = [{ id: 0 }, { id: 1 }, { id: null }] 47 | const filteredItems = items.filter(isPropertyFalsy('id')) 48 | 49 | assert.ok(filteredItems.length === 2) 50 | }) 51 | 52 | // arePropertiesTruthy ------------------------------------------------------------------------------------------------ 53 | 54 | test(`arePropertiesTruthy id name`, () => { 55 | const items = [ 56 | { id: 0, name: 'name-1' }, 57 | { id: 1, name: '' }, 58 | { id: 1, name: 'name-1' }, 59 | { id: null, name: '' }, 60 | ] 61 | const filteredItems = items.filter(arePropertiesTruthy('id', 'name')) 62 | 63 | assert.ok(filteredItems.length === 1) 64 | }) 65 | 66 | // arePropertiesFalsy ------------------------------------------------------------------------------------------------- 67 | 68 | test(`arePropertiesFalsy id name`, () => { 69 | const items = [ 70 | { id: 0, name: 'name-1' }, 71 | { id: 1, name: '' }, 72 | { id: 1, name: 'name-1' }, 73 | { id: null, name: '' }, 74 | ] 75 | const filteredItems = items.filter(arePropertiesFalsy('id', 'name')) 76 | 77 | assert.ok(filteredItems.length === 1) 78 | }) 79 | 80 | test.run() 81 | -------------------------------------------------------------------------------- /src/isTruthy/isTruthy.ts: -------------------------------------------------------------------------------- 1 | import { FalsyType, TypeGuard, TypeGuardInverted } from '../types' 2 | 3 | export type Truthy = TypeGuardInverted 4 | 5 | export type Falsy = TypeGuard 6 | 7 | export const isTruthy = (value: T): value is Truthy => !!value 8 | 9 | export const isFalsy = (value: T): value is Falsy => !value 10 | 11 | export const isPropertyTruthy = (property: K) => (value: T): boolean => 12 | !!value[property] 13 | 14 | export const isPropertyFalsy = (property: K) => (value: T): boolean => !value[property] 15 | 16 | export const arePropertiesTruthy = (...properties: K[]) => (value: T): boolean => 17 | properties.every((property) => !!value[property]) 18 | 19 | export const arePropertiesFalsy = (...properties: K[]) => (value: T): boolean => 20 | properties.every((property) => !value[property]) 21 | -------------------------------------------------------------------------------- /src/isUndefined/isUndefined.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | 4 | import { 5 | isUndefined, 6 | isNotUndefined, 7 | isPropertyUndefined, 8 | isPropertyNotUndefined, 9 | arePropertiesUndefined, 10 | arePropertiesNotUndefined, 11 | } from './isUndefined' 12 | 13 | const test = suite('undefined') 14 | 15 | const undefinedValues: undefined[] = [undefined] 16 | const notUndefinedValues = [-Infinity, -1, 1, Infinity, 'test', true, [], {}, null, 0, '', false] 17 | 18 | // isUndefined -------------------------------------------------------------------------------------------------------- 19 | 20 | undefinedValues.forEach((value) => test(`isUndefined ${value}`, () => assert.ok(isUndefined(value)))) 21 | notUndefinedValues.forEach((value) => test(`! isUndefined ${value}`, () => assert.not(isUndefined(value)))) 22 | 23 | const _undefinedType: undefined[] = [...undefinedValues, notUndefinedValues].filter(isUndefined) 24 | const _neverType: never[] = notUndefinedValues.filter(isUndefined) 25 | 26 | // isNotUndefined ----------------------------------------------------------------------------------------------------- 27 | 28 | notUndefinedValues.forEach((value) => test(`isNotUndefined ${value}`, () => assert.ok(isNotUndefined(value)))) 29 | undefinedValues.forEach((value) => test(`! isNotUndefined ${value}`, () => assert.not(isNotUndefined(value)))) 30 | 31 | const _allNotType: ({} | null)[] = [...undefinedValues, ...notUndefinedValues].filter(isNotUndefined) 32 | const _neverNotType: never[] = undefinedValues.filter(isNotUndefined) 33 | 34 | // isPropertyUndefined ------------------------------------------------------------------------------------------------ 35 | 36 | test(`isPropertyUndefined id`, () => { 37 | const items = [{ id: 0 }, { id: undefined }, { id: null }] 38 | const filteredItems = items.filter(isPropertyUndefined('id')) 39 | 40 | assert.ok(filteredItems.length === 1) 41 | }) 42 | 43 | // isPropertyNotUndefined --------------------------------------------------------------------------------------------- 44 | 45 | test(`isPropertyNotUndefined id`, () => { 46 | const items = [{ id: undefined }, { id: 1 }, { id: null }] 47 | const filteredItems = items.filter(isPropertyNotUndefined('id')) 48 | 49 | assert.ok(filteredItems.length === 2) 50 | }) 51 | 52 | // arePropertiesUndefined --------------------------------------------------------------------------------------------- 53 | 54 | test(`arePropertiesUndefined id name`, () => { 55 | const items = [ 56 | { id: 0, name: undefined }, 57 | { id: 12, name: 'name-1' }, 58 | { id: undefined, name: undefined }, 59 | { id: null, name: undefined }, 60 | ] 61 | const filteredItems = items.filter(arePropertiesUndefined('id', 'name')) 62 | 63 | assert.ok(filteredItems.length === 1) 64 | }) 65 | 66 | // arePropertiesNotUndefined ------------------------------------------------------------------------------------------ 67 | 68 | test(`arePropertiesNotUndefined id name`, () => { 69 | const items = [ 70 | { id: 0, name: undefined }, 71 | { id: 12, name: 'name-1' }, 72 | { id: undefined, name: undefined }, 73 | { id: null, name: undefined }, 74 | ] 75 | const filteredItems = items.filter(arePropertiesNotUndefined('id', 'name')) 76 | 77 | assert.ok(filteredItems.length === 1) 78 | }) 79 | 80 | test.run() 81 | -------------------------------------------------------------------------------- /src/isUndefined/isUndefined.ts: -------------------------------------------------------------------------------- 1 | import { TypeGuard, TypeGuardInverted } from '../types' 2 | 3 | export const isUndefined = (value: T): value is TypeGuard => value === undefined 4 | 5 | export const isNotUndefined = (value: T): value is TypeGuardInverted => value !== undefined 6 | 7 | export const isPropertyUndefined = (property: K) => (value: T): boolean => 8 | value[property] === undefined 9 | 10 | export const isPropertyNotUndefined = (property: K) => (value: T): boolean => 11 | value[property] !== undefined 12 | 13 | export const arePropertiesUndefined = (...properties: K[]) => (value: T): boolean => 14 | properties.every((property) => value[property] === undefined) 15 | 16 | export const arePropertiesNotUndefined = (...properties: K[]) => (value: T): boolean => 17 | properties.every((property) => value[property] !== undefined) 18 | -------------------------------------------------------------------------------- /src/isZero/isZero.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { Everything } from '../types' 4 | import { isZero, isNotZero, isPropertyZero, isPropertyNotZero, arePropertiesNotZero, arePropertiesZero } from './isZero' 5 | 6 | const test = suite('zero') 7 | 8 | const zeroValues = [0] 9 | const notZeroValues = [-Infinity, -1, 1, Infinity, 'test', true, [], {}, undefined, null, '', false] 10 | 11 | // isZero ------------------------------------------------------------------------------------------------------------- 12 | 13 | zeroValues.forEach((value) => test(`isZero ${value}`, () => assert.ok(isZero(value)))) 14 | notZeroValues.forEach((value) => test(`! isZero ${value}`, () => assert.not(isZero(value)))) 15 | 16 | const _zeroType: 0[] = [...zeroValues, notZeroValues].filter(isZero) 17 | const _neverType: never[] = notZeroValues.filter(isZero) 18 | 19 | // isNotZero ---------------------------------------------------------------------------------------------------------- 20 | 21 | notZeroValues.forEach((value) => test(`isNotZero ${value}`, () => assert.ok(isNotZero(value)))) 22 | zeroValues.forEach((value) => test(`! isNotZero ${value}`, () => assert.not(isNotZero(value)))) 23 | 24 | const _allNotType: Exclude[] = [...zeroValues, ...notZeroValues].filter(isNotZero) 25 | const _neverNotType: number[] = zeroValues.filter(isNotZero) 26 | 27 | // isPropertyZero ----------------------------------------------------------------------------------------------------- 28 | 29 | test(`isPropertyZero id`, () => { 30 | const items = [{ id: 0 }, { id: undefined }, { id: null }] 31 | const filteredItems = items.filter(isPropertyZero('id')) 32 | 33 | assert.ok(filteredItems.length === 1) 34 | }) 35 | 36 | // isPropertyNotZero -------------------------------------------------------------------------------------------------- 37 | 38 | test(`isPropertyNotZero id`, () => { 39 | const items = [{ id: 0 }, { id: 1 }, { id: null }] 40 | const filteredItems = items.filter(isPropertyNotZero('id')) 41 | 42 | assert.ok(filteredItems.length === 2) 43 | }) 44 | 45 | // arePropertiesZero -------------------------------------------------------------------------------------------------- 46 | 47 | test(`arePropertiesZero id count`, () => { 48 | const items = [ 49 | { id: 0, count: 0 }, 50 | { id: undefined, count: 0 }, 51 | { id: 0, count: null }, 52 | { id: null, count: 12 }, 53 | ] 54 | const filteredItems = items.filter(arePropertiesZero('id', 'count')) 55 | 56 | assert.ok(filteredItems.length === 1) 57 | }) 58 | 59 | // arePropertiesNotZero ----------------------------------------------------------------------------------------------- 60 | 61 | test(`arePropertiesNotZero id count`, () => { 62 | const items = [ 63 | { id: 0, count: 0 }, 64 | { id: undefined, count: 0 }, 65 | { id: 0, count: null }, 66 | { id: null, count: 12 }, 67 | ] 68 | const filteredItems = items.filter(arePropertiesNotZero('id', 'count')) 69 | 70 | assert.ok(filteredItems.length === 1) 71 | }) 72 | 73 | test.run() 74 | -------------------------------------------------------------------------------- /src/isZero/isZero.ts: -------------------------------------------------------------------------------- 1 | import { TypeGuard, TypeGuardWithReturnType, TypeGuardInverted } from '../types' 2 | 3 | export const isZero = (value: T | 0): value is TypeGuardWithReturnType => value === 0 4 | 5 | export const isNotZero = (value: T): value is TypeGuardInverted<0, T> => value !== 0 6 | 7 | export const isPropertyZero = (property: K) => (value: T): boolean => 8 | value[property] === 0 9 | 10 | export const isPropertyNotZero = (property: K) => (value: T): boolean => 11 | value[property] !== 0 12 | 13 | export const arePropertiesZero = (...properties: K[]) => (value: T): boolean => 14 | properties.every((property) => value[property] === 0) 15 | 16 | export const arePropertiesNotZero = (...properties: K[]) => (value: T): boolean => 17 | properties.every((property) => value[property] !== 0) 18 | -------------------------------------------------------------------------------- /src/logical/logical.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { isNotUndefined } from '..' 4 | import { isNotNull, isNull } from '../isNull/isNull' 5 | import { isNumber } from '../isNumber/isNumber' 6 | import { isString } from '../isString/isString' 7 | import { isFalsy, isTruthy } from '../isTruthy/isTruthy' 8 | import { and, not, or } from './logical' 9 | 10 | const test = suite('logical') 11 | 12 | const items = ['test', { prop: 0 }, null, undefined, true, {}, 0, 123, false, ''] 13 | 14 | // and ---------------------------------------------------------------------------------------------------------------- 15 | 16 | test(`and truthy`, () => { 17 | const filteredItems = items.filter(and(isTruthy, isFalsy)) 18 | 19 | assert.ok(filteredItems.length === 0) 20 | }) 21 | 22 | test(`and isNumber && equals 4`, () => { 23 | const filteredItems = [1.5, 4, -4, 6, 4].filter(and(isNumber, (value) => value === 4)) 24 | 25 | assert.ok(filteredItems.length === 2) 26 | }) 27 | 28 | // or ----------------------------------------------------------------------------------------------------------------- 29 | 30 | test(`or truthy`, () => { 31 | const filteredItems = items.filter(or(isTruthy, isFalsy)) 32 | 33 | assert.ok(filteredItems.length === items.length) 34 | }) 35 | 36 | test(`and isString || isNull`, () => { 37 | const filteredItems = ['', null, 'test', 55, undefined].filter(or(isString, isNull)) 38 | 39 | assert.ok(filteredItems.length === 3) 40 | }) 41 | 42 | // not ---------------------------------------------------------------------------------------------------------------- 43 | 44 | test(`not isNull`, () => { 45 | const items = [1, 5, 8, 5, 33, null] 46 | const filteredItems = items.filter(not(isNull)) 47 | 48 | assert.ok(filteredItems.length === 5) 49 | }) 50 | 51 | test(`not isNotNull`, () => { 52 | const items = [1, 5, 8, 5, 33, null] 53 | const filteredItems = items.filter(not(isNotNull)) 54 | 55 | assert.ok(filteredItems.length === 1) 56 | }) 57 | 58 | const _explicitType: number[] = [null, 123].filter(not(isNotNull)) 59 | const _autoType: number[] = [123, undefined].filter(not(isNotUndefined)) 60 | 61 | test.run() 62 | -------------------------------------------------------------------------------- /src/logical/logical.ts: -------------------------------------------------------------------------------- 1 | import type { FilterFn } from '../types' 2 | 3 | export const and = 4 | (...filters: FilterFn[]) => 5 | (value: T, index?: number, array?: T[]): value is U => 6 | filters.reduce((prev, filter) => prev && (filter as any)(value, index, array), true) 7 | 8 | export const or = 9 | (...filters: FilterFn[]) => 10 | (value: T, index?: number, array?: T[]): value is U => 11 | filters.reduce((prev, filter) => prev || (filter as any)(value, index, array), false) 12 | 13 | export const not = 14 | = FilterFn>(filterFn: F) => 15 | (value: T, i?: number, array?: T[]): value is U => 16 | !filterFn(value, i, array) 17 | -------------------------------------------------------------------------------- /src/pick/pick.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { pick } from './pick' 4 | 5 | const test = suite('pick') 6 | 7 | // pick ----------------------------------------------------------------------------------------------- 8 | 9 | test(`pick inStock`, () => { 10 | const items = [ 11 | { available: 'some-id', inStock: true }, 12 | { available: true, inStock: true }, 13 | { available: 'some-id', inStock: false }, 14 | { available: null, inStock: true }, 15 | ] 16 | const filteredItems = items.map(pick('inStock')) 17 | 18 | filteredItems.forEach(item => assert.is(typeof item, 'boolean')) 19 | assert.is(filteredItems.filter(item => item === true).length, 3) 20 | assert.is(filteredItems.filter(item => item === false).length, 1) 21 | }) 22 | 23 | test(`pick length`, () => { 24 | const items = ["string", "another-string", ""] 25 | const filteredItems = items.map(pick('length')) 26 | 27 | filteredItems.forEach(item => assert.is(typeof item, 'number')) 28 | assert.is(filteredItems[0], 6) 29 | assert.is(filteredItems[1], 14) 30 | assert.is(filteredItems[2], 0) 31 | }) 32 | 33 | test.run() 34 | -------------------------------------------------------------------------------- /src/pick/pick.ts: -------------------------------------------------------------------------------- 1 | export const pick = (property: K) => (value: T): T[K] => 2 | value[property] -------------------------------------------------------------------------------- /src/sorting/sorting.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { 4 | sortDateASC, 5 | sortDateDESC, 6 | sortDatePropertyASC, 7 | sortDatePropertyDESC, 8 | sortNumberASC, 9 | sortNumberDESC, 10 | sortNumberPropertyASC, 11 | sortNumberPropertyDESC, 12 | sortStringASC, 13 | sortStringPropertyASC, 14 | sortStringPropertyDESC, 15 | } from './sorting' 16 | 17 | const test = suite('sorting') 18 | 19 | // number ------------------------------------------------------------------------------------------------------------- 20 | 21 | test(`sortNumberASC`, () => { 22 | const items = [123, null, 0, -10] 23 | const sortedItems = items.sort(sortNumberASC) 24 | 25 | assert.equal(sortedItems, [null, -10, 0, 123]) 26 | }) 27 | 28 | test(`sortNumberDESC`, () => { 29 | const items = [12, -3, 0] 30 | const sortedItems = items.sort(sortNumberDESC) 31 | 32 | assert.equal(sortedItems, [12, 0, -3]) 33 | }) 34 | 35 | test(`sortNumberPropertyASC`, () => { 36 | const items = [{ a: 12 }, { a: -3 }] 37 | const sortedItems = items.sort(sortNumberPropertyASC('a')) 38 | 39 | assert.equal(sortedItems, [{ a: -3 }, { a: 12 }]) 40 | }) 41 | 42 | test(`sortNumberPropertyDESC`, () => { 43 | const items = [{ t: 0 }, { t: 100 }] 44 | const sortedItems = items.sort(sortNumberPropertyDESC('t')) 45 | 46 | assert.equal(sortedItems, [{ t: 100 }, { t: 0 }]) 47 | }) 48 | 49 | // string ------------------------------------------------------------------------------------------------------------- 50 | 51 | test(`sortStringASC`, () => { 52 | const items = ['z', null, 'A', ''] 53 | const sortedItems = items.sort(sortStringASC) 54 | 55 | assert.equal(sortedItems, [null, '', 'A', 'z']) 56 | }) 57 | 58 | test(`sortStringDESC`, () => { 59 | const items = ['z', 'B', 'a'] 60 | const sortedItems = items.sort(sortStringASC) 61 | 62 | assert.equal(sortedItems, ['a', 'B', 'z']) 63 | }) 64 | 65 | test(`sortStringASC Upper-/Lowercase`, () => { 66 | const items = ['hi', 'hI', 'Hi', 'HI'] 67 | const sortedItems = items.sort(sortStringASC) 68 | assert.equal(sortedItems, items) 69 | 70 | const items2 = ['HI', 'hI', 'Hi', 'hi'] 71 | const sortedItems2 = items2.sort(sortStringASC) 72 | assert.equal(sortedItems2, items2) 73 | }) 74 | 75 | test(`sortStringPropertyASC`, () => { 76 | const items = [{ a: 'z' }, { a: 'b' }] 77 | const sortedItems = items.sort(sortStringPropertyASC('a')) 78 | 79 | assert.equal(sortedItems, [{ a: 'b' }, { a: 'z' }]) 80 | }) 81 | 82 | test(`sortStringPropertyDESC`, () => { 83 | const items = [{ t: 'a' }, { t: 'c' }] 84 | const sortedItems = items.sort(sortStringPropertyDESC('t')) 85 | 86 | assert.equal(sortedItems, [{ t: 'c' }, { t: 'a' }]) 87 | }) 88 | 89 | // date --------------------------------------------------------------------------------------------------------------- 90 | 91 | const today = new Date() 92 | const tomorrow = new Date(today.getTime() + 24 * 60 * 60 * 1000) 93 | test(`sortDateASC`, () => { 94 | const items = [tomorrow, null, today] 95 | const sortedItems = items.sort(sortDateASC) 96 | 97 | assert.equal(sortedItems, [null, today, tomorrow]) 98 | }) 99 | 100 | test(`sortDateDESC`, () => { 101 | const items = [today, tomorrow, undefined] 102 | const sortedItems = items.sort(sortDateDESC) 103 | 104 | assert.equal(sortedItems, [tomorrow, today, undefined]) 105 | }) 106 | 107 | test(`sortDatePropertyASC`, () => { 108 | const items = [{ a: tomorrow }, { a: today }] 109 | const sortedItems = items.sort(sortDatePropertyASC('a')) 110 | 111 | assert.equal(sortedItems, [{ a: today }, { a: tomorrow }]) 112 | }) 113 | 114 | test(`sortDatePropertyDESC`, () => { 115 | const items = [{ t: today }, { t: tomorrow }] 116 | const sortedItems = items.sort(sortDatePropertyDESC('t')) 117 | 118 | assert.equal(sortedItems, [{ t: tomorrow }, { t: today }]) 119 | }) 120 | 121 | test.run() 122 | -------------------------------------------------------------------------------- /src/sorting/sorting.ts: -------------------------------------------------------------------------------- 1 | const sortASC = (a: T, b: T) => { 2 | if (a === b) return 0 3 | if (a == null) return -1 4 | if (b == null) return 1 5 | return a < b ? -1 : 1 6 | } 7 | 8 | // number ------------------------------------------------------------------------------------------------------------- 9 | 10 | type NumberType = number | undefined | null 11 | 12 | export const sortNumberASC = (a?: NumberType, b?: NumberType): number => sortASC(a, b) 13 | 14 | export const sortNumberPropertyASC = ( 15 | property: K, 16 | ) => ({ [property]: a }: T, { [property]: b }: T): number => sortNumberASC(a, b) 17 | 18 | export const sortNumberDESC = (a?: NumberType, b?: NumberType): number => sortNumberASC(b, a) 19 | 20 | export const sortNumberPropertyDESC = ( 21 | property: K, 22 | ) => ({ [property]: a }: T, { [property]: b }: T): number => sortNumberDESC(a, b) 23 | 24 | // string ------------------------------------------------------------------------------------------------------------- 25 | 26 | type StringType = string | undefined | null 27 | 28 | export const sortStringASC = (a?: StringType, b?: StringType): number => sortASC(a?.toLowerCase(), b?.toLowerCase()) 29 | 30 | export const sortStringPropertyASC = ( 31 | property: K, 32 | ) => ({ [property]: a }: T, { [property]: b }: T): number => sortStringASC(a, b) 33 | 34 | export const sortStringDESC = (a?: StringType, b?: StringType): number => sortStringASC(b, a) 35 | 36 | export const sortStringPropertyDESC = ( 37 | property: K, 38 | ) => ({ [property]: a }: T, { [property]: b }: T): number => sortStringDESC(a, b) 39 | 40 | // date --------------------------------------------------------------------------------------------------------------- 41 | 42 | type DateType = Date | undefined | null 43 | 44 | export const sortDateASC = (a?: DateType, b?: DateType): number => sortASC(a?.getTime(), b?.getTime()) 45 | 46 | export const sortDatePropertyASC = (property: K) => ( 47 | { [property]: a }: T, 48 | { [property]: b }: T, 49 | ): number => sortASC(a?.getTime(), b?.getTime()) 50 | 51 | export const sortDateDESC = (a?: DateType, b?: DateType): number => sortDateASC(b, a) 52 | 53 | export const sortDatePropertyDESC = (property: K) => ( 54 | { [property]: a }: T, 55 | { [property]: b }: T, 56 | ): number => sortDateDESC(a, b) 57 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | export type Everything = {} | null | undefined 2 | 3 | export type FalsyType = false | '' | 0 | null | undefined 4 | 5 | export type TypeGuard = 6 | Type extends Guard 7 | ? Type 8 | : never 9 | 10 | export type TypeGuardWithReturnType = 11 | Type extends Guard 12 | ? Type extends ReturnType 13 | ? Type 14 | : ReturnType 15 | : never 16 | 17 | export type TypeGuardInverted = 18 | Type extends Guard 19 | ? never 20 | : Type 21 | 22 | export type TypeGuardInvertedWithReturnType = 23 | Type extends Guard 24 | ? never 25 | : Type extends ReturnType 26 | ? Type 27 | : ReturnType 28 | 29 | export type FilterFn = 30 | | ((value: InputType, i?: number, array?: InputType[]) => boolean) 31 | | ((value: InputType, i?: number, array?: InputType[]) => value is ReturnType) 32 | 33 | export type InferType = OriginalType extends infer InferredType ? InferredType : OriginalType 34 | -------------------------------------------------------------------------------- /src/uniqueArray/uniqueArray.test.ts: -------------------------------------------------------------------------------- 1 | import { suite } from 'uvu' 2 | import * as assert from 'uvu/assert' 3 | import { uniqueArray } from './uniqueArray' 4 | 5 | const test = suite('uniqueArray') 6 | 7 | // -------------------------------------------------------------------------------------------------------------------- 8 | 9 | const testUniqueArray = (input: T[], expexted: T[]) => 10 | test('uniqueArray', () => assert.equal(uniqueArray(input), expexted)) 11 | 12 | testUniqueArray([], []) 13 | 14 | testUniqueArray(['test'], ['test']) 15 | testUniqueArray(['test', '123'], ['test', '123']) 16 | testUniqueArray(['a', 'a'], ['a']) 17 | testUniqueArray(['a', 'b', 'a', 'a'], ['a', 'b']) 18 | 19 | testUniqueArray([123], [123]) 20 | testUniqueArray([123, 456], [123, 456]) 21 | testUniqueArray([1, 1], [1]) 22 | testUniqueArray([1, 2, 1, 1], [1, 2]) 23 | 24 | testUniqueArray([true, false], [true, false]) 25 | testUniqueArray([true, true], [true]) 26 | testUniqueArray([false, false, false], [false]) 27 | 28 | testUniqueArray(['test', 123, true, null, false], ['test', 123, true, null, false]) 29 | 30 | test.run() 31 | -------------------------------------------------------------------------------- /src/uniqueArray/uniqueArray.ts: -------------------------------------------------------------------------------- 1 | 2 | export const uniqueArray = (array: T[]): T[] => Array.from(new Set(array)) 3 | -------------------------------------------------------------------------------- /tsconfig-cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "module": "CommonJS", 5 | "outDir": "./lib/cjs" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2019", 4 | "module": "ES2020", 5 | "moduleResolution": "Node", 6 | "declaration": true, 7 | // "sourceMap": true, 8 | // "declarationMap": true, 9 | "outDir": "./lib/esm", 10 | "rootDir": "./src", 11 | "strict": true, 12 | "noImplicitAny": true, 13 | "strictNullChecks": true, 14 | "strictFunctionTypes": true, 15 | "strictBindCallApply": true, 16 | "strictPropertyInitialization": true, 17 | "noImplicitThis": true, 18 | "alwaysStrict": true, 19 | // "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noImplicitReturns": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "noUncheckedIndexedAccess": true, 24 | "esModuleInterop": true, 25 | "skipLibCheck": true, 26 | "forceConsistentCasingInFileNames": true 27 | }, 28 | "include": ["src/**/*"], 29 | "exclude": ["node_modules"], 30 | "ts-node": { 31 | "compilerOptions": { 32 | "module": "commonjs", 33 | "noUnusedLocals": false 34 | }, 35 | "include": ["src/**/*.test.*"] 36 | } 37 | } 38 | --------------------------------------------------------------------------------