diff --git a/README.md b/README.md index daa52c42..72000f75 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,6 @@ with smart type inference.

- - ```ts import { match, P } from 'ts-pattern'; @@ -44,6 +42,7 @@ const html = match(result) Write **better** and **safer conditions**. Pattern matching lets you express complex conditions in a single, compact expression. Your code becomes **shorter** and **more readable**. Exhaustiveness checking ensures you haven’t forgotten **any possible case**. ![ts-pattern](https://user-images.githubusercontent.com/9265418/231688650-7cd957a9-8edc-4db8-a5fe-61e1c2179d91.gif) +

Animation by @nicoespeon

## Features @@ -55,7 +54,7 @@ Write **better** and **safer conditions**. Pattern matching lets you express com - **Expressive API**, with catch-all and type specific **wildcards**: [`P._`](#P_-wildcard), [`P.string`](#Pstring-wildcard), [`P.number`](#Pnumber-wildcard), etc. - Supports [**predicates**](#Pwhen-patterns), [**unions**](#Punion-patterns), [**intersections**](#Pintersection-patterns) and [**exclusion**](#Pnot-patterns) patterns for non-trivial cases. - Supports properties selection, via the [`P.select(name?)`](#Pselect-patterns) function. -- Tiny bundle footprint ([**only 1.7kB**](https://bundlephobia.com/package/ts-pattern)). +- Tiny bundle footprint ([**only ~2kB**](https://bundlephobia.com/package/ts-pattern)). ## What is Pattern Matching? @@ -83,14 +82,13 @@ yarn add ts-pattern Note: TS-Pattern assumes [Strict Mode](https://www.typescriptlang.org/tsconfig#strict) is enabled in your `tsconfig.json` file. -| ts-pattern | TypeScript v4.5+ | TypeScript v4.2+ | TypeScript v4.1+ | -| --------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ---------------- | ---------------- | -| v4.x [(Docs)](#documentation) [(Migration Guide)](https://github.com/gvergnaud/ts-pattern/tree/master/docs/v3-to-v4-migration-guide.md) | ✅ | ❌ | ❌ | -| v3.x [(Docs)](https://github.com/gvergnaud/ts-pattern/tree/v3#documentation) | ✅ | ✅ | ⚠️ | -| v2.x [(Docs)](https://github.com/gvergnaud/ts-pattern/tree/v2#documentation) | ✅ | ✅ | ✅ | +| ts-pattern | TypeScript v5+ | TypeScript v4.5+ | TypeScript v4.2+ | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | ---------------- | ---------------- | +| v5.x [(Docs)](#documentation) [(Migration Guide)](https://github.com/gvergnaud/ts-pattern/tree/master/docs/v4-to-v5-migration-guide.md) | ✅ | ❌ | ❌ | +| v4.x [(Docs)](https://github.com/gvergnaud/ts-pattern/tree/v4##documentation) [(Migration Guide)](https://github.com/gvergnaud/ts-pattern/tree/master/docs/v3-to-v4-migration-guide.md) | ✅ | ✅ | ❌ | +| v3.x [(Docs)](https://github.com/gvergnaud/ts-pattern/tree/v3#documentation) | ✅ | ✅ | ✅ | - ✅ Full support -- ⚠️ Partial support, All features except passing multiple patterns to `.with()`. - ❌ Not supported # Documentation @@ -566,7 +564,7 @@ type Permission = 'editor' | 'viewer'; type Plan = 'basic' | 'pro'; const fn = (org: Plan, user: Permission) => - match([org, user] as const) + match([org, user]) .with(['basic', 'viewer'], () => {}) .with(['basic', 'editor'], () => {}) .with(['pro', 'viewer'], () => {}) @@ -575,7 +573,7 @@ const fn = (org: Plan, user: Permission) => .exhaustive(); const fn2 = (org: Plan, user: Permission) => - match([org, user] as const) + match([org, user]) .with(['basic', 'viewer'], () => {}) .with(['basic', 'editor'], () => {}) .with(['pro', 'viewer'], () => {}) @@ -741,6 +739,61 @@ console.log(output); // => 'number: two' ``` +### Objects + +Patterns can be objects containing sub-patterns. An object pattern will match +If and only if the input value **is an object**, contains **all properties** the pattern defines +and each property **matches** the corresponding sub-pattern. + +```ts +import { match } from 'ts-pattern'; + +type Input = + | { type: 'user'; name: string } + | { type: 'image'; src: string } + | { type: 'video'; seconds: number }; + +let input: Input = { type: 'user', name: 'Gabriel' }; + +const output = match(input) + .with({ type: 'image' }, () => 'image') + .with({ type: 'video', seconds: 10 }, () => 'video of 10 seconds.') + .with({ type: 'user' }, ({ name }) => `user of name: ${name}`) + .otherwise(() => 'something else'); + +console.log(output); +// => 'user of name: Gabriel' +``` + +### Tuples (arrays) + +In TypeScript, [Tuples](https://en.wikipedia.org/wiki/Tuple) are arrays with a fixed +number of elements which can be of different types. You can pattern-match on tuples +using a tuple pattern. A tuple pattern will match if the input value **is an array of the same length**, +and each item match the corresponding sub-pattern. + +```ts +import { match, P } from 'ts-pattern'; + +type Input = + | [number, '+', number] + | [number, '-', number] + | [number, '*', number] + | ['-', number]; + +const input: Input = [3, '*', 4]; + +const output = match(input) + .with([P._, '+', P._], ([x, , y]) => x + y) + .with([P._, '-', P._], ([x, , y]) => x - y) + .with([P._, '*', P._], ([x, , y]) => x * y) + .with(['-', P._], ([, x]) => -x) + .otherwise(() => NaN); + +console.log(output); +// => 12 +``` + ### Wildcards #### `P._` wildcard @@ -874,61 +927,6 @@ console.log(output); // => 'it is a symbol!' ``` -### Objects - -Patterns can be objects containing sub-patterns. An object pattern will match -If and only if the input value **is an object**, contains **all properties** the pattern defines -and each property **matches** the corresponding sub-pattern. - -```ts -import { match } from 'ts-pattern'; - -type Input = - | { type: 'user'; name: string } - | { type: 'image'; src: string } - | { type: 'video'; seconds: number }; - -let input: Input = { type: 'user', name: 'Gabriel' }; - -const output = match(input) - .with({ type: 'image' }, () => 'image') - .with({ type: 'video', seconds: 10 }, () => 'video of 10 seconds.') - .with({ type: 'user' }, ({ name }) => `user of name: ${name}`) - .otherwise(() => 'something else'); - -console.log(output); -// => 'user of name: Gabriel' -``` - -### Tuples (arrays) - -In TypeScript, [Tuples](https://en.wikipedia.org/wiki/Tuple) are arrays with a fixed -number of elements which can be of different types. You can pattern-match on tuples -using a tuple pattern. A tuple pattern will match if the input value **is an array of the same length**, -and each item match the corresponding sub-pattern. - -```ts -import { match, P } from 'ts-pattern'; - -type Input = - | [number, '+', number] - | [number, '-', number] - | [number, '*', number] - | ['-', number]; - -const input: Input = [3, '*', 4]; - -const output = match(input) - .with([P._, '+', P._], ([x, , y]) => x + y) - .with([P._, '-', P._], ([x, , y]) => x - y) - .with([P._, '*', P._], ([x, , y]) => x * y) - .with(['-', P._], ([, x]) => -x) - .otherwise(() => NaN); - -console.log(output); -// => 12 -``` - ### `P.array` patterns To match on arrays of unknown size, you can use `P.array(subpattern)`. @@ -956,9 +954,32 @@ console.log(output); // => 'a list of posts!' ``` -### Sets +### Matching variadic tuples with `P.array` -Patterns can be Sets. +In TypeScript, [Variadic Tuple Types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html#variadic-tuple-types) are array types created with the `...` spread operator, like `[string, ...string[]]`, `[number, ...boolean[], string]` etc. You can match against variadic tuple types using array literals containing `...P.array(subpattern)`: + +```ts +import { match, P } from 'ts-pattern'; + +type Input = (number | string)[]; + +declare const input: Input; + +const output = match(input) + // P.array's parameter is optional + .with([P.string, ...P.array()], (input) => input) // input: [string, ...(number | string)[]] + .with(['print', ...P.array(P.string)], (input) => input) // input: ['print', ...string[]] + // you can put patterns on either side of `...P.array()`: + .with([...P.array(P.string), 'end'], (input) => input) // input: [...string[], 'end'] + .with(['start', ...P.array(P.string), 'end'], (input) => input) // input: ['start', ...string[], 'end'] + .otherwise((input) => input); +``` + +### `P.set` patterns + +To match a Set, you can use `P.set(subpattern)`. +It takes a sub-pattern, and will match if **all elements** inside the set +match this sub-pattern. ```ts import { match, P } from 'ts-pattern'; @@ -968,26 +989,20 @@ type Input = Set; const input: Input = new Set([1, 2, 3]); const output = match(input) - .with(new Set([1, 'hello']), (set) => `Set contains 1 and 'hello'`) - .with(new Set([1, 2]), (set) => `Set contains 1 and 2`) - .with(new Set([P.string]), (set) => `Set contains only strings`) - .with(new Set([P.number]), (set) => `Set contains only numbers`) + .with(P.set(1), (set) => `Set contains only 1`) + .with(P.set(P.string), (set) => `Set contains only strings`) + .with(P.set(P.number), (set) => `Set contains only numbers`) .otherwise(() => ''); console.log(output); -// => 'Set contains 1 and 2' +// => "Set contains only numbers" ``` -If a Set pattern contains one single wildcard pattern, it will match if -each value in the input set match the wildcard. - -If a Set pattern contains several values, it will match if the -input Set contains each of these values. - -### Maps +### `P.map` patterns -Patterns can be Maps. They match if the input is a Map, and if each -value match the corresponding sub-pattern. +To match a Map, you can use `P.map(keyPattern, valuePattern)`. +It takes a subpattern to match against the key, a subpattern to match agains the value, and will match if **all elements** inside this map +match these two sub-patterns. ```ts import { match, P } from 'ts-pattern'; @@ -1001,19 +1016,16 @@ const input: Input = new Map([ ]); const output = match(input) - .with(new Map([['b', 2]]), (map) => `map.get('b') is 2`) - .with(new Map([['a', P.string]]), (map) => `map.get('a') is a string`) + .with(P.map(P.string, P.number), (map) => `map's type is Map`) + .with(P.map(P.string, P.string), (map) => `map's type is Map`) .with( - new Map([ - ['a', P.number], - ['c', P.number], - ]), - (map) => `map.get('a') and map.get('c') are number` + P.map(P.union('a', 'c'), P.number), + (map) => `map's type is Map<'a' | 'c', number>` ) .otherwise(() => ''); console.log(output); -// => 'map.get('b') is 2' +// => "map's type is Map" ``` ### `P.when` patterns @@ -1135,13 +1147,13 @@ declare const input: Input; const output = match(input) .with( { - author: P.select({ age: P.when((age) => age > 18) }), + author: P.select({ age: P.number.gt(18) }), }, (author) => author // author: User ) .with( { - author: P.select('author', { age: P.when((age) => age > 18) }), + author: P.select('author', { age: P.number.gt(18) }), content: P.select(), }, ({ author, content }) => author // author: User, content: Post @@ -1256,6 +1268,209 @@ const output = match(input) .otherwise(() => ''); ``` +## `P.string` helper patterns + +`P.string` has a number of methods to help you match on specific strings. + +### `P.string.startsWith` + +`P.string.startsWith(str)` matches strings that start with the provided string. + +```ts +const fn = (input: string) => + match(input) + .with(P.string.startsWith('TS'), () => '🎉') + .otherwise(() => '❌'); + +console.log(fn('TS-Pattern')); // logs '🎉' +``` + +### `P.string.endsWith` + +`P.string.endsWith(str)` matches strings that end with the provided string. + +```ts +const fn = (input: string) => + match(input) + .with(P.string.endsWith('!'), () => '🎉') + .otherwise(() => '❌'); + +console.log(fn('Hola!')); // logs '🎉' +``` + +### `P.string.minLength` + +`P.string.minLength(min)` matches strings with at least `min` characters. + +```ts +const fn = (input: string) => + match(input) + .with(P.string.minLength(2), () => '🎉') + .otherwise(() => '❌'); + +console.log(fn('two')); // logs '🎉' +``` + +### `P.string.maxLength` + +`P.string.maxLength(max)` matches strings with at most `max` characters. + +```ts +const fn = (input: string) => + match(input) + .with(P.string.minLength(5), () => '🎉') + .otherwise(() => 'too long'); + +console.log(fn('is this too long?')); // logs 'too long' +``` + +### `P.string.includes` + +`P.string.includes(str)` matches strings that contain the provided substring. + +```ts +const fn = (input: string) => + match(input) + .with(P.string.includes('!'), () => '✅') + .otherwise(() => '❌'); + +console.log(fn('Good job! 🎉')); // logs '✅' +``` + +### `P.string.regex` + +`P.string.regex(RegExp)` matches strings if they match the provided regular expression. + +```ts +const fn = (input: string) => + match(input) + .with(P.string.regex(/^[a-z]$/), () => 'single word') + .otherwise(() => 'other strings'); + +console.log(fn('gabriel')); // logs 'single word' +``` + +## `P.number` and `P.bigint` helper patterns + +`P.number` and `P.bigint` have several of methods to help you match on specific numbers and bigints. + +### `P.number.between` + +`P.number.between(min, max)` matches numbers between `min` and `max`. + +```ts +const fn = (input: number) => + match(input) + .with(P.number.between(1, 5), () => '✅') + .otherwise(() => '❌'); + +console.log(fn(3), fn(1), fn(5), fn(7)); // logs '✅ ✅ ✅ ❌' +``` + +### `P.number.lt` + +`P.number.lt(max)` matches numbers smaller than `max`. + +```ts +const fn = (input: number) => + match(input) + .with(P.number.lt(7), () => '✅') + .otherwise(() => '❌'); + +console.log(fn(2), fn(7)); // logs '✅ ❌' +``` + +### `P.number.gt` + +`P.number.gt(min)` matches numbers greater than `min`. + +```ts +const fn = (input: number) => + match(input) + .with(P.number.gt(7), () => '✅') + .otherwise(() => '❌'); + +console.log(fn(12), fn(7)); // logs '✅ ❌' +``` + +### `P.number.lte` + +`P.number.lte(max)` matches numbers smaller than or equal to `max`. + +```ts +const fn = (input: number) => + match(input) + .with(P.number.lte(7), () => '✅') + .otherwise(() => '❌'); + +console.log(fn(7), fn(12)); // logs '✅ ❌' +``` + +### `P.number.gte` + +`P.number.gte(min)` matches numbers greater than or equal to `min`. + +```ts +const fn = (input: number) => + match(input) + .with(P.number.gte(7), () => '✅') + .otherwise(() => '❌'); + +console.log(fn(7), fn(2)); // logs '✅ ❌' +``` + +### `P.number.int` + +`P.number.int()` matches integers. + +```ts +const fn = (input: number) => + match(input) + .with(P.number.int(), () => '✅') + .otherwise(() => '❌'); + +console.log(fn(12), fn(-3.141592)); // logs '✅ ❌' +``` + +### `P.number.finite` + +`P.number.finite()` matches all numbers except `Infinity` and `-Infinity`. + +```ts +const fn = (input: number) => + match(input) + .with(P.number.finite(), () => '✅') + .otherwise(() => '❌'); + +console.log(fn(-3.141592), fn(Infinity)); // logs '✅ ❌' +``` + +### `P.number.positive` + +`P.number.positive()` matches positive numbers. + +```ts +const fn = (input: number) => + match(input) + .with(P.number.positive(), () => '✅') + .otherwise(() => '❌'); + +console.log(fn(7), fn(-3.141592)); // logs '✅ ❌' +``` + +### `P.number.negative` + +`P.number.negative()` matches negative numbers. + +```ts +const fn = (input: number) => + match(input) + .with(P.number.negative(), () => '✅') + .otherwise(() => '❌'); + +console.log(fn(-3.141592), fn(7)); // logs '✅ ❌' +``` + ## Types ### `P.infer` @@ -1268,9 +1483,11 @@ It's particularly useful when validating an API response. const postPattern = { title: P.string, content: P.string, - likeCount: P.number, + stars: P.number.between(1, 5).optional(), author: { - name: P.string, + firstName: P.string, + lastName: P.string.optional(), + followerCount: P.number, }, }; @@ -1373,7 +1590,7 @@ type Permission = 'editor' | 'viewer'; type Plan = 'basic' | 'pro'; const fn = (org: Plan, user: Permission): string => - match([org, user] as const) + match([org, user]) .with(['basic', 'viewer'], () => {}) .with(['basic', 'editor'], () => {}) .with(['pro', 'viewer'], () => {}) diff --git a/docs/roadmap.md b/docs/roadmap.md index e849cfb1..4ede7fe2 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,9 +1,30 @@ ### Roadmap -- [ ] Add a custom matcher protocol data structures could implement to make them matchable. -- [ ] Add a native regex support. - -- [ ] (Maybe) add an iterator protocol to `P.array` to be usable as a variadic tuple pattern. Example of using `P.array`: +- [ ] chainable methods + - [ ] string + - [x] `P.string.includes('str')` + - [x] `P.string.startsWith('str')` + - [x] `P.string.endsWith('str')` + - [ ] `P.string.regex('[a-z]+')` + - [ ] numbers + - [ ] `P.number.between(1, 10)` + - [ ] `P.number.lt(12)` + - [ ] `P.number.gt(12)` + - [ ] `P.number.gte(12)` + - [ ] `P.number.lte(12)` + - [ ] `P.number.int(12)` + - [ ] `P.number.finite` + - [ ] `P.number.positive` + - [ ] `P.number.negative` + - [ ] all + - [ ] `P.number.optional` + - [ ] `P.string.optional` + - [ ] `P.number.select()` + - [ ] `P.string.select()` + - [ ] `P.number.optional.select()` + - [ ] `P.string.optional.select()` +- [x] Add a custom matcher protocol data structures could implement to make them matchable. +- [x] (Maybe) add an iterator protocol to `P.array` to be usable as a variadic tuple pattern. Example of using `P.array`: ```ts const reverse = (xs: T[]): T[] => { diff --git a/docs/v4-to-v5-migration-guide.md b/docs/v4-to-v5-migration-guide.md new file mode 100644 index 00000000..4bce8db8 --- /dev/null +++ b/docs/v4-to-v5-migration-guide.md @@ -0,0 +1,235 @@ +# TS-Pattern v4 to v5 Migration Guide + +This file contains all breaking changes and new features between the version 4 and 5 of TS-Pattern. + +# Breaking changes + +## `.with` is now evaluated eagerly + +In the previous version of TS-Pattern, no code would execute until you called `.exhaustive()` or `.otherwise(...)`. For example, in the following code block, nothing would be logged to the console or thrown: + +```ts +// TS-Pattern v4 +type Input = { type: 'ok'; value: number } | { type: 'error'; error: Error }; + +// We don't call `.exhaustive`, so handlers don't run. +function someFunction(input: Input) { + match(input) + .with({ type: 'ok' }, ({ value }) => { + console.log(value); + }) + .with({ type: 'error' }, ({ error }) => { + throw error; + }); +} + +someFunction({ type: 'ok', value: 42 }); // nothing happens +``` + +In **TS-Pattern v5**, however, the library will execute the matching handler as soon as it finds it: + +```ts +// TS-Pattern v5 +someFunction({ type: 'ok', value: 42 }); // logs "42" to the console! +``` + +Handlers are now evaluated **eagerly** instead of lazily. In practice, this shouldn't change anything as long as you always finish your pattern matching expressions by either `.exhaustive` or `.otherwise`. + +## Matching on Map and Sets + +Matching `Set` and `Map` instances using `.with(new Set(...))` and `.with(new Map(...))` is no longer supported. If you want to match specific sets and maps, you should now use the `P.map(keyPattern, valuePattern)` and `P.set(valuePattern)` patterns: + +```diff +- import { match } from 'ts-pattern'; ++ import { match, P } from 'ts-pattern'; + + +const someFunction = (value: Set | Map) => + match(value) +- .with(new Set([P.number]), (set) => `a set of numbers`) +- .with(new Map([['key', P.number]]), (map) => `map.get('key') is a number`) ++ .with(P.set(P.number), (set) => `a set of numbers`) ++ .with(P.map('key', P.number), (map) => `map.get('key') is a number`) + .otherwise(() => null); +``` + +- The subpattern we provide in `P.set(subpattern)` should match all values in the set. +- The value subpattern we provide in `P.map(keyPattern, subpattern)` should only match the values matching `keyPattern` for the whole `P.map(..)` pattern to match the input. + +# New features + +## chainable methods + +TS-Pattern v5's major addition is the ability to chain methods to narrow down the values matched by primitive patterns, like `P.string` or `P.number`. + +Since a few examples is worth a thousand words, here are a few ways you can use chainable methods: + +### P.number methods + +```ts +const example = (position: { x: number; y: number }) => + match(position) + .with({ x: P.number.gte(100) }, (value) => '🎮') + .with({ x: P.number.between(0, 100) }, (value) => '🎮') + .with( + { + x: P.number.positive().int(), + y: P.number.positive().int(), + }, + (value) => '🎮' + ) + .otherwise(() => 'x or y is negative'); +``` + +Here is the full list of number methods: + +- `P.number.between(min, max)`: matches numbers between `min` and `max`. +- `P.number.lt(max)`: matches numbers smaller than `max`. +- `P.number.gt(min)`: matches numbers greater than `min`. +- `P.number.lte(max)`: matches numbers smaller than or equal to `max`. +- `P.number.gte(min)`: matches numbers greater than or equal to `min`. +- `P.number.int()`: matches integers. +- `P.number.finite()`: matches all numbers except `Infinity` and `-Infinity` +- `P.number.positive()`: matches positive numbers. +- `P.number.negative()`: matches negative numbers. + +### P.string methods + +```ts +const example = (query: string) => + match(query) + .with(P.string.startsWith('SELECT'), (query) => `selection`) + .with(P.string.endsWith('FROM user'), (query) => `👯‍♂️`) + .with(P.string.includes('*'), () => 'contains a star') + // Methods can be chained: + .with(P.string.startsWith('SET').includes('*'), (query) => `🤯`) + .exhaustive(); +``` + +Here is the full list of string methods: + +- `P.string.startsWith(str)`: matches strings that start with `str`. +- `P.string.endsWith(str)`: matches strings that end with `str`. +- `P.string.minLength(min)`: matches strings with at least `min` characters. +- `P.string.maxLength(max)`: matches strings with at most `max` characters. +- `P.string.includes(str)`: matches strings that contain `str`. +- `P.string.regex(RegExp)`: matches strings if they match this regular expression. + +### Global methods + +Some methods are available for all primitive type patterns: + +- `P.{..}.optional()`: matches even if this property isn't present on the input object. +- `P.{..}.select()`: injects the matched value into the handler function. +- `P.{..}.and(pattern)`: matches if the current pattern **and** the provided pattern match. +- `P.{..}.or(pattern)`: matches if either the current pattern **or** the provided pattern match. + +```ts +const example = (value: unknown) => + match(value) + .with( + { + username: P.string, + displayName: P.string.optional(), + }, + () => `{ username:string, displayName?: string }` + ) + .with( + { + title: P.string, + author: { username: P.string.select() }, + }, + (username) => `author.username is ${username}` + ) + .with( + P.instanceOf(Error).and({ source: P.string }), + () => `Error & { source: string }` + ) + .with(P.string.or(P.number), () => `string | number`) + .otherwise(() => null); +``` + +## Variadic tuple patterns + +With TS-Pattern, you are now able to create array (or more accurately tuple) pattern with a variable number of elements: + +```ts +const example = (value: unknown) => + match(value) + .with( + // non-empty list of strings + [P.string, ...P.array(P.string)], + (value) => `value: [string, ...string[]]` + ) + .otherwise(() => null); +``` + +Array patterns that include a `...P.array` are called **variadic tuple patterns**. You may only have a single `...P.array`, but as many fixed-index patterns as you want: + +```ts +const example = (value: unknown) => + match(value) + .with( + [P.string, P.string, P.string, ...P.array(P.string)], + (value) => `value: [string, string, string, ...string[]]` + ) + .with( + [P.string, P.string, ...P.array(P.string)], + (value) => `value: [string, string, ...string[]]` + ) + .with([], (value) => `value: []`) + .otherwise(() => null); +``` + +Fixed-index patterns can also be set **after** the `...P.array` variadic, or on both sides! + +```ts +const example = (value: unknown) => + match(value) + .with( + [...P.array(P.number), P.string, P.number], + (value) => `value: [...number[], string, number]` + ) + .with( + [P.boolean, ...P.array(P.string), P.number, P.symbol], + (value) => `value: [boolean, ...string[], number, symbol]` + ) + .otherwise(() => null); +``` + +Lastly, argument of `P.array` is now optional, and will default to `P._`, which matches anything: + +```ts +const example = (value: unknown) => + match(value) + // 👇 + .with([P.string, ...P.array()], (value) => `value: [string, ...unknown[]]`) + .otherwise(() => null); +``` + +## `.returnType` + +In TS-Pattern v4, the only way to explicitly set the return type of your `match` expression is to set the two `` type parameters of `match`: + +```ts +// TS-Pattern v4 +match< + { isAdmin: boolean; plan: 'free' | 'paid' }, // input type + number // return type +>({ isAdmin, plan }) + .with({ isAdmin: true }, () => 123) + .with({ plan: 'free' }, () => 'Oops!'); +// ~~~~~~ ❌ not a number. +``` + +the main drawback is that you need to set the **_input type_** explicitly **_too_**, even though TypeScript should be able to infer it. + +In TS-Pattern v5, you can use the `.returnType()` method to only set the return type: + +```ts +match({ isAdmin, plan }) + .returnType() // 👈 new + .with({ isAdmin: true }, () => 123) + .with({ plan: 'free' }, () => 'Oops!'); +// ~~~~~~ ❌ not a number. +``` diff --git a/examples/one-file-demo.ts b/examples/one-file-demo.ts index a33e88f7..9914d471 100644 --- a/examples/one-file-demo.ts +++ b/examples/one-file-demo.ts @@ -1,3 +1,5 @@ +import { isMatching, match, P } from 'ts-pattern'; + /** * ### One file TS-Pattern demo. * @@ -11,8 +13,6 @@ * `P.array`, `P.optional`, etc. */ -import { isMatching, match, P } from 'ts-pattern'; - /************************************************** * Use case 1: handling discriminated union types * **************************************************/ @@ -22,7 +22,7 @@ type Response = | { type: 'image'; data: { extension: 'gif' | 'jpg' | 'png'; src: string } } | { type: 'text'; data: string; tags: { name: string; id: number }[] }; -const exampleFunction1 = (input: Response): string => +const example1 = (input: Response): string => match(input) // 1. Basic pattern with inference with a wildcard .with({ type: 'video', data: { format: 'mp4' } }, (video) => video.data.src) @@ -57,7 +57,7 @@ type UserType = 'editor' | 'viewer'; // Uncomment 'enterprise' to see exhaustive checking in action type OrgPlan = 'basic' | 'pro' | 'premium'; // | 'enterprise'; -const exampleFunction2 = (org: OrgPlan, user: UserType) => +const example2 = (org: OrgPlan, user: UserType) => // 1. Checking several enums with tuples match([org, user] as const) .with(['basic', P._], () => `Please upgrade to unlock this feature!`) @@ -72,8 +72,31 @@ const exampleFunction2 = (org: OrgPlan, user: UserType) => // 3. complex exhaustive checking .exhaustive(); +/************************************************** + * Use case 3: Matching specific strings or numbers + **************************************************/ + +const example3 = (queries: string[]) => + match(queries) + .with( + [ + P.string.startsWith('SELECT').endsWith('FROM user').select(), + ...P.array(), + ], + (firstQuery) => `${firstQuery}: 👨‍👩‍👧‍👦` + ) + .with(P.array(), () => 'other queries') + .exhaustive(); + +const example4 = (position: { x: number; y: number }) => + match(position) + .with({ x: P.number.gte(100) }, (value) => '⏱️') + .with({ x: P.number.between(0, 100) }, (value) => '⏱️') + .with({ x: P.number.positive(), y: P.number.positive() }, (value) => '⏱️') + .otherwise(() => 'x or y is negative'); + /****************************************** - * Use case 3: Validation an API response * + * Use case 4: Validation an API response * ******************************************/ const userPattern = { @@ -87,15 +110,17 @@ const userPattern = { }; const postPattern = { - title: P.string, + title: P.string.minLength(2).maxLength(255), + stars: P.number.int().between(0, 5), content: P.string, - likeCount: P.number, author: userPattern, // 2. arrays comments: P.array({ author: userPattern, content: P.string, }), + // 3. tuples (a non-empty array in this case) + tags: [P.string, ...P.array(P.string)], }; type Post = P.infer; diff --git a/examples/package-lock.json b/examples/package-lock.json index d7b62aa2..147ea803 100644 --- a/examples/package-lock.json +++ b/examples/package-lock.json @@ -8,20 +8,20 @@ "name": "ts-pattern-examples", "version": "1.0.0", "dependencies": { - "ts-pattern": "^4.1.2" + "ts-pattern": "^5.0.0-rc.1" } }, "node_modules/ts-pattern": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-4.1.2.tgz", - "integrity": "sha512-R/NEQHgeQwiyQyD5++s8rVB6jC1c6KiHHac2GEm0Pf82p3dth7s/kZfSimcUkVLjz+bPJn12721Vw9sbMpY5Rw==" + "version": "5.0.0-rc.1", + "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.0.0-rc.1.tgz", + "integrity": "sha512-Wb0s2expqr36hUiWZX2PD3FTEqNfsHpmb7W/D3a+rH9vV2oH5QABqJIcHXNsboa3UqOy6IGEdPe3NkNOEMIr/A==" } }, "dependencies": { "ts-pattern": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-4.1.2.tgz", - "integrity": "sha512-R/NEQHgeQwiyQyD5++s8rVB6jC1c6KiHHac2GEm0Pf82p3dth7s/kZfSimcUkVLjz+bPJn12721Vw9sbMpY5Rw==" + "version": "5.0.0-rc.1", + "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.0.0-rc.1.tgz", + "integrity": "sha512-Wb0s2expqr36hUiWZX2PD3FTEqNfsHpmb7W/D3a+rH9vV2oH5QABqJIcHXNsboa3UqOy6IGEdPe3NkNOEMIr/A==" } } } diff --git a/examples/package.json b/examples/package.json index b6f43b8b..be31b052 100644 --- a/examples/package.json +++ b/examples/package.json @@ -4,6 +4,6 @@ "main": "one-file-demo.ts", "author": "gvergnaud", "dependencies": { - "ts-pattern": "^4.1.2" + "ts-pattern": "^5.0.0-rc.1" } } diff --git a/examples/tsconfig.json b/examples/tsconfig.json index 5a18cd04..5d953614 100644 --- a/examples/tsconfig.json +++ b/examples/tsconfig.json @@ -1,6 +1,9 @@ { "compilerOptions": { "strict": true, - "lib": ["ES2015"] + "lib": ["ES2015"], + "target": "ES2015", + "moduleResolution": "bundler", + "module": "ESNext" } } diff --git a/package-lock.json b/package-lock.json index 101e8581..5a49272c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,21 @@ { "name": "ts-pattern", - "version": "4.3.0", + "version": "5.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "ts-pattern", - "version": "4.3.0", + "version": "5.0.0", "license": "MIT", "devDependencies": { - "@types/jest": "^27.0.2", - "jest": "^27.4.5", + "@types/jest": "^29.5.2", + "jest": "^29.5.0", "microbundle": "^0.15.1", - "prettier": "^2.5.1", - "rimraf": "^5.0.0", - "ts-jest": "^27.1.2", - "typescript": "^4.8.3" + "prettier": "^2.8.8", + "rimraf": "^5.0.1", + "ts-jest": "^29.1.0", + "typescript": "^5.1.3" } }, "node_modules/@babel/code-frame": { @@ -1055,12 +1055,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.16.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.5.tgz", - "integrity": "sha512-/d4//lZ1Vqb4mZ5xTep3dDK888j7BGM/iKqBmndBaoYAFPlPKrGU608VVBz5JeyAb6YQDjRu1UKqj86UhwWVgw==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", + "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.16.5" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1889,23 +1889,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz", - "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1971,9 +1954,9 @@ } }, "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { "ansi-regex": "^6.0.1" @@ -2028,59 +2011,59 @@ } }, "node_modules/@jest/console": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.4.2.tgz", - "integrity": "sha512-xknHThRsPB/To1FUbi6pCe43y58qFC03zfb6R7fDb/FfC7k2R3i1l+izRBJf8DI46KhYGRaF14Eo9A3qbBoixg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", + "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^27.4.2", - "jest-util": "^27.4.2", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/core": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.4.5.tgz", - "integrity": "sha512-3tm/Pevmi8bDsgvo73nX8p/WPng6KWlCyScW10FPEoN1HU4pwI83tJ3TsFvi1FfzsjwUlMNEPowgb/rPau/LTQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", + "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", "dev": true, "dependencies": { - "@jest/console": "^27.4.2", - "@jest/reporters": "^27.4.5", - "@jest/test-result": "^27.4.2", - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", + "@jest/console": "^29.5.0", + "@jest/reporters": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.8.1", + "ci-info": "^3.2.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-changed-files": "^27.4.2", - "jest-config": "^27.4.5", - "jest-haste-map": "^27.4.5", - "jest-message-util": "^27.4.2", - "jest-regex-util": "^27.4.0", - "jest-resolve": "^27.4.5", - "jest-resolve-dependencies": "^27.4.5", - "jest-runner": "^27.4.5", - "jest-runtime": "^27.4.5", - "jest-snapshot": "^27.4.5", - "jest-util": "^27.4.2", - "jest-validate": "^27.4.2", - "jest-watcher": "^27.4.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.5.0", + "jest-config": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-resolve-dependencies": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", + "jest-watcher": "^29.5.0", "micromatch": "^4.0.4", - "rimraf": "^3.0.0", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -2091,101 +2074,120 @@ } } }, - "node_modules/@jest/core/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "node_modules/@jest/environment": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", + "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", "dev": true, "dependencies": { - "glob": "^7.1.3" + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/node": "*", + "jest-mock": "^29.5.0" }, - "bin": { - "rimraf": "bin.js" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", + "dev": true, + "dependencies": { + "expect": "^29.5.0", + "jest-snapshot": "^29.5.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/@jest/environment": { - "version": "27.4.4", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.4.4.tgz", - "integrity": "sha512-q+niMx7cJgt/t/b6dzLOh4W8Ef/8VyKG7hxASK39jakijJzbFBGpptx3RXz13FFV7OishQ9lTbv+dQ5K3EhfDQ==", + "node_modules/@jest/expect-utils": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", + "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", "dev": true, "dependencies": { - "@jest/fake-timers": "^27.4.2", - "@jest/types": "^27.4.2", - "@types/node": "*", - "jest-mock": "^27.4.2" + "jest-get-type": "^29.4.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils/node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/fake-timers": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.4.2.tgz", - "integrity": "sha512-f/Xpzn5YQk5adtqBgvw1V6bF8Nx3hY0OIRRpCvWcfPl0EAjdqWPdhH3t/3XpiWZqtjIEHDyMKP9ajpva1l4Zmg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", + "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", - "@sinonjs/fake-timers": "^8.0.1", + "@jest/types": "^29.5.0", + "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^27.4.2", - "jest-mock": "^27.4.2", - "jest-util": "^27.4.2" + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "27.4.4", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.4.4.tgz", - "integrity": "sha512-bqpqQhW30BOreXM8bA8t8JbOQzsq/WnPTnBl+It3UxAD9J8yxEAaBEylHx1dtBapAr/UBk8GidXbzmqnee8tYQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", + "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", "dev": true, "dependencies": { - "@jest/environment": "^27.4.4", - "@jest/types": "^27.4.2", - "expect": "^27.4.2" + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/types": "^29.5.0", + "jest-mock": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.4.5.tgz", - "integrity": "sha512-3orsG4vi8zXuBqEoy2LbnC1kuvkg1KQUgqNxmxpQgIOQEPeV0onvZu+qDQnEoX8qTQErtqn/xzcnbpeTuOLSiA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", + "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.4.2", - "@jest/test-result": "^27.4.2", - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", + "@jest/console": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", + "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.4", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.3", + "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "jest-haste-map": "^27.4.5", - "jest-resolve": "^27.4.5", - "jest-util": "^27.4.2", - "jest-worker": "^27.4.5", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "slash": "^3.0.0", - "source-map": "^0.6.0", "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -2196,90 +2198,109 @@ } } }, + "node_modules/@jest/schemas": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.25.16" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/@jest/source-map": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.4.0.tgz", - "integrity": "sha512-Ntjx9jzP26Bvhbm93z/AKcPRj/9wrkI88/gK60glXDx1q+IeI0rf7Lw2c89Ch6ofonB0On/iRDreQuQ6te9pgQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", + "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", "dev": true, "dependencies": { + "@jridgewell/trace-mapping": "^0.3.15", "callsites": "^3.0.0", - "graceful-fs": "^4.2.4", - "source-map": "^0.6.0" + "graceful-fs": "^4.2.9" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-result": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.4.2.tgz", - "integrity": "sha512-kr+bCrra9jfTgxHXHa2UwoQjxvQk3Am6QbpAiJ5x/50LW8llOYrxILkqY0lZRW/hu8FXesnudbql263+EW9iNA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", + "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", "dev": true, "dependencies": { - "@jest/console": "^27.4.2", - "@jest/types": "^27.4.2", + "@jest/console": "^29.5.0", + "@jest/types": "^29.5.0", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/test-sequencer": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.4.5.tgz", - "integrity": "sha512-n5woIn/1v+FT+9hniymHPARA9upYUmfi5Pw9ewVwXCDlK4F5/Gkees9v8vdjGdAIJ2MPHLHodiajLpZZanWzEQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", + "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", "dev": true, "dependencies": { - "@jest/test-result": "^27.4.2", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.4.5", - "jest-runtime": "^27.4.5" + "@jest/test-result": "^29.5.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", + "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.4.5.tgz", - "integrity": "sha512-PuMet2UlZtlGzwc6L+aZmR3I7CEBpqadO03pU40l2RNY2fFJ191b9/ITB44LNOhVtsyykx0OZvj0PCyuLm7Eew==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", + "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", "dev": true, "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.4.2", - "babel-plugin-istanbul": "^6.0.0", + "@babel/core": "^7.11.6", + "@jest/types": "^29.5.0", + "@jridgewell/trace-mapping": "^0.3.15", + "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.4.5", - "jest-regex-util": "^27.4.0", - "jest-util": "^27.4.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.5.0", "micromatch": "^4.0.4", - "pirates": "^4.0.1", + "pirates": "^4.0.4", "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" + "write-file-atomic": "^4.0.2" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/@jest/transform/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, "node_modules/@jest/types": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.4.2.tgz", - "integrity": "sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dev": true, "dependencies": { + "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "@types/yargs": "^16.0.0", + "@types/yargs": "^17.0.8", "chalk": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jridgewell/gen-mapping": { @@ -2470,22 +2491,28 @@ "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", "dev": true }, + "node_modules/@sinclair/typebox": { + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "dev": true + }, "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", + "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", "dev": true, "dependencies": { - "@sinonjs/commons": "^1.7.0" + "@sinonjs/commons": "^3.0.0" } }, "node_modules/@surma/rollup-plugin-off-main-thread": { @@ -2500,15 +2527,6 @@ "string.prototype.matchall": "^4.0.6" } }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -2566,9 +2584,9 @@ "dev": true }, "node_modules/@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", "dev": true, "dependencies": { "@types/node": "*" @@ -2599,13 +2617,13 @@ } }, "node_modules/@types/jest": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.0.2.tgz", - "integrity": "sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA==", + "version": "29.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz", + "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==", "dev": true, "dependencies": { - "jest-diff": "^27.0.0", - "pretty-format": "^27.0.0" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, "node_modules/@types/node": { @@ -2621,9 +2639,9 @@ "dev": true }, "node_modules/@types/prettier": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.2.tgz", - "integrity": "sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", "dev": true }, "node_modules/@types/resolve": { @@ -2642,24 +2660,18 @@ "dev": true }, "node_modules/@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "dependencies": { "@types/yargs-parser": "*" } }, "node_modules/@types/yargs-parser": { - "version": "20.2.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", - "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", - "dev": true - }, - "node_modules/abab": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", - "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, "node_modules/acorn": { @@ -2674,49 +2686,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -2754,9 +2723,9 @@ } }, "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", @@ -2794,12 +2763,6 @@ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "dev": true }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, "node_modules/asyncro": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/asyncro/-/asyncro-3.0.0.tgz", @@ -2852,37 +2815,36 @@ } }, "node_modules/babel-jest": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.4.5.tgz", - "integrity": "sha512-3uuUTjXbgtODmSv/DXO9nZfD52IyC2OYTFaXGRzL0kpykzroaquCrD5+lZNafTvZlnNqZHt5pb0M08qVBZnsnA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", + "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", "dev": true, "dependencies": { - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", + "@jest/transform": "^29.5.0", "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^27.4.0", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.5.0", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.8.0" } }, "node_modules/babel-plugin-istanbul": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", - "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" }, "engines": { @@ -2890,18 +2852,18 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.4.0.tgz", - "integrity": "sha512-Jcu7qS4OX5kTWBc45Hz7BMmgXuJqRnhatqpUhnzGC3OBYpOmf2tv6jFNwZpwM7wU7MUuv2r9IPS/ZlYOuburVw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", + "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", + "@types/babel__core": "^7.1.14", "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/babel-plugin-macros": { @@ -3000,16 +2962,16 @@ } }, "node_modules/babel-preset-jest": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.4.0.tgz", - "integrity": "sha512-NK4jGYpnBvNxcGo7/ZpZJr51jCGT+3bwwpVIDY2oNfTxJJldRtB4VAcYdgp1loDE50ODuTu+yBjpMAswv5tlpg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", + "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^27.4.0", + "babel-plugin-jest-hoist": "^29.5.0", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": "^7.0.0" @@ -3061,12 +3023,6 @@ "node": ">= 10.16.0" } }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, "node_modules/browserslist": { "version": "4.21.5", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", @@ -3220,10 +3176,19 @@ } }, "node_modules/ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", - "dev": true + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } }, "node_modules/cjs-module-lexer": { "version": "1.2.2", @@ -3232,20 +3197,23 @@ "dev": true }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true, "engines": { "iojs": ">= 1.0.0", @@ -3282,18 +3250,6 @@ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", @@ -3529,44 +3485,6 @@ "node": ">=8.0.0" } }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -3584,22 +3502,10 @@ } } }, - "node_modules/decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", - "dev": true - }, "node_modules/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, "node_modules/deepmerge": { @@ -3636,15 +3542,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -3654,15 +3551,6 @@ "node": ">=8" } }, - "node_modules/diff-sequences": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.4.0.tgz", - "integrity": "sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==", - "dev": true, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -3689,27 +3577,6 @@ } ] }, - "node_modules/domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/domhandler": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", @@ -3773,12 +3640,12 @@ "dev": true }, "node_modules/emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sindresorhus/emittery?sponsor=1" @@ -3887,466 +3754,57 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esbuild": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.54.tgz", - "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "peer": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/linux-loong64": "0.14.54", - "esbuild-android-64": "0.14.54", - "esbuild-android-arm64": "0.14.54", - "esbuild-darwin-64": "0.14.54", - "esbuild-darwin-arm64": "0.14.54", - "esbuild-freebsd-64": "0.14.54", - "esbuild-freebsd-arm64": "0.14.54", - "esbuild-linux-32": "0.14.54", - "esbuild-linux-64": "0.14.54", - "esbuild-linux-arm": "0.14.54", - "esbuild-linux-arm64": "0.14.54", - "esbuild-linux-mips64le": "0.14.54", - "esbuild-linux-ppc64le": "0.14.54", - "esbuild-linux-riscv64": "0.14.54", - "esbuild-linux-s390x": "0.14.54", - "esbuild-netbsd-64": "0.14.54", - "esbuild-openbsd-64": "0.14.54", - "esbuild-sunos-64": "0.14.54", - "esbuild-windows-32": "0.14.54", - "esbuild-windows-64": "0.14.54", - "esbuild-windows-arm64": "0.14.54" - } - }, - "node_modules/esbuild-android-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz", - "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==", - "cpu": [ - "x64" - ], + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true, - "optional": true, - "os": [ - "android" - ], - "peer": true, "engines": { - "node": ">=12" + "node": ">=6" } }, - "node_modules/esbuild-android-arm64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz", - "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==", - "cpu": [ - "arm64" - ], + "node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true, - "optional": true, - "os": [ - "android" - ], - "peer": true, "engines": { - "node": ">=12" + "node": ">=8" } }, - "node_modules/esbuild-darwin-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz", - "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==", - "cpu": [ - "x64" - ], + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "peer": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, "engines": { - "node": ">=12" + "node": ">=4" } }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz", - "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=12" - } + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true }, - "node_modules/esbuild-freebsd-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz", - "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==", - "cpu": [ - "x64" - ], + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, "engines": { - "node": ">=12" + "node": ">=0.10.0" } }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz", - "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz", - "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz", - "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz", - "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz", - "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz", - "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz", - "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz", - "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz", - "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz", - "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz", - "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz", - "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz", - "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz", - "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz", - "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "dev": true + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true }, "node_modules/execa": { "version": "5.1.1", @@ -4374,39 +3832,35 @@ "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true, "engines": { "node": ">= 0.8.0" } }, "node_modules/expect": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.4.2.tgz", - "integrity": "sha512-BjAXIDC6ZOW+WBFNg96J22D27Nq5ohn+oGcuP2rtOtcjuxNoV9McpQ60PcQWhdFOSBIQdR72e+4HdnbZTFSTyg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", - "ansi-styles": "^5.0.0", - "jest-get-type": "^27.4.0", - "jest-matcher-utils": "^27.4.2", - "jest-message-util": "^27.4.2", - "jest-regex-util": "^27.4.0" + "@jest/expect-utils": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/expect/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/expect/node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", "dev": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/fast-json-stable-stringify": { @@ -4415,16 +3869,10 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, "node_modules/fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "dependencies": { "bser": "2.1.1" @@ -4559,9 +4007,9 @@ } }, "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz", - "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", "dev": true, "engines": { "node": ">=14" @@ -4570,20 +4018,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fraction.js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", @@ -4817,9 +4251,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/gzip-size": { @@ -4945,51 +4379,12 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "dependencies": { - "whatwg-encoding": "^1.0.5" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -4999,18 +4394,6 @@ "node": ">=10.17.0" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/icss-replace-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", @@ -5079,9 +4462,9 @@ } }, "node_modules/import-local": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", - "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "dependencies": { "pkg-dir": "^4.2.0", @@ -5092,12 +4475,15 @@ }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "engines": { "node": ">=0.8.19" @@ -5295,12 +4681,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, "node_modules/is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -5399,12 +4779,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -5436,23 +4810,24 @@ "dev": true }, "node_modules/istanbul-lib-coverage": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.1.tgz", - "integrity": "sha512-GvCYYTxaCPqwMjobtVcVKvSHtAGe48MNhGjpK8LtVF8K0ISX7hCKl85LgtuaSneWVyQmaGcW3iXVV3GaZSLpmQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "dependencies": { - "@babel/core": "^7.7.5", + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" }, "engines": { @@ -5488,9 +4863,9 @@ } }, "node_modules/istanbul-reports": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.1.tgz", - "integrity": "sha512-q1kvhAXWSsXfMjCdNHNPKZZv94OlspKnoGv+R9RGbnqOOQ0VbNfLFgQDVgi7hHenKsndGq3/o0OBdzDXthWcNw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -5501,9 +4876,9 @@ } }, "node_modules/jackspeak": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.0.tgz", - "integrity": "sha512-r5XBrqIJfwRIjRt/Xr5fv9Wh09qyhHfKnYddDlpM+ibRR20qrYActpCAgU6U+d53EOEjzkvxPMVHSlgR7leXrQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", + "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -5537,20 +4912,21 @@ } }, "node_modules/jest": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.4.5.tgz", - "integrity": "sha512-uT5MiVN3Jppt314kidCk47MYIRilJjA/l2mxwiuzzxGUeJIvA8/pDaJOAX5KWvjAo7SCydcW0/4WEtgbLMiJkg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", + "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", "dev": true, "dependencies": { - "@jest/core": "^27.4.5", + "@jest/core": "^29.5.0", + "@jest/types": "^29.5.0", "import-local": "^3.0.2", - "jest-cli": "^27.4.5" + "jest-cli": "^29.5.0" }, "bin": { "jest": "bin/jest.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -5562,73 +4938,103 @@ } }, "node_modules/jest-changed-files": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.4.2.tgz", - "integrity": "sha512-/9x8MjekuzUQoPjDHbBiXbNEBauhrPU2ct7m8TfCg69ywt1y/N+yYwGh3gCpnqUS3klYWDU/lSNgv+JhoD2k1A==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", + "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", "execa": "^5.0.0", - "throat": "^6.0.1" + "p-limit": "^3.1.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/jest-circus": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.4.5.tgz", - "integrity": "sha512-eTNWa9wsvBwPykhMMShheafbwyakcdHZaEYh5iRrQ0PFJxkDP/e3U/FvzGuKWu2WpwUA3C3hPlfpuzvOdTVqnw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", + "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", "dev": true, "dependencies": { - "@jest/environment": "^27.4.4", - "@jest/test-result": "^27.4.2", - "@jest/types": "^27.4.2", + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", - "expect": "^27.4.2", "is-generator-fn": "^2.0.0", - "jest-each": "^27.4.2", - "jest-matcher-utils": "^27.4.2", - "jest-message-util": "^27.4.2", - "jest-runtime": "^27.4.5", - "jest-snapshot": "^27.4.5", - "jest-util": "^27.4.2", - "pretty-format": "^27.4.2", + "jest-each": "^29.5.0", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.5.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" + "stack-utils": "^2.0.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/jest-cli": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.4.5.tgz", - "integrity": "sha512-hrky3DSgE0u7sQxaCL7bdebEPHx5QzYmrGuUjaPLmPE8jx5adtvGuOlRspvMoVLTTDOHRnZDoRLYJuA+VCI7Hg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", + "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", "dev": true, "dependencies": { - "@jest/core": "^27.4.5", - "@jest/test-result": "^27.4.2", - "@jest/types": "^27.4.2", + "@jest/core": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^27.4.5", - "jest-util": "^27.4.2", - "jest-validate": "^27.4.2", + "jest-config": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "prompts": "^2.0.1", - "yargs": "^16.2.0" + "yargs": "^17.3.1" }, "bin": { "jest": "bin/jest.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" @@ -5640,253 +5046,246 @@ } }, "node_modules/jest-config": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.4.5.tgz", - "integrity": "sha512-t+STVJtPt+fpqQ8GBw850NtSQbnDOw/UzdPfzDaHQ48/AylQlW7LHj3dH+ndxhC1UxJ0Q3qkq7IH+nM1skwTwA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", + "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", "dev": true, "dependencies": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^27.4.5", - "@jest/types": "^27.4.2", - "babel-jest": "^27.4.5", + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.5.0", + "@jest/types": "^29.5.0", + "babel-jest": "^29.5.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.4", - "jest-circus": "^27.4.5", - "jest-environment-jsdom": "^27.4.4", - "jest-environment-node": "^27.4.4", - "jest-get-type": "^27.4.0", - "jest-jasmine2": "^27.4.5", - "jest-regex-util": "^27.4.0", - "jest-resolve": "^27.4.5", - "jest-runner": "^27.4.5", - "jest-util": "^27.4.2", - "jest-validate": "^27.4.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.5.0", + "jest-environment-node": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "micromatch": "^4.0.4", - "pretty-format": "^27.4.2", - "slash": "^3.0.0" + "parse-json": "^5.2.0", + "pretty-format": "^29.5.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { + "@types/node": "*", "ts-node": ">=9.0.0" }, "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, "ts-node": { "optional": true } } }, - "node_modules/jest-diff": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.4.2.tgz", - "integrity": "sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q==", + "node_modules/jest-config/node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^27.4.0", - "jest-get-type": "^27.4.0", - "pretty-format": "^27.4.2" - }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-docblock": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.4.0.tgz", - "integrity": "sha512-7TBazUdCKGV7svZ+gh7C8esAnweJoG+SvcF6Cjqj4l17zA2q1cMwx2JObSioubk317H+cjcHgP+7fTs60paulg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", + "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", "dev": true, "dependencies": { "detect-newline": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-each": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.4.2.tgz", - "integrity": "sha512-53V2MNyW28CTruB3lXaHNk6PkiIFuzdOC9gR3C6j8YE/ACfrPnz+slB0s17AgU1TtxNzLuHyvNlLJ+8QYw9nBg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", + "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", - "jest-get-type": "^27.4.0", - "jest-util": "^27.4.2", - "pretty-format": "^27.4.2" + "jest-get-type": "^29.4.3", + "jest-util": "^29.5.0", + "pretty-format": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-environment-jsdom": { - "version": "27.4.4", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.4.4.tgz", - "integrity": "sha512-cYR3ndNfHBqQgFvS1RL7dNqSvD//K56j/q1s2ygNHcfTCAp12zfIromO1w3COmXrxS8hWAh7+CmZmGCIoqGcGA==", + "node_modules/jest-each/node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", "dev": true, - "dependencies": { - "@jest/environment": "^27.4.4", - "@jest/fake-timers": "^27.4.2", - "@jest/types": "^27.4.2", - "@types/node": "*", - "jest-mock": "^27.4.2", - "jest-util": "^27.4.2", - "jsdom": "^16.6.0" - }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "27.4.4", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.4.4.tgz", - "integrity": "sha512-D+v3lbJ2GjQTQR23TK0kY3vFVmSeea05giInI41HHOaJnAwOnmUHTZgUaZL+VxUB43pIzoa7PMwWtCVlIUoVoA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", + "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", "dev": true, "dependencies": { - "@jest/environment": "^27.4.4", - "@jest/fake-timers": "^27.4.2", - "@jest/types": "^27.4.2", + "@jest/environment": "^29.5.0", + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-mock": "^27.4.2", - "jest-util": "^27.4.2" + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.4.0.tgz", - "integrity": "sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==", - "dev": true, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-haste-map": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.4.5.tgz", - "integrity": "sha512-oJm1b5qhhPs78K24EDGifWS0dELYxnoBiDhatT/FThgB9yxqUm5F6li3Pv+Q+apMBmmPNzOBnZ7ZxWMB1Leq1Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", + "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", - "@types/graceful-fs": "^4.1.2", + "@jest/types": "^29.5.0", + "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-regex-util": "^27.4.0", - "jest-serializer": "^27.4.0", - "jest-util": "^27.4.2", - "jest-worker": "^27.4.5", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "micromatch": "^4.0.4", - "walker": "^1.0.7" + "walker": "^1.0.8" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "optionalDependencies": { "fsevents": "^2.3.2" } }, - "node_modules/jest-jasmine2": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.4.5.tgz", - "integrity": "sha512-oUnvwhJDj2LhOiUB1kdnJjkx8C5PwgUZQb9urF77mELH9DGR4e2GqpWQKBOYXWs5+uTN9BGDqRz3Aeg5Wts7aw==", + "node_modules/jest-leak-detector": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", + "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", "dev": true, "dependencies": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^27.4.4", - "@jest/source-map": "^27.4.0", - "@jest/test-result": "^27.4.2", - "@jest/types": "^27.4.2", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.4.2", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.4.2", - "jest-matcher-utils": "^27.4.2", - "jest-message-util": "^27.4.2", - "jest-runtime": "^27.4.5", - "jest-snapshot": "^27.4.5", - "jest-util": "^27.4.2", - "pretty-format": "^27.4.2", - "throat": "^6.0.1" + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-leak-detector": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.4.2.tgz", - "integrity": "sha512-ml0KvFYZllzPBJWDei3mDzUhyp/M4ubKebX++fPaudpe8OsxUE+m+P6ciVLboQsrzOCWDjE20/eXew9QMx/VGw==", + "node_modules/jest-leak-detector/node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", + "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", "dev": true, "dependencies": { - "jest-get-type": "^27.4.0", - "pretty-format": "^27.4.2" + "chalk": "^4.0.0", + "jest-diff": "^29.5.0", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-matcher-utils": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.4.2.tgz", - "integrity": "sha512-jyP28er3RRtMv+fmYC/PKG8wvAmfGcSNproVTW2Y0P/OY7/hWUOmsPfxN1jOhM+0u2xU984u2yEagGivz9OBGQ==", + "node_modules/jest-matcher-utils/node_modules/diff-sequences": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/jest-diff": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^27.4.2", - "jest-get-type": "^27.4.0", - "pretty-format": "^27.4.2" + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.4.2.tgz", - "integrity": "sha512-OMRqRNd9E0DkBLZpFtZkAGYOXl6ZpoMtQJWTAREJKDOFa0M6ptB7L67tp+cszMBkvSgKOhNtQp2Vbcz3ZZKo/w==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", + "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.4.2", + "@jest/types": "^29.5.0", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^27.4.2", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-mock": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.4.2.tgz", - "integrity": "sha512-PDDPuyhoukk20JrQKeofK12hqtSka7mWH0QQuxSNgrdiPsrnYYLS6wbzu/HDlxZRzji5ylLRULeuI/vmZZDrYA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", + "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", - "@types/node": "*" + "@jest/types": "^29.5.0", + "@types/node": "*", + "jest-util": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "engines": { "node": ">=6" @@ -5901,171 +5300,208 @@ } }, "node_modules/jest-regex-util": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.4.0.tgz", - "integrity": "sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", + "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", "dev": true, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.4.5.tgz", - "integrity": "sha512-xU3z1BuOz/hUhVUL+918KqUgK+skqOuUsAi7A+iwoUldK6/+PW+utK8l8cxIWT9AW7IAhGNXjSAh1UYmjULZZw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", + "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.4.5", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.4.2", - "jest-validate": "^27.4.2", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", + "resolve.exports": "^2.0.0", "slash": "^3.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-resolve-dependencies": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.4.5.tgz", - "integrity": "sha512-elEVvkvRK51y037NshtEkEnukMBWvlPzZHiL847OrIljJ8yIsujD2GXRPqDXC4rEVKbcdsy7W0FxoZb4WmEs7w==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", + "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", - "jest-regex-util": "^27.4.0", - "jest-snapshot": "^27.4.5" + "jest-regex-util": "^29.4.3", + "jest-snapshot": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.4.5.tgz", - "integrity": "sha512-/irauncTfmY1WkTaRQGRWcyQLzK1g98GYG/8QvIPviHgO1Fqz1JYeEIsSfF+9mc/UTA6S+IIHFgKyvUrtiBIZg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", + "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", "dev": true, "dependencies": { - "@jest/console": "^27.4.2", - "@jest/environment": "^27.4.4", - "@jest/test-result": "^27.4.2", - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", + "@jest/console": "^29.5.0", + "@jest/environment": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-docblock": "^27.4.0", - "jest-environment-jsdom": "^27.4.4", - "jest-environment-node": "^27.4.4", - "jest-haste-map": "^27.4.5", - "jest-leak-detector": "^27.4.2", - "jest-message-util": "^27.4.2", - "jest-resolve": "^27.4.5", - "jest-runtime": "^27.4.5", - "jest-util": "^27.4.2", - "jest-worker": "^27.4.5", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.4.3", + "jest-environment-node": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-leak-detector": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-resolve": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-util": "^29.5.0", + "jest-watcher": "^29.5.0", + "jest-worker": "^29.5.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" } }, "node_modules/jest-runtime": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.4.5.tgz", - "integrity": "sha512-CIYqwuJQXHQtPd/idgrx4zgJ6iCb6uBjQq1RSAGQrw2S8XifDmoM1Ot8NRd80ooAm+ZNdHVwsktIMGlA1F1FAQ==", - "dev": true, - "dependencies": { - "@jest/console": "^27.4.2", - "@jest/environment": "^27.4.4", - "@jest/globals": "^27.4.4", - "@jest/source-map": "^27.4.0", - "@jest/test-result": "^27.4.2", - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", - "@types/yargs": "^16.0.0", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", + "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.5.0", + "@jest/fake-timers": "^29.5.0", + "@jest/globals": "^29.5.0", + "@jest/source-map": "^29.4.3", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "exit": "^0.1.2", "glob": "^7.1.3", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.4.5", - "jest-message-util": "^27.4.2", - "jest-mock": "^27.4.2", - "jest-regex-util": "^27.4.0", - "jest-resolve": "^27.4.5", - "jest-snapshot": "^27.4.5", - "jest-util": "^27.4.2", - "jest-validate": "^27.4.2", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0", - "strip-bom": "^4.0.0", - "yargs": "^16.2.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-serializer": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.4.0.tgz", - "integrity": "sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "graceful-fs": "^4.2.4" + "strip-bom": "^4.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.4.5.tgz", - "integrity": "sha512-eCi/iM1YJFrJWiT9de4+RpWWWBqsHiYxFG9V9o/n0WXs6GpW4lUt4FAHAgFPTLPqCUVzrMQmSmTZSgQzwqR7IQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", + "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", "dev": true, "dependencies": { - "@babel/core": "^7.7.2", + "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", - "@babel/parser": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", - "@types/babel__traverse": "^7.0.4", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^27.4.2", - "graceful-fs": "^4.2.4", - "jest-diff": "^27.4.2", - "jest-get-type": "^27.4.0", - "jest-haste-map": "^27.4.5", - "jest-matcher-utils": "^27.4.2", - "jest-message-util": "^27.4.2", - "jest-resolve": "^27.4.5", - "jest-util": "^27.4.2", + "expect": "^29.5.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "natural-compare": "^1.4.0", - "pretty-format": "^27.4.2", - "semver": "^7.3.2" + "pretty-format": "^29.5.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/diff-sequences": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-diff": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -6078,43 +5514,43 @@ } }, "node_modules/jest-util": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.4.2.tgz", - "integrity": "sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", + "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.4.2.tgz", - "integrity": "sha512-hWYsSUej+Fs8ZhOm5vhWzwSLmVaPAxRy+Mr+z5MzeaHm9AxUpXdoVMEW4R86y5gOobVfBsMFLk4Rb+QkiEpx1A==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", + "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", + "@jest/types": "^29.5.0", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^27.4.0", + "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^27.4.2" + "pretty-format": "^29.5.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", - "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "engines": { "node": ">=10" @@ -6123,36 +5559,47 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/jest-validate/node_modules/jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "node_modules/jest-watcher": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.4.2.tgz", - "integrity": "sha512-NJvMVyyBeXfDezhWzUOCOYZrUmkSCiatpjpm+nFUid74OZEHk6aMLrZAukIiFDwdbqp6mTM6Ui1w4oc+8EobQg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", + "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", "dev": true, "dependencies": { - "@jest/test-result": "^27.4.2", - "@jest/types": "^27.4.2", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^27.4.2", + "emittery": "^0.13.1", + "jest-util": "^29.5.0", "string-length": "^4.0.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.5.tgz", - "integrity": "sha512-f2s8kEdy15cv9r7q4KkzGXvlY0JTcmCbMHZBfSQDwW77REr45IDWwd0lksDFeVHH2jJ5pqb90T77XscrjeGzzg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", + "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", "dev": true, "dependencies": { "@types/node": "*", + "jest-util": "^29.5.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-worker/node_modules/supports-color": { @@ -6189,52 +5636,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -6304,19 +5705,6 @@ "node": ">=6" } }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -6353,12 +5741,6 @@ "node": ">=8" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -6641,38 +6023,30 @@ "node": ">=6" } }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "node_modules/microbundle/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true, - "engines": { - "node": ">= 0.6" + "node": ">=4.2.0" } }, - "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "dependencies": { - "mime-db": "1.51.0" + "braces": "^3.0.2", + "picomatch": "^2.3.1" }, "engines": { - "node": ">= 0.6" + "node": ">=8.6" } }, "node_modules/mimic-fn": { @@ -6697,12 +6071,12 @@ } }, "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", + "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==", "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/mri": { @@ -6741,24 +6115,15 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true }, - "node_modules/node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/node-releases": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", @@ -6828,12 +6193,6 @@ "node": ">=0.10.0" } }, - "node_modules/nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", - "dev": true - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -6920,23 +6279,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -7040,12 +6382,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -7080,13 +6416,13 @@ "dev": true }, "node_modules/path-scurry": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", - "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", + "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", "dev": true, "dependencies": { - "lru-cache": "^9.0.0", - "minipass": "^5.0.0" + "lru-cache": "^9.1.1", + "minipass": "^5.0.0 || ^6.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -7096,9 +6432,9 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", - "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", + "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", "dev": true, "engines": { "node": "14 || >=16.14" @@ -7144,13 +6480,10 @@ } }, "node_modules/pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", "dev": true, - "dependencies": { - "node-modules-regexp": "^1.0.0" - }, "engines": { "node": ">= 6" } @@ -7726,25 +7059,19 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/pretty-bytes": { @@ -7760,18 +7087,17 @@ } }, "node_modules/pretty-format": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.4.2.tgz", - "integrity": "sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", "dev": true, "dependencies": { - "@jest/types": "^27.4.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.4.3", "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "react-is": "^18.0.0" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/pretty-format/node_modules/ansi-styles": { @@ -7808,20 +7134,21 @@ "node": ">= 6" } }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "node_modules/pure-rand": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", + "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", "dev": true, - "engines": { - "node": ">=6" - } + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] }, "node_modules/randombytes": { "version": "2.1.0", @@ -7833,9 +7160,9 @@ } }, "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "node_modules/regenerate": { @@ -7970,21 +7297,21 @@ } }, "node_modules/resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, "engines": { "node": ">=10" } }, "node_modules/rimraf": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", - "integrity": "sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", + "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", "dev": true, "dependencies": { - "glob": "^10.0.0" + "glob": "^10.2.5" }, "bin": { "rimraf": "dist/cjs/src/bin.js" @@ -8006,15 +7333,15 @@ } }, "node_modules/rimraf/node_modules/glob": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.2.tgz", - "integrity": "sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==", + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz", + "integrity": "sha512-U/rnDpXJGF414QQQZv5uVsabTVxMSwzS5CH0p3DRCIV6ownl4f7PzGnkGmvlum2wB+9RlJWJZ6ACU1INnBqiPA==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.0.3", - "minimatch": "^9.0.0", - "minipass": "^5.0.0", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2", "path-scurry": "^1.7.0" }, "bin": { @@ -8028,9 +7355,9 @@ } }, "node_modules/rimraf/node_modules/minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "dev": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -8244,20 +7571,6 @@ } } }, - "node_modules/rollup-plugin-visualizer/node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/rollup-plugin-visualizer/node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", @@ -8267,33 +7580,6 @@ "node": ">= 8" } }, - "node_modules/rollup-plugin-visualizer/node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/rollup-plugin-visualizer/node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, "node_modules/rollup-pluginutils": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", @@ -8347,24 +7633,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -8419,9 +7687,9 @@ } }, "node_modules/signal-exit": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.4.tgz", - "integrity": "sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, "node_modules/sisteransi": { @@ -8477,7 +7745,7 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "node_modules/stable": { @@ -8488,9 +7756,9 @@ "dev": true }, "node_modules/stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "dependencies": { "escape-string-regexp": "^2.0.0" @@ -8654,6 +7922,18 @@ "node": ">=6" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/style-inject": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", @@ -8688,19 +7968,6 @@ "node": ">=8" } }, - "node_modules/supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/svgo": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", @@ -8722,28 +7989,6 @@ "node": ">=10.13.0" } }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/terser": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.1.tgz", @@ -8782,12 +8027,6 @@ "node": ">=8" } }, - "node_modules/throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", - "dev": true - }, "node_modules/tiny-glob": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", @@ -8825,66 +8064,39 @@ "node": ">=8.0" } }, - "node_modules/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "dev": true, - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ts-jest": { - "version": "27.1.2", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.2.tgz", - "integrity": "sha512-eSOiJOWq6Hhs6Khzk5wKC5sgWIXgXqOCiIl1+3lfnearu58Hj4QpE5tUhQcA3xtZrELbcvAGCsd6HB8OsaVaTA==", + "version": "29.1.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", + "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", "dev": true, "dependencies": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", "semver": "7.x", - "yargs-parser": "20.x" + "yargs-parser": "^21.0.1" }, "bin": { "ts-jest": "cli.js" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { "@babel/core": ">=7.0.0-beta.0 <8", - "@types/jest": "^27.0.0", - "babel-jest": ">=27.0.0 <28", - "esbuild": "~0.14.0", - "jest": "^27.0.0", - "typescript": ">=3.8 <5.0" + "@jest/types": "^29.0.0", + "babel-jest": "^29.0.0", + "jest": "^29.0.0", + "typescript": ">=4.3 <6" }, "peerDependenciesMeta": { "@babel/core": { "optional": true }, - "@types/jest": { + "@jest/types": { "optional": true }, "babel-jest": { @@ -8913,18 +8125,6 @@ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "dev": true }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -8960,26 +8160,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, "node_modules/typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", + "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/unbox-primitive": { @@ -9037,15 +8228,6 @@ "node": ">=4" } }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/update-browserslist-db": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", @@ -9083,49 +8265,19 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz", - "integrity": "sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" + "convert-source-map": "^1.6.0" }, "engines": { "node": ">=10.12.0" } }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -9135,44 +8287,6 @@ "makeerror": "1.0.12" } }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true, - "engines": { - "node": ">=10.4" - } - }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "dependencies": { - "iconv-lite": "0.4.24" - } - }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -9224,15 +8338,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -9275,50 +8380,18 @@ "dev": true }, "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "dependencies": { "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/ws": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", - "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "signal-exit": "^3.0.7" }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -9344,30 +8417,42 @@ } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { - "version": "20.2.7", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", - "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } } }, @@ -10114,12 +9199,12 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.16.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.5.tgz", - "integrity": "sha512-/d4//lZ1Vqb4mZ5xTep3dDK888j7BGM/iKqBmndBaoYAFPlPKrGU608VVBz5JeyAb6YQDjRu1UKqj86UhwWVgw==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", + "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.16.5" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-transform-arrow-functions": { @@ -10683,14 +9768,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@esbuild/linux-loong64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz", - "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==", - "dev": true, - "optional": true, - "peer": true - }, "@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -10735,9 +9812,9 @@ } }, "strip-ansi": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", - "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "requires": { "ansi-regex": "^6.0.1" @@ -10776,204 +9853,238 @@ "dev": true }, "@jest/console": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.4.2.tgz", - "integrity": "sha512-xknHThRsPB/To1FUbi6pCe43y58qFC03zfb6R7fDb/FfC7k2R3i1l+izRBJf8DI46KhYGRaF14Eo9A3qbBoixg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", + "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", "dev": true, "requires": { - "@jest/types": "^27.4.2", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^27.4.2", - "jest-util": "^27.4.2", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0" } }, "@jest/core": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.4.5.tgz", - "integrity": "sha512-3tm/Pevmi8bDsgvo73nX8p/WPng6KWlCyScW10FPEoN1HU4pwI83tJ3TsFvi1FfzsjwUlMNEPowgb/rPau/LTQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", + "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", "dev": true, "requires": { - "@jest/console": "^27.4.2", - "@jest/reporters": "^27.4.5", - "@jest/test-result": "^27.4.2", - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", + "@jest/console": "^29.5.0", + "@jest/reporters": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "emittery": "^0.8.1", + "ci-info": "^3.2.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-changed-files": "^27.4.2", - "jest-config": "^27.4.5", - "jest-haste-map": "^27.4.5", - "jest-message-util": "^27.4.2", - "jest-regex-util": "^27.4.0", - "jest-resolve": "^27.4.5", - "jest-resolve-dependencies": "^27.4.5", - "jest-runner": "^27.4.5", - "jest-runtime": "^27.4.5", - "jest-snapshot": "^27.4.5", - "jest-util": "^27.4.2", - "jest-validate": "^27.4.2", - "jest-watcher": "^27.4.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.5.0", + "jest-config": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-resolve-dependencies": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", + "jest-watcher": "^29.5.0", "micromatch": "^4.0.4", - "rimraf": "^3.0.0", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } } }, "@jest/environment": { - "version": "27.4.4", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.4.4.tgz", - "integrity": "sha512-q+niMx7cJgt/t/b6dzLOh4W8Ef/8VyKG7hxASK39jakijJzbFBGpptx3RXz13FFV7OishQ9lTbv+dQ5K3EhfDQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", + "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", "dev": true, "requires": { - "@jest/fake-timers": "^27.4.2", - "@jest/types": "^27.4.2", + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-mock": "^27.4.2" + "jest-mock": "^29.5.0" + } + }, + "@jest/expect": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", + "dev": true, + "requires": { + "expect": "^29.5.0", + "jest-snapshot": "^29.5.0" + } + }, + "@jest/expect-utils": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", + "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "dev": true, + "requires": { + "jest-get-type": "^29.4.3" + }, + "dependencies": { + "jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true + } } }, "@jest/fake-timers": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.4.2.tgz", - "integrity": "sha512-f/Xpzn5YQk5adtqBgvw1V6bF8Nx3hY0OIRRpCvWcfPl0EAjdqWPdhH3t/3XpiWZqtjIEHDyMKP9ajpva1l4Zmg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", + "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", "dev": true, "requires": { - "@jest/types": "^27.4.2", - "@sinonjs/fake-timers": "^8.0.1", + "@jest/types": "^29.5.0", + "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^27.4.2", - "jest-mock": "^27.4.2", - "jest-util": "^27.4.2" + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" } }, "@jest/globals": { - "version": "27.4.4", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.4.4.tgz", - "integrity": "sha512-bqpqQhW30BOreXM8bA8t8JbOQzsq/WnPTnBl+It3UxAD9J8yxEAaBEylHx1dtBapAr/UBk8GidXbzmqnee8tYQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", + "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", "dev": true, "requires": { - "@jest/environment": "^27.4.4", - "@jest/types": "^27.4.2", - "expect": "^27.4.2" + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/types": "^29.5.0", + "jest-mock": "^29.5.0" } }, "@jest/reporters": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.4.5.tgz", - "integrity": "sha512-3orsG4vi8zXuBqEoy2LbnC1kuvkg1KQUgqNxmxpQgIOQEPeV0onvZu+qDQnEoX8qTQErtqn/xzcnbpeTuOLSiA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", + "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.4.2", - "@jest/test-result": "^27.4.2", - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", + "@jest/console": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", + "@jridgewell/trace-mapping": "^0.3.15", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.4", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.3", + "istanbul-lib-instrument": "^5.1.0", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "jest-haste-map": "^27.4.5", - "jest-resolve": "^27.4.5", - "jest-util": "^27.4.2", - "jest-worker": "^27.4.5", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "slash": "^3.0.0", - "source-map": "^0.6.0", "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.1.0" + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + } + }, + "@jest/schemas": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "dev": true, + "requires": { + "@sinclair/typebox": "^0.25.16" } }, "@jest/source-map": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.4.0.tgz", - "integrity": "sha512-Ntjx9jzP26Bvhbm93z/AKcPRj/9wrkI88/gK60glXDx1q+IeI0rf7Lw2c89Ch6ofonB0On/iRDreQuQ6te9pgQ==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", + "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", "dev": true, "requires": { + "@jridgewell/trace-mapping": "^0.3.15", "callsites": "^3.0.0", - "graceful-fs": "^4.2.4", - "source-map": "^0.6.0" + "graceful-fs": "^4.2.9" } }, "@jest/test-result": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.4.2.tgz", - "integrity": "sha512-kr+bCrra9jfTgxHXHa2UwoQjxvQk3Am6QbpAiJ5x/50LW8llOYrxILkqY0lZRW/hu8FXesnudbql263+EW9iNA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", + "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", "dev": true, "requires": { - "@jest/console": "^27.4.2", - "@jest/types": "^27.4.2", + "@jest/console": "^29.5.0", + "@jest/types": "^29.5.0", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.4.5.tgz", - "integrity": "sha512-n5woIn/1v+FT+9hniymHPARA9upYUmfi5Pw9ewVwXCDlK4F5/Gkees9v8vdjGdAIJ2MPHLHodiajLpZZanWzEQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", + "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", "dev": true, "requires": { - "@jest/test-result": "^27.4.2", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.4.5", - "jest-runtime": "^27.4.5" + "@jest/test-result": "^29.5.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", + "slash": "^3.0.0" } }, "@jest/transform": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.4.5.tgz", - "integrity": "sha512-PuMet2UlZtlGzwc6L+aZmR3I7CEBpqadO03pU40l2RNY2fFJ191b9/ITB44LNOhVtsyykx0OZvj0PCyuLm7Eew==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", + "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", "dev": true, "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.4.2", - "babel-plugin-istanbul": "^6.0.0", + "@babel/core": "^7.11.6", + "@jest/types": "^29.5.0", + "@jridgewell/trace-mapping": "^0.3.15", + "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.4.5", - "jest-regex-util": "^27.4.0", - "jest-util": "^27.4.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.5.0", "micromatch": "^4.0.4", - "pirates": "^4.0.1", + "pirates": "^4.0.4", "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" + "write-file-atomic": "^4.0.2" + }, + "dependencies": { + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + } } }, "@jest/types": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.4.2.tgz", - "integrity": "sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dev": true, "requires": { + "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", - "@types/yargs": "^16.0.0", + "@types/yargs": "^17.0.8", "chalk": "^4.0.0" } }, @@ -11117,22 +10228,28 @@ } } }, + "@sinclair/typebox": { + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "dev": true + }, "@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "requires": { "type-detect": "4.0.8" } }, "@sinonjs/fake-timers": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", - "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", + "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", "dev": true, "requires": { - "@sinonjs/commons": "^1.7.0" + "@sinonjs/commons": "^3.0.0" } }, "@surma/rollup-plugin-off-main-thread": { @@ -11147,12 +10264,6 @@ "string.prototype.matchall": "^4.0.6" } }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, "@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", @@ -11207,9 +10318,9 @@ "dev": true }, "@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", + "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==", "dev": true, "requires": { "@types/node": "*" @@ -11240,13 +10351,13 @@ } }, "@types/jest": { - "version": "27.0.2", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-27.0.2.tgz", - "integrity": "sha512-4dRxkS/AFX0c5XW6IPMNOydLn2tEhNhJV7DnYK+0bjoJZ+QTmfucBlihX7aoEsh/ocYtkLC73UbnBXBXIxsULA==", + "version": "29.5.2", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.2.tgz", + "integrity": "sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==", "dev": true, "requires": { - "jest-diff": "^27.0.0", - "pretty-format": "^27.0.0" + "expect": "^29.0.0", + "pretty-format": "^29.0.0" } }, "@types/node": { @@ -11262,9 +10373,9 @@ "dev": true }, "@types/prettier": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.2.tgz", - "integrity": "sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", "dev": true }, "@types/resolve": { @@ -11283,24 +10394,18 @@ "dev": true }, "@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "requires": { "@types/yargs-parser": "*" } }, "@types/yargs-parser": { - "version": "20.2.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", - "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", - "dev": true - }, - "abab": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", - "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", + "version": "21.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz", + "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, "acorn": { @@ -11309,39 +10414,6 @@ "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==", "dev": true }, - "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - }, - "dependencies": { - "acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true - } - } - }, - "acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "dev": true - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "requires": { - "debug": "4" - } - }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -11367,9 +10439,9 @@ } }, "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -11401,12 +10473,6 @@ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", "dev": true }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, "asyncro": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/asyncro/-/asyncro-3.0.0.tgz", @@ -11434,43 +10500,42 @@ "dev": true }, "babel-jest": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.4.5.tgz", - "integrity": "sha512-3uuUTjXbgtODmSv/DXO9nZfD52IyC2OYTFaXGRzL0kpykzroaquCrD5+lZNafTvZlnNqZHt5pb0M08qVBZnsnA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", + "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", "dev": true, "requires": { - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", + "@jest/transform": "^29.5.0", "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^27.4.0", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.5.0", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "slash": "^3.0.0" } }, "babel-plugin-istanbul": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", - "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" } }, "babel-plugin-jest-hoist": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.4.0.tgz", - "integrity": "sha512-Jcu7qS4OX5kTWBc45Hz7BMmgXuJqRnhatqpUhnzGC3OBYpOmf2tv6jFNwZpwM7wU7MUuv2r9IPS/ZlYOuburVw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", + "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", "dev": true, "requires": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", + "@types/babel__core": "^7.1.14", "@types/babel__traverse": "^7.0.6" } }, @@ -11551,12 +10616,12 @@ } }, "babel-preset-jest": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.4.0.tgz", - "integrity": "sha512-NK4jGYpnBvNxcGo7/ZpZJr51jCGT+3bwwpVIDY2oNfTxJJldRtB4VAcYdgp1loDE50ODuTu+yBjpMAswv5tlpg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", + "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^27.4.0", + "babel-plugin-jest-hoist": "^29.5.0", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -11600,12 +10665,6 @@ "duplexer": "0.1.1" } }, - "browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, "browserslist": { "version": "4.21.5", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", @@ -11705,9 +10764,9 @@ "dev": true }, "ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true }, "cjs-module-lexer": { @@ -11717,20 +10776,20 @@ "dev": true }, "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "requires": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", "dev": true }, "collect-v8-coverage": { @@ -11760,15 +10819,6 @@ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, "commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", @@ -11944,40 +10994,6 @@ "css-tree": "^1.1.2" } }, - "cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", - "dev": true - }, - "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dev": true, - "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } - } - }, - "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - } - }, "debug": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", @@ -11987,22 +11003,10 @@ "ms": "2.1.2" } }, - "decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", - "dev": true - }, "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", - "dev": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, "deepmerge": { @@ -12027,24 +11031,12 @@ "object-keys": "^1.1.1" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", "dev": true }, - "diff-sequences": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.4.0.tgz", - "integrity": "sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==", - "dev": true - }, "dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", @@ -12062,23 +11054,6 @@ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true }, - "domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "requires": { - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } - } - }, "domhandler": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", @@ -12127,9 +11102,9 @@ "dev": true }, "emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", "dev": true }, "emoji-regex": { @@ -12217,197 +11192,6 @@ "is-symbol": "^1.0.2" } }, - "esbuild": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.54.tgz", - "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "@esbuild/linux-loong64": "0.14.54", - "esbuild-android-64": "0.14.54", - "esbuild-android-arm64": "0.14.54", - "esbuild-darwin-64": "0.14.54", - "esbuild-darwin-arm64": "0.14.54", - "esbuild-freebsd-64": "0.14.54", - "esbuild-freebsd-arm64": "0.14.54", - "esbuild-linux-32": "0.14.54", - "esbuild-linux-64": "0.14.54", - "esbuild-linux-arm": "0.14.54", - "esbuild-linux-arm64": "0.14.54", - "esbuild-linux-mips64le": "0.14.54", - "esbuild-linux-ppc64le": "0.14.54", - "esbuild-linux-riscv64": "0.14.54", - "esbuild-linux-s390x": "0.14.54", - "esbuild-netbsd-64": "0.14.54", - "esbuild-openbsd-64": "0.14.54", - "esbuild-sunos-64": "0.14.54", - "esbuild-windows-32": "0.14.54", - "esbuild-windows-64": "0.14.54", - "esbuild-windows-arm64": "0.14.54" - } - }, - "esbuild-android-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz", - "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-android-arm64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz", - "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-darwin-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz", - "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-darwin-arm64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz", - "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-freebsd-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz", - "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-freebsd-arm64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz", - "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-linux-32": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz", - "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-linux-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz", - "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-linux-arm": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz", - "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-linux-arm64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz", - "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-linux-mips64le": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz", - "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-linux-ppc64le": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz", - "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-linux-riscv64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz", - "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-linux-s390x": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz", - "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-netbsd-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz", - "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-openbsd-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz", - "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-sunos-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz", - "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-windows-32": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz", - "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-windows-64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz", - "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==", - "dev": true, - "optional": true, - "peer": true - }, - "esbuild-windows-arm64": { - "version": "0.14.54", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz", - "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==", - "dev": true, - "optional": true, - "peer": true - }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -12420,31 +11204,12 @@ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", "dev": true }, - "escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dev": true, - "requires": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", @@ -12483,27 +11248,26 @@ "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", "dev": true }, "expect": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.4.2.tgz", - "integrity": "sha512-BjAXIDC6ZOW+WBFNg96J22D27Nq5ohn+oGcuP2rtOtcjuxNoV9McpQ60PcQWhdFOSBIQdR72e+4HdnbZTFSTyg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", "dev": true, "requires": { - "@jest/types": "^27.4.2", - "ansi-styles": "^5.0.0", - "jest-get-type": "^27.4.0", - "jest-matcher-utils": "^27.4.2", - "jest-message-util": "^27.4.2", - "jest-regex-util": "^27.4.0" + "@jest/expect-utils": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0" }, "dependencies": { - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", "dev": true } } @@ -12514,16 +11278,10 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, "fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, "requires": { "bser": "2.1.1" @@ -12632,24 +11390,13 @@ }, "dependencies": { "signal-exit": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz", - "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.2.tgz", + "integrity": "sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==", "dev": true } } }, - "form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, "fraction.js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", @@ -12817,9 +11564,9 @@ } }, "graceful-fs": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", - "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "gzip-size": { @@ -12907,57 +11654,18 @@ "has-symbols": "^1.0.2" } }, - "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.5" - } - }, "html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - } - }, "human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", "dev": true }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, "icss-replace-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", @@ -13008,9 +11716,9 @@ } }, "import-local": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", - "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", + "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", "dev": true, "requires": { "pkg-dir": "^4.2.0", @@ -13020,7 +11728,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true }, "inflight": { @@ -13155,12 +11863,6 @@ "has-tostringtag": "^1.0.0" } }, - "is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true - }, "is-reference": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", @@ -13226,12 +11928,6 @@ "has-tostringtag": "^1.0.0" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, "is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -13257,20 +11953,21 @@ "dev": true }, "istanbul-lib-coverage": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.1.tgz", - "integrity": "sha512-GvCYYTxaCPqwMjobtVcVKvSHtAGe48MNhGjpK8LtVF8K0ISX7hCKl85LgtuaSneWVyQmaGcW3iXVV3GaZSLpmQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true }, "istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", "dev": true, "requires": { - "@babel/core": "^7.7.5", + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" } }, @@ -13297,9 +11994,9 @@ } }, "istanbul-reports": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.1.tgz", - "integrity": "sha512-q1kvhAXWSsXfMjCdNHNPKZZv94OlspKnoGv+R9RGbnqOOQ0VbNfLFgQDVgi7hHenKsndGq3/o0OBdzDXthWcNw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -13307,9 +12004,9 @@ } }, "jackspeak": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.0.tgz", - "integrity": "sha512-r5XBrqIJfwRIjRt/Xr5fv9Wh09qyhHfKnYddDlpM+ibRR20qrYActpCAgU6U+d53EOEjzkvxPMVHSlgR7leXrQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.2.1.tgz", + "integrity": "sha512-MXbxovZ/Pm42f6cDIDkl3xpwv1AGwObKwfmjs2nQePiy85tP3fatofl3FC1aBsOtP/6fq5SbtgHwWcMsLP+bDw==", "dev": true, "requires": { "@isaacs/cliui": "^8.0.2", @@ -13329,421 +12026,462 @@ } }, "jest": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.4.5.tgz", - "integrity": "sha512-uT5MiVN3Jppt314kidCk47MYIRilJjA/l2mxwiuzzxGUeJIvA8/pDaJOAX5KWvjAo7SCydcW0/4WEtgbLMiJkg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", + "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", "dev": true, "requires": { - "@jest/core": "^27.4.5", + "@jest/core": "^29.5.0", + "@jest/types": "^29.5.0", "import-local": "^3.0.2", - "jest-cli": "^27.4.5" + "jest-cli": "^29.5.0" } }, "jest-changed-files": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.4.2.tgz", - "integrity": "sha512-/9x8MjekuzUQoPjDHbBiXbNEBauhrPU2ct7m8TfCg69ywt1y/N+yYwGh3gCpnqUS3klYWDU/lSNgv+JhoD2k1A==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", + "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", "dev": true, "requires": { - "@jest/types": "^27.4.2", "execa": "^5.0.0", - "throat": "^6.0.1" + "p-limit": "^3.1.0" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + } } }, "jest-circus": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.4.5.tgz", - "integrity": "sha512-eTNWa9wsvBwPykhMMShheafbwyakcdHZaEYh5iRrQ0PFJxkDP/e3U/FvzGuKWu2WpwUA3C3hPlfpuzvOdTVqnw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", + "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", "dev": true, "requires": { - "@jest/environment": "^27.4.4", - "@jest/test-result": "^27.4.2", - "@jest/types": "^27.4.2", + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", - "expect": "^27.4.2", "is-generator-fn": "^2.0.0", - "jest-each": "^27.4.2", - "jest-matcher-utils": "^27.4.2", - "jest-message-util": "^27.4.2", - "jest-runtime": "^27.4.5", - "jest-snapshot": "^27.4.5", - "jest-util": "^27.4.2", - "pretty-format": "^27.4.2", + "jest-each": "^29.5.0", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.5.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" + "stack-utils": "^2.0.3" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + } } }, "jest-cli": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.4.5.tgz", - "integrity": "sha512-hrky3DSgE0u7sQxaCL7bdebEPHx5QzYmrGuUjaPLmPE8jx5adtvGuOlRspvMoVLTTDOHRnZDoRLYJuA+VCI7Hg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", + "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", "dev": true, "requires": { - "@jest/core": "^27.4.5", - "@jest/test-result": "^27.4.2", - "@jest/types": "^27.4.2", + "@jest/core": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", "exit": "^0.1.2", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^27.4.5", - "jest-util": "^27.4.2", - "jest-validate": "^27.4.2", + "jest-config": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "prompts": "^2.0.1", - "yargs": "^16.2.0" + "yargs": "^17.3.1" } }, "jest-config": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.4.5.tgz", - "integrity": "sha512-t+STVJtPt+fpqQ8GBw850NtSQbnDOw/UzdPfzDaHQ48/AylQlW7LHj3dH+ndxhC1UxJ0Q3qkq7IH+nM1skwTwA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", + "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", "dev": true, "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^27.4.5", - "@jest/types": "^27.4.2", - "babel-jest": "^27.4.5", + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.5.0", + "@jest/types": "^29.5.0", + "babel-jest": "^29.5.0", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.4", - "jest-circus": "^27.4.5", - "jest-environment-jsdom": "^27.4.4", - "jest-environment-node": "^27.4.4", - "jest-get-type": "^27.4.0", - "jest-jasmine2": "^27.4.5", - "jest-regex-util": "^27.4.0", - "jest-resolve": "^27.4.5", - "jest-runner": "^27.4.5", - "jest-util": "^27.4.2", - "jest-validate": "^27.4.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.5.0", + "jest-environment-node": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "micromatch": "^4.0.4", - "pretty-format": "^27.4.2", - "slash": "^3.0.0" - } - }, - "jest-diff": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.4.2.tgz", - "integrity": "sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^27.4.0", - "jest-get-type": "^27.4.0", - "pretty-format": "^27.4.2" + "parse-json": "^5.2.0", + "pretty-format": "^29.5.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true + } } }, "jest-docblock": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.4.0.tgz", - "integrity": "sha512-7TBazUdCKGV7svZ+gh7C8esAnweJoG+SvcF6Cjqj4l17zA2q1cMwx2JObSioubk317H+cjcHgP+7fTs60paulg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.4.3.tgz", + "integrity": "sha512-fzdTftThczeSD9nZ3fzA/4KkHtnmllawWrXO69vtI+L9WjEIuXWs4AmyME7lN5hU7dB0sHhuPfcKofRsUb/2Fg==", "dev": true, "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.4.2.tgz", - "integrity": "sha512-53V2MNyW28CTruB3lXaHNk6PkiIFuzdOC9gR3C6j8YE/ACfrPnz+slB0s17AgU1TtxNzLuHyvNlLJ+8QYw9nBg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", + "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", "dev": true, "requires": { - "@jest/types": "^27.4.2", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", - "jest-get-type": "^27.4.0", - "jest-util": "^27.4.2", - "pretty-format": "^27.4.2" - } - }, - "jest-environment-jsdom": { - "version": "27.4.4", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.4.4.tgz", - "integrity": "sha512-cYR3ndNfHBqQgFvS1RL7dNqSvD//K56j/q1s2ygNHcfTCAp12zfIromO1w3COmXrxS8hWAh7+CmZmGCIoqGcGA==", - "dev": true, - "requires": { - "@jest/environment": "^27.4.4", - "@jest/fake-timers": "^27.4.2", - "@jest/types": "^27.4.2", - "@types/node": "*", - "jest-mock": "^27.4.2", - "jest-util": "^27.4.2", - "jsdom": "^16.6.0" + "jest-get-type": "^29.4.3", + "jest-util": "^29.5.0", + "pretty-format": "^29.5.0" + }, + "dependencies": { + "jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true + } } }, "jest-environment-node": { - "version": "27.4.4", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.4.4.tgz", - "integrity": "sha512-D+v3lbJ2GjQTQR23TK0kY3vFVmSeea05giInI41HHOaJnAwOnmUHTZgUaZL+VxUB43pIzoa7PMwWtCVlIUoVoA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", + "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", "dev": true, "requires": { - "@jest/environment": "^27.4.4", - "@jest/fake-timers": "^27.4.2", - "@jest/types": "^27.4.2", + "@jest/environment": "^29.5.0", + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-mock": "^27.4.2", - "jest-util": "^27.4.2" + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" } }, - "jest-get-type": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.4.0.tgz", - "integrity": "sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==", - "dev": true - }, "jest-haste-map": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.4.5.tgz", - "integrity": "sha512-oJm1b5qhhPs78K24EDGifWS0dELYxnoBiDhatT/FThgB9yxqUm5F6li3Pv+Q+apMBmmPNzOBnZ7ZxWMB1Leq1Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", + "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", "dev": true, "requires": { - "@jest/types": "^27.4.2", - "@types/graceful-fs": "^4.1.2", + "@jest/types": "^29.5.0", + "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", - "graceful-fs": "^4.2.4", - "jest-regex-util": "^27.4.0", - "jest-serializer": "^27.4.0", - "jest-util": "^27.4.2", - "jest-worker": "^27.4.5", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "micromatch": "^4.0.4", - "walker": "^1.0.7" - } - }, - "jest-jasmine2": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.4.5.tgz", - "integrity": "sha512-oUnvwhJDj2LhOiUB1kdnJjkx8C5PwgUZQb9urF77mELH9DGR4e2GqpWQKBOYXWs5+uTN9BGDqRz3Aeg5Wts7aw==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^27.4.4", - "@jest/source-map": "^27.4.0", - "@jest/test-result": "^27.4.2", - "@jest/types": "^27.4.2", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.4.2", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.4.2", - "jest-matcher-utils": "^27.4.2", - "jest-message-util": "^27.4.2", - "jest-runtime": "^27.4.5", - "jest-snapshot": "^27.4.5", - "jest-util": "^27.4.2", - "pretty-format": "^27.4.2", - "throat": "^6.0.1" + "walker": "^1.0.8" } }, "jest-leak-detector": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.4.2.tgz", - "integrity": "sha512-ml0KvFYZllzPBJWDei3mDzUhyp/M4ubKebX++fPaudpe8OsxUE+m+P6ciVLboQsrzOCWDjE20/eXew9QMx/VGw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", + "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", "dev": true, "requires": { - "jest-get-type": "^27.4.0", - "pretty-format": "^27.4.2" + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" + }, + "dependencies": { + "jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true + } } }, "jest-matcher-utils": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.4.2.tgz", - "integrity": "sha512-jyP28er3RRtMv+fmYC/PKG8wvAmfGcSNproVTW2Y0P/OY7/hWUOmsPfxN1jOhM+0u2xU984u2yEagGivz9OBGQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", + "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^27.4.2", - "jest-get-type": "^27.4.0", - "pretty-format": "^27.4.2" + "jest-diff": "^29.5.0", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" + }, + "dependencies": { + "diff-sequences": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "dev": true + }, + "jest-diff": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" + } + }, + "jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true + } } }, "jest-message-util": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.4.2.tgz", - "integrity": "sha512-OMRqRNd9E0DkBLZpFtZkAGYOXl6ZpoMtQJWTAREJKDOFa0M6ptB7L67tp+cszMBkvSgKOhNtQp2Vbcz3ZZKo/w==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", + "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.4.2", + "@jest/types": "^29.5.0", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^27.4.2", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.4.2.tgz", - "integrity": "sha512-PDDPuyhoukk20JrQKeofK12hqtSka7mWH0QQuxSNgrdiPsrnYYLS6wbzu/HDlxZRzji5ylLRULeuI/vmZZDrYA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", + "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", "dev": true, "requires": { - "@jest/types": "^27.4.2", - "@types/node": "*" + "@jest/types": "^29.5.0", + "@types/node": "*", + "jest-util": "^29.5.0" } }, "jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", "dev": true, "requires": {} }, "jest-regex-util": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.4.0.tgz", - "integrity": "sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", + "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", "dev": true }, "jest-resolve": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.4.5.tgz", - "integrity": "sha512-xU3z1BuOz/hUhVUL+918KqUgK+skqOuUsAi7A+iwoUldK6/+PW+utK8l8cxIWT9AW7IAhGNXjSAh1UYmjULZZw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", + "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", "dev": true, "requires": { - "@jest/types": "^27.4.2", "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.4.5", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.4.2", - "jest-validate": "^27.4.2", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "resolve": "^1.20.0", - "resolve.exports": "^1.1.0", + "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.4.5.tgz", - "integrity": "sha512-elEVvkvRK51y037NshtEkEnukMBWvlPzZHiL847OrIljJ8yIsujD2GXRPqDXC4rEVKbcdsy7W0FxoZb4WmEs7w==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", + "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", "dev": true, "requires": { - "@jest/types": "^27.4.2", - "jest-regex-util": "^27.4.0", - "jest-snapshot": "^27.4.5" + "jest-regex-util": "^29.4.3", + "jest-snapshot": "^29.5.0" } }, "jest-runner": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.4.5.tgz", - "integrity": "sha512-/irauncTfmY1WkTaRQGRWcyQLzK1g98GYG/8QvIPviHgO1Fqz1JYeEIsSfF+9mc/UTA6S+IIHFgKyvUrtiBIZg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", + "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", "dev": true, "requires": { - "@jest/console": "^27.4.2", - "@jest/environment": "^27.4.4", - "@jest/test-result": "^27.4.2", - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", + "@jest/console": "^29.5.0", + "@jest/environment": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-docblock": "^27.4.0", - "jest-environment-jsdom": "^27.4.4", - "jest-environment-node": "^27.4.4", - "jest-haste-map": "^27.4.5", - "jest-leak-detector": "^27.4.2", - "jest-message-util": "^27.4.2", - "jest-resolve": "^27.4.5", - "jest-runtime": "^27.4.5", - "jest-util": "^27.4.2", - "jest-worker": "^27.4.5", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.4.3", + "jest-environment-node": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-leak-detector": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-resolve": "^29.5.0", + "jest-runtime": "^29.5.0", + "jest-util": "^29.5.0", + "jest-watcher": "^29.5.0", + "jest-worker": "^29.5.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "dependencies": { + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } } }, "jest-runtime": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.4.5.tgz", - "integrity": "sha512-CIYqwuJQXHQtPd/idgrx4zgJ6iCb6uBjQq1RSAGQrw2S8XifDmoM1Ot8NRd80ooAm+ZNdHVwsktIMGlA1F1FAQ==", - "dev": true, - "requires": { - "@jest/console": "^27.4.2", - "@jest/environment": "^27.4.4", - "@jest/globals": "^27.4.4", - "@jest/source-map": "^27.4.0", - "@jest/test-result": "^27.4.2", - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", - "@types/yargs": "^16.0.0", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", + "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", + "dev": true, + "requires": { + "@jest/environment": "^29.5.0", + "@jest/fake-timers": "^29.5.0", + "@jest/globals": "^29.5.0", + "@jest/source-map": "^29.4.3", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", - "execa": "^5.0.0", - "exit": "^0.1.2", "glob": "^7.1.3", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.4.5", - "jest-message-util": "^27.4.2", - "jest-mock": "^27.4.2", - "jest-regex-util": "^27.4.0", - "jest-resolve": "^27.4.5", - "jest-snapshot": "^27.4.5", - "jest-util": "^27.4.2", - "jest-validate": "^27.4.2", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", + "jest-regex-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0", - "strip-bom": "^4.0.0", - "yargs": "^16.2.0" - } - }, - "jest-serializer": { - "version": "27.4.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.4.0.tgz", - "integrity": "sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ==", - "dev": true, - "requires": { - "@types/node": "*", - "graceful-fs": "^4.2.4" + "strip-bom": "^4.0.0" } }, "jest-snapshot": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.4.5.tgz", - "integrity": "sha512-eCi/iM1YJFrJWiT9de4+RpWWWBqsHiYxFG9V9o/n0WXs6GpW4lUt4FAHAgFPTLPqCUVzrMQmSmTZSgQzwqR7IQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", + "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", "dev": true, "requires": { - "@babel/core": "^7.7.2", + "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", - "@babel/parser": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.4.5", - "@jest/types": "^27.4.2", - "@types/babel__traverse": "^7.0.4", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", + "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^27.4.2", - "graceful-fs": "^4.2.4", - "jest-diff": "^27.4.2", - "jest-get-type": "^27.4.0", - "jest-haste-map": "^27.4.5", - "jest-matcher-utils": "^27.4.2", - "jest-message-util": "^27.4.2", - "jest-resolve": "^27.4.5", - "jest-util": "^27.4.2", + "expect": "^29.5.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.5.0", + "jest-get-type": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "natural-compare": "^1.4.0", - "pretty-format": "^27.4.2", - "semver": "^7.3.2" + "pretty-format": "^29.5.0", + "semver": "^7.3.5" }, "dependencies": { + "diff-sequences": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "dev": true + }, + "jest-diff": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^29.4.3", + "jest-get-type": "^29.4.3", + "pretty-format": "^29.5.0" + } + }, + "jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", + "dev": true + }, "semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -13752,63 +12490,71 @@ } }, "jest-util": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.4.2.tgz", - "integrity": "sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", + "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", "dev": true, "requires": { - "@jest/types": "^27.4.2", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", - "graceful-fs": "^4.2.4", + "graceful-fs": "^4.2.9", "picomatch": "^2.2.3" } }, "jest-validate": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.4.2.tgz", - "integrity": "sha512-hWYsSUej+Fs8ZhOm5vhWzwSLmVaPAxRy+Mr+z5MzeaHm9AxUpXdoVMEW4R86y5gOobVfBsMFLk4Rb+QkiEpx1A==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", + "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", "dev": true, "requires": { - "@jest/types": "^27.4.2", + "@jest/types": "^29.5.0", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^27.4.0", + "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^27.4.2" + "pretty-format": "^29.5.0" }, "dependencies": { "camelcase": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", - "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "jest-get-type": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.4.3.tgz", + "integrity": "sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==", "dev": true } } }, "jest-watcher": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.4.2.tgz", - "integrity": "sha512-NJvMVyyBeXfDezhWzUOCOYZrUmkSCiatpjpm+nFUid74OZEHk6aMLrZAukIiFDwdbqp6mTM6Ui1w4oc+8EobQg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", + "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", "dev": true, "requires": { - "@jest/test-result": "^27.4.2", - "@jest/types": "^27.4.2", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^27.4.2", + "emittery": "^0.13.1", + "jest-util": "^29.5.0", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "27.4.5", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.5.tgz", - "integrity": "sha512-f2s8kEdy15cv9r7q4KkzGXvlY0JTcmCbMHZBfSQDwW77REr45IDWwd0lksDFeVHH2jJ5pqb90T77XscrjeGzzg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", + "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", "dev": true, "requires": { "@types/node": "*", + "jest-util": "^29.5.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -13840,41 +12586,6 @@ "esprima": "^4.0.0" } }, - "jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dev": true, - "requires": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - } - }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", @@ -13923,16 +12634,6 @@ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", "dev": true }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, "lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -13960,12 +12661,6 @@ "p-locate": "^4.1.0" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -14195,32 +12890,23 @@ "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", "dev": true + }, + "typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true } } }, "micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - } - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", - "dev": true - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dev": true, "requires": { - "mime-db": "1.51.0" + "braces": "^3.0.2", + "picomatch": "^2.3.1" } }, "mimic-fn": { @@ -14239,9 +12925,9 @@ } }, "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-6.0.2.tgz", + "integrity": "sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w==", "dev": true }, "mri": { @@ -14265,19 +12951,13 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", - "dev": true - }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", "dev": true }, "node-releases": { @@ -14328,12 +13008,6 @@ "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", "dev": true }, - "nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", - "dev": true - }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -14393,20 +13067,6 @@ "is-wsl": "^2.2.0" } }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -14477,12 +13137,6 @@ "lines-and-columns": "^1.1.6" } }, - "parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", - "dev": true - }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -14508,19 +13162,19 @@ "dev": true }, "path-scurry": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", - "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.9.2.tgz", + "integrity": "sha512-qSDLy2aGFPm8i4rsbHd4MNyTcrzHFsLQykrtbuGRknZZCBBVXSv2tSCDN2Cg6Rt/GFRw8GoW9y9Ecw5rIPG1sg==", "dev": true, "requires": { - "lru-cache": "^9.0.0", - "minipass": "^5.0.0" + "lru-cache": "^9.1.1", + "minipass": "^5.0.0 || ^6.0.2" }, "dependencies": { "lru-cache": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", - "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.2.tgz", + "integrity": "sha512-ERJq3FOzJTxBbFjZ7iDs+NiK4VI9Wz+RdrrAB8dio1oV+YvdPzUEE4QNiT2VD51DkIbCYRUUzCRkssXCHqSnKQ==", "dev": true } } @@ -14550,13 +13204,10 @@ "dev": true }, "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, - "requires": { - "node-modules-regexp": "^1.0.0" - } + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", + "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "dev": true }, "pkg-dir": { "version": "4.2.0", @@ -14907,16 +13558,10 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, "prettier": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz", - "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true }, "pretty-bytes": { @@ -14926,15 +13571,14 @@ "dev": true }, "pretty-format": { - "version": "27.4.2", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.4.2.tgz", - "integrity": "sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", "dev": true, "requires": { - "@jest/types": "^27.4.2", - "ansi-regex": "^5.0.1", + "@jest/schemas": "^29.4.3", "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "react-is": "^18.0.0" }, "dependencies": { "ansi-styles": { @@ -14961,16 +13605,10 @@ "sisteransi": "^1.0.5" } }, - "psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "pure-rand": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", + "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", "dev": true }, "randombytes": { @@ -14983,9 +13621,9 @@ } }, "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, "regenerate": { @@ -15092,18 +13730,18 @@ "dev": true }, "resolve.exports": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", - "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true }, "rimraf": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", - "integrity": "sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.1.tgz", + "integrity": "sha512-OfFZdwtd3lZ+XZzYP/6gTACubwFcHdLRqS9UX3UwpU2dnGQYkPFISRwvM3w9IiB2w7bW5qGo/uAwE4SmXXSKvg==", "dev": true, "requires": { - "glob": "^10.0.0" + "glob": "^10.2.5" }, "dependencies": { "brace-expansion": { @@ -15116,22 +13754,22 @@ } }, "glob": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.2.tgz", - "integrity": "sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==", + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.6.tgz", + "integrity": "sha512-U/rnDpXJGF414QQQZv5uVsabTVxMSwzS5CH0p3DRCIV6ownl4f7PzGnkGmvlum2wB+9RlJWJZ6ACU1INnBqiPA==", "dev": true, "requires": { "foreground-child": "^3.1.0", "jackspeak": "^2.0.3", - "minimatch": "^9.0.0", - "minipass": "^5.0.0", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2", "path-scurry": "^1.7.0" } }, "minimatch": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", - "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -15289,43 +13927,11 @@ "yargs": "^17.5.1" }, "dependencies": { - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, "source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true - }, - "yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - } - }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true } } }, @@ -15378,21 +13984,6 @@ "is-regex": "^1.1.4" } }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -15435,9 +14026,9 @@ } }, "signal-exit": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.4.tgz", - "integrity": "sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q==", + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, "sisteransi": { @@ -15483,7 +14074,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "stable": { @@ -15493,9 +14084,9 @@ "dev": true }, "stack-utils": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", - "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", "dev": true, "requires": { "escape-string-regexp": "^2.0.0" @@ -15618,6 +14209,12 @@ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "style-inject": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", @@ -15643,16 +14240,6 @@ "has-flag": "^4.0.0" } }, - "supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dev": true, - "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - } - }, "svgo": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", @@ -15668,22 +14255,6 @@ "stable": "^0.1.8" } }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true - }, - "terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - } - }, "terser": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.1.tgz", @@ -15715,12 +14286,6 @@ "minimatch": "^3.0.4" } }, - "throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", - "dev": true - }, "tiny-glob": { "version": "0.2.9", "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", @@ -15752,40 +14317,20 @@ "is-number": "^7.0.0" } }, - "tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "dev": true, - "requires": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - } - }, - "tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, "ts-jest": { - "version": "27.1.2", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.1.2.tgz", - "integrity": "sha512-eSOiJOWq6Hhs6Khzk5wKC5sgWIXgXqOCiIl1+3lfnearu58Hj4QpE5tUhQcA3xtZrELbcvAGCsd6HB8OsaVaTA==", + "version": "29.1.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", + "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", "dev": true, "requires": { "bs-logger": "0.x", "fast-json-stable-stringify": "2.x", - "jest-util": "^27.0.0", - "json5": "2.x", + "jest-util": "^29.0.0", + "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", "semver": "7.x", - "yargs-parser": "20.x" + "yargs-parser": "^21.0.1" }, "dependencies": { "semver": { @@ -15802,15 +14347,6 @@ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", "dev": true }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -15834,19 +14370,10 @@ "is-typed-array": "^1.1.9" } }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, "typescript": { - "version": "4.8.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", - "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", + "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", "dev": true }, "unbox-primitive": { @@ -15889,12 +14416,6 @@ "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", "dev": true }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, "update-browserslist-db": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", @@ -15912,40 +14433,14 @@ "dev": true }, "v8-to-istanbul": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz", - "integrity": "sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "requires": { + "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "dependencies": { - "source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true - } - } - }, - "w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "requires": { - "browser-process-hrtime": "^1.0.0" - } - }, - "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "requires": { - "xml-name-validator": "^3.0.0" + "convert-source-map": "^1.6.0" } }, "walker": { @@ -15957,38 +14452,6 @@ "makeerror": "1.0.12" } }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dev": true, - "requires": { - "iconv-lite": "0.4.24" - } - }, - "whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", - "dev": true - }, - "whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dev": true, - "requires": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -16025,12 +14488,6 @@ "is-typed-array": "^1.1.10" } }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -16060,36 +14517,15 @@ "dev": true }, "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", "dev": true, "requires": { "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "signal-exit": "^3.0.7" } }, - "ws": { - "version": "7.5.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", - "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==", - "dev": true, - "requires": {} - }, - "xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "dev": true - }, - "xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true - }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -16109,24 +14545,30 @@ "dev": true }, "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" } }, "yargs-parser": { - "version": "20.2.7", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.7.tgz", - "integrity": "sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true } } diff --git a/package.json b/package.json index 91969ea4..ae08a7c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ts-pattern", - "version": "4.3.0", + "version": "5.0.0", "description": " The exhaustive Pattern Matching library for TypeScript.", "type": "module", "source": "src/index.ts", @@ -24,7 +24,7 @@ "module": "dist/index.js", "unpkg": "dist/index.umd.js", "scripts": { - "build": "rimraf dist && microbundle && sh ./scripts/generate-cts.sh", + "build": "rimraf dist && microbundle --format modern,cjs,umd && sh ./scripts/generate-cts.sh", "dev": "microbundle watch", "prepublishOnly": "npm run test && npm run build", "test": "jest", @@ -58,12 +58,12 @@ }, "homepage": "https://github.com/gvergnaud/ts-pattern#readme", "devDependencies": { - "@types/jest": "^27.0.2", - "jest": "^27.4.5", + "@types/jest": "^29.5.2", + "jest": "^29.5.0", "microbundle": "^0.15.1", - "prettier": "^2.5.1", - "rimraf": "^5.0.0", - "ts-jest": "^27.1.2", - "typescript": "^4.8.3" + "prettier": "^2.8.8", + "rimraf": "^5.0.1", + "ts-jest": "^29.1.0", + "typescript": "^5.1.3" } } diff --git a/src/internals/helpers.ts b/src/internals/helpers.ts index ca03ba7f..4c188988 100644 --- a/src/internals/helpers.ts +++ b/src/internals/helpers.ts @@ -6,7 +6,7 @@ import * as symbols from './symbols'; import { SelectionType } from '../types/FindSelected'; -import { Pattern, Matcher, MatcherType } from '../types/Pattern'; +import { Pattern, Matcher, MatcherType, AnyMatcher } from '../types/Pattern'; // @internal export const isObject = (value: unknown): value is Object => @@ -30,25 +30,72 @@ const isOptionalPattern = ( // tells us if the value matches a given pattern. // @internal export const matchPattern = ( - pattern: Pattern, + pattern: any, value: any, select: (key: string, value: unknown) => void ): boolean => { - if (isObject(pattern)) { - if (isMatcher(pattern)) { - const matcher = pattern[symbols.matcher](); - const { matched, selections } = matcher.match(value); - if (matched && selections) { - Object.keys(selections).forEach((key) => select(key, selections[key])); - } - return matched; + if (isMatcher(pattern)) { + const matcher = pattern[symbols.matcher](); + const { matched, selections } = matcher.match(value); + if (matched && selections) { + Object.keys(selections).forEach((key) => select(key, selections[key])); } + return matched; + } + if (isObject(pattern)) { if (!isObject(value)) return false; + // Tuple pattern if (Array.isArray(pattern)) { if (!Array.isArray(value)) return false; - // Tuple pattern + let startPatterns = []; + let endPatterns = []; + let variadicPatterns: AnyMatcher[] = []; + + for (const i of pattern.keys()) { + const subpattern = pattern[i]; + if (isMatcher(subpattern) && subpattern[symbols.isVariadic]) { + variadicPatterns.push(subpattern); + } else if (variadicPatterns.length) { + endPatterns.push(subpattern); + } else { + startPatterns.push(subpattern); + } + } + + if (variadicPatterns.length) { + if (variadicPatterns.length > 1) { + throw new Error( + `Pattern error: Using \`...P.array(...)\` several times in a single pattern is not allowed.` + ); + } + + if (value.length < startPatterns.length + endPatterns.length) { + return false; + } + + const startValues = value.slice(0, startPatterns.length); + const endValues = + endPatterns.length === 0 ? [] : value.slice(-endPatterns.length); + const middleValues = value.slice( + startPatterns.length, + endPatterns.length === 0 ? Infinity : -endPatterns.length + ); + + return ( + startPatterns.every((subPattern, i) => + matchPattern(subPattern, startValues[i], select) + ) && + endPatterns.every((subPattern, i) => + matchPattern(subPattern, endValues[i], select) + ) && + (variadicPatterns.length === 0 + ? true + : matchPattern(variadicPatterns[0], middleValues, select)) + ); + } + return pattern.length === value.length ? pattern.every((subPattern, i) => matchPattern(subPattern, value[i], select) @@ -56,32 +103,6 @@ export const matchPattern = ( : false; } - if (pattern instanceof Map) { - if (!(value instanceof Map)) return false; - return Array.from(pattern.keys()).every((key) => - matchPattern(pattern.get(key), value.get(key), select) - ); - } - - if (pattern instanceof Set) { - if (!(value instanceof Set)) return false; - - if (pattern.size === 0) return value.size === 0; - - if (pattern.size === 1) { - const [subPattern] = Array.from(pattern.values()); - return isMatcher(subPattern) - ? Array.from(value.values()).every((v) => - matchPattern(subPattern, v, select) - ) - : value.has(subPattern); - } - - return Array.from(pattern.values()).every((subPattern) => - value.has(subPattern) - ); - } - return Object.keys(pattern).every((k: string): boolean => { // @ts-ignore const subPattern = pattern[k]; @@ -102,7 +123,7 @@ export const matchPattern = ( }; // @internal -export const getSelectionKeys = (pattern: Pattern): string[] => { +export const getSelectionKeys = (pattern: any): string[] => { if (isObject(pattern)) { if (isMatcher(pattern)) { return pattern[symbols.matcher]().getSelectionKeys?.() ?? []; @@ -114,5 +135,7 @@ export const getSelectionKeys = (pattern: Pattern): string[] => { }; // @internal -export const flatMap = (xs: a[], f: (v: a) => b[]): b[] => - xs.reduce((acc, p) => acc.concat(f(p)), []); +export const flatMap = ( + xs: readonly a[], + f: (v: a) => readonly b[] +): b[] => xs.reduce((acc, p) => acc.concat(f(p)), []); diff --git a/src/internals/symbols.ts b/src/internals/symbols.ts index 0b713900..c238b2a2 100644 --- a/src/internals/symbols.ts +++ b/src/internals/symbols.ts @@ -13,14 +13,17 @@ * @internal */ -export const toExclude = Symbol('@ts-pattern/to-exclude'); -export type toExclude = typeof toExclude; - export const matcher = Symbol('@ts-pattern/matcher'); export type matcher = typeof matcher; export const unset = Symbol('@ts-pattern/unset'); export type unset = typeof unset; +export const isVariadic = Symbol('@ts-pattern/isVariadic'); +export type isVariadic = typeof isVariadic; + export const anonymousSelectKey = '@ts-pattern/anonymous-select-key'; export type anonymousSelectKey = typeof anonymousSelectKey; + +export const override = Symbol('@ts-pattern/override'); +export type override = typeof override; diff --git a/src/is-matching.ts b/src/is-matching.ts index 1214df06..7fdf5ffc 100644 --- a/src/is-matching.ts +++ b/src/is-matching.ts @@ -1,5 +1,4 @@ -import { Pattern } from './types/Pattern'; -import { MatchedValue } from './types/Match'; +import { MatchedValue, Pattern } from './types/Pattern'; import * as P from './patterns'; import { matchPattern } from './internals/helpers'; @@ -18,9 +17,9 @@ import { matchPattern } from './internals/helpers'; * return input.name * } */ -export function isMatching

>( +export function isMatching

>( pattern: p -): (value: any) => value is MatchedValue>; +): (value: unknown) => value is P.infer

; /** * `isMatching` takes pattern and a value and checks if the value matches this pattern. * @@ -34,10 +33,10 @@ export function isMatching

>( * return input.name * } */ -export function isMatching

>( +export function isMatching

>( pattern: p, - value: any -): value is MatchedValue>; + value: unknown +): value is P.infer

; export function isMatching

>( ...args: [pattern: p, value?: any] diff --git a/src/match.ts b/src/match.ts index 8ebeefc0..f4b94d5d 100644 --- a/src/match.ts +++ b/src/match.ts @@ -1,17 +1,14 @@ import { Pattern } from './types/Pattern'; -import { GuardValue } from './types/helpers'; -import { Match, PickReturnValue } from './types/Match'; +import { Match } from './types/Match'; import * as symbols from './internals/symbols'; import { matchPattern } from './internals/helpers'; /** * `match` creates a **pattern matching expression**. + * * Use `.with(pattern, handler)` to pattern match on the input. + * * Use `.exhaustive()` or `.otherwise(() => defaultValue)` to end the expression and get the result. * - * Use `.with(pattern, handler)` to pattern match on the input. - * - * Use `.exhaustive()` or `.otherwise(() => defaultValue)` to end the expression and get the result. - * - * [Read documentation for `match` on GitHub](https://github.com/gvergnaud/ts-pattern#match) + * [Read the documentation for `match` on GitHub](https://github.com/gvergnaud/ts-pattern#match) * * @example * declare let input: "A" | "B"; @@ -22,18 +19,21 @@ import { matchPattern } from './internals/helpers'; * .exhaustive(); * */ -export function match( - value: input -): Match; -export function match( - value: input -): Match; -export function match( +export function match( value: input ): Match { - return new MatchExpression(value, []) as any; + return new MatchExpression(value) as any; } +type MatchState = + | { matched: true; value: output } + | { matched: false; value: undefined }; + +const unmatched: MatchState = { + matched: false, + value: undefined, +}; + /** * This class represents a match expression. It follows the * builder pattern, we chain methods to add features to the expression @@ -43,20 +43,20 @@ export function match( * The types of this class aren't public, the public type definition * can be found in src/types/Match.ts. */ -class MatchExpression { +class MatchExpression { constructor( - private value: i, - private cases: { - match: (value: i) => { matched: boolean; value: any }; - handler: (...args: any) => any; - }[] + private input: input, + private state: MatchState = unmatched ) {} - with(...args: any[]) { - const handler = args[args.length - 1]; + with(...args: any[]): MatchExpression { + if (this.state.matched) return this; + + const handler: (selection: unknown, value: input) => output = + args[args.length - 1]; - const patterns: Pattern[] = [args[0]]; - const predicates: ((value: i) => unknown)[] = []; + const patterns: Pattern[] = [args[0]]; + const predicates: ((value: input) => unknown)[] = []; // case with guard as second argument if (args.length === 3 && typeof args[1] === 'function') { @@ -67,98 +67,74 @@ class MatchExpression { patterns.push(...args.slice(1, args.length - 1)); } - return new MatchExpression( - this.value, - this.cases.concat([ - { - match: (value: i) => { - let selected: Record = {}; - const matched = Boolean( - patterns.some((pattern) => - matchPattern(pattern, value, (key, value) => { - selected[key] = value; - }) - ) && predicates.every((predicate) => predicate(value as any)) - ); - return { - matched, - value: - matched && Object.keys(selected).length - ? symbols.anonymousSelectKey in selected - ? selected[symbols.anonymousSelectKey] - : selected - : value, - }; - }, - handler, - }, - ]) + let selected: Record = {}; + + const matched = Boolean( + patterns.some((pattern) => + matchPattern(pattern, this.input, (key, value) => { + selected[key] = value; + }) + ) && predicates.every((predicate) => predicate(this.input)) ); + + const state = matched + ? { + matched: true as const, + value: handler( + Object.keys(selected).length + ? symbols.anonymousSelectKey in selected + ? selected[symbols.anonymousSelectKey] + : selected + : this.input, + this.input + ), + } + : unmatched; + + return new MatchExpression(this.input, state); } - when

unknown, c>( - predicate: p, - handler: (value: GuardValue

) => PickReturnValue - ) { - return new MatchExpression>( - this.value, - this.cases.concat([ - { - match: (value) => ({ - matched: Boolean(predicate(value)), - value, - }), - handler, - }, - ]) + when( + predicate: (value: input) => unknown, + handler: (selection: input, value: input) => output + ): MatchExpression { + if (this.state.matched) return this; + + const matched = Boolean(predicate(this.input)); + + return new MatchExpression( + this.input, + matched + ? { matched: true, value: handler(this.input, this.input) } + : unmatched ); } - otherwise( - handler: (value: i) => PickReturnValue - ): PickReturnValue { - return new MatchExpression>( - this.value, - this.cases.concat([ - { - match: (value) => ({ - matched: true, - value, - }), - handler, - }, - ]) - ).run(); + otherwise(handler: (value: input) => output): output { + if (this.state.matched) return this.state.value; + return handler(this.input); } - exhaustive() { + exhaustive(): output { return this.run(); } - run() { - let selected = this.value; - let handler: undefined | ((...args: any) => any) = undefined; - - for (let i = 0; i < this.cases.length; i++) { - const entry = this.cases[i]; - const matchResult = entry.match(this.value); - if (matchResult.matched) { - selected = matchResult.value; - handler = entry.handler; - break; - } - } - if (!handler) { - let displayedValue; - try { - displayedValue = JSON.stringify(this.value); - } catch (e) { - displayedValue = this.value; - } - throw new Error( - `Pattern matching error: no pattern matches value ${displayedValue}` - ); + run(): output { + if (this.state.matched) return this.state.value; + + let displayedValue; + try { + displayedValue = JSON.stringify(this.input); + } catch (e) { + displayedValue = this.input; } - return handler(selected, this.value); + + throw new Error( + `Pattern matching error: no pattern matches value ${displayedValue}` + ); + } + + returnType() { + return this; } } diff --git a/src/patterns.ts b/src/patterns.ts index 35621fc6..4003e83b 100644 --- a/src/patterns.ts +++ b/src/patterns.ts @@ -1,12 +1,17 @@ import { matchPattern, getSelectionKeys, flatMap } from './internals/helpers'; import * as symbols from './internals/symbols'; -import { GuardFunction, IsNever, Primitives } from './types/helpers'; +import { matcher } from './internals/symbols'; +import { isMatching } from './is-matching'; +import { ExtractPreciseValue } from './types/ExtractPreciseValue'; +import { Fn } from './types/helpers'; import { InvertPattern } from './types/InvertPattern'; import { Pattern, UnknownPattern, OptionalP, ArrayP, + MapP, + SetP, AndP, OrP, NotP, @@ -14,40 +19,228 @@ import { SelectP, AnonymousSelectP, GuardExcludeP, + CustomP, + Matcher, } from './types/Pattern'; -export { Pattern }; +export { Pattern, Fn as unstable_Fn }; + +export { matcher }; + +/** + * @experimental + * A `Matchable` is an object implementing + * the Matcher Protocol. It must have a `[P.matcher]: P.Matcher` + * key, which defines how this object should be matched by TS-Pattern. + * + * Note that this api is unstable. + * + * @example + * ```ts + * class Some implements P.unstable_Matchable { + * [P.matcher](): P.unstable_Matcher> + * } + * ``` + */ +export type unstable_Matchable< + narrowedOrFn, + input = unknown, + pattern = never +> = CustomP; + +/** + * @experimental + * A `Matcher` is an object with `match` function, which + * defines how this object should be matched by TS-Pattern. + * + * Note that this api is unstable. + * + * @example + * ```ts + * class Some implements P.unstable_Matchable { + * [P.matcher](): P.unstable_Matcher> + * } + * ``` + */ +export type unstable_Matcher< + narrowedOrFn, + input = unknown, + pattern = never +> = ReturnType[matcher]>; /** * `P.infer` will return the type of the value * matched by this pattern. * - * [Read documentation for `P.infer` on GitHub](https://github.com/gvergnaud/ts-pattern#Pinfer) + * [Read the documentation for `P.infer` on GitHub](https://github.com/gvergnaud/ts-pattern#Pinfer) * * @example * const userPattern = { name: P.string } * type User = P.infer */ -export type infer

> = InvertPattern

; +export type infer

> = InvertPattern; + +export type narrow> = ExtractPreciseValue< + i, + InvertPattern +>; + +type Chainable = p & + Omit< + { + /** + * `.optional()` returns a pattern which matches if the + * key is undefined or if it is defined and the previous pattern matches its value. + * + * [Read the documentation for `P.optional` on GitHub](https://github.com/gvergnaud/ts-pattern#Poptional-patterns) + * + * @example + * match(value) + * .with({ greeting: P.string.optional() }, () => 'will match { greeting?: string}') + */ + optional(): Chainable, omitted | 'optional'>; + /** + * `pattern.and(pattern)` returns a pattern that matches + * if the previous pattern and the next one match the input. + * + * [Read the documentation for `P.intersection` on GitHub](https://github.com/gvergnaud/ts-pattern#Pintersection-patterns) + * + * @example + * match(value) + * .with( + * P.string.and(P.when(isUsername)), + * (username) => '...' + * ) + */ + and>( + pattern: p2 + ): Chainable, omitted>; + /** + * `pattern.or(pattern)` returns a pattern that matches + * if **either** the previous pattern or the next one match the input. + * + * [Read the documentation for `P.union` on GitHub](https://github.com/gvergnaud/ts-pattern#Punion-patterns) + * + * @example + * match(value) + * .with( + * { value: P.string.or(P.number) }, + * ({ value }) => 'value: number | string' + * ) + */ + or>( + pattern: p2 + ): Chainable, omitted>; + /** + * `P.select()` will inject this property into the handler function's arguments. + * + * [Read the documentation for `P.select` on GitHub](https://github.com/gvergnaud/ts-pattern#Pselect-patterns) + * + * @example + * match<{ age: number }>(value) + * .with({ age: P.string.select() }, (age) => 'age: number') + */ + select(): Chainable< + SelectP, + omitted | 'select' | 'or' | 'and' + >; + select( + key: k + ): Chainable, omitted | 'select' | 'or' | 'and'>; + }, + omitted + >; + +function chainable

>( + pattern: p +): Chainable

{ + return Object.assign(pattern, { + optional: () => optional(pattern), + and: (p2: any) => intersection(pattern, p2), + or: (p2: any) => union(pattern, p2), + select: (key: any) => + key === undefined ? select(pattern) : select(key, pattern), + }) as Chainable

; +} + +type Variadic

= p & Iterable

; + +const variadic =

(pattern: p): Variadic

=> + Object.assign(pattern, { + *[Symbol.iterator]() { + yield Object.assign(pattern, { + [symbols.isVariadic]: true, + }); + }, + }); + +type ArrayChainable = Variadic

& + Omit< + { + /** + * `.optional()` returns a pattern which matches if the + * key is undefined or if it is defined and the previous pattern matches its value. + * + * [Read the documentation for `P.optional` on GitHub](https://github.com/gvergnaud/ts-pattern#Poptional-patterns) + * + * @example + * match(value) + * .with({ greeting: P.string.optional() }, () => 'will match { greeting?: string}') + */ + optional(): ArrayChainable< + OptionalP, + omitted | 'optional' + >; + /** + * `P.select()` will inject this property into the handler function's arguments. + * + * [Read the documentation for `P.select` on GitHub](https://github.com/gvergnaud/ts-pattern#Pselect-patterns) + * + * @example + * match<{ age: number }>(value) + * .with({ age: P.string.select() }, (age) => 'age: number') + */ + select(): ArrayChainable< + SelectP, + omitted | 'select' + >; + select( + key: k + ): Chainable, omitted | 'select'>; + }, + omitted + >; + +function arrayChainable

>( + pattern: p +): ArrayChainable

{ + return Object.assign(variadic(pattern), { + optional: () => arrayChainable(optional(pattern)), + select: (key: any) => + arrayChainable( + key === undefined ? select(pattern) : select(key, pattern) + ), + }) as any; +} /** * `P.optional(subpattern)` takes a sub pattern and returns a pattern which matches if the * key is undefined or if it is defined and the sub pattern matches its value. * - * [Read documentation for `P.optional` on GitHub](https://github.com/gvergnaud/ts-pattern#Poptional-patterns) - -* @example + * [Read the documentation for `P.optional` on GitHub](https://github.com/gvergnaud/ts-pattern#Poptional-patterns) + * + * @example * match(value) * .with({ greeting: P.optional('Hello') }, () => 'will match { greeting?: "Hello" }') */ export function optional< input, - p extends unknown extends input ? UnknownPattern : Pattern ->(pattern: p): OptionalP { - return { - [symbols.matcher]() { + const p extends unknown extends input ? UnknownPattern : Pattern +>(pattern: p): Chainable, 'optional'> { + return chainable({ + [matcher]() { return { - match: (value: I | input) => { + match: (value: UnknownInput | input) => { let selections: Record = {}; const selector = (key: string, value: any) => { selections[key] = value; @@ -65,31 +258,46 @@ export function optional< matcherType: 'optional', }; }, - }; + }); } -type Elem = xs extends readonly (infer x)[] ? x : never; +type UnwrapArray = xs extends readonly (infer x)[] ? x : never; + +type UnwrapSet = xs extends Set ? x : never; + +type UnwrapMapKey = xs extends Map ? k : never; + +type UnwrapMapValue = xs extends Map ? v : never; + +type WithDefault = [a] extends [never] ? b : a; /** * `P.array(subpattern)` takes a sub pattern and returns a pattern, which matches * arrays if all their elements match the sub pattern. * - * [Read documentation for `P.array` on GitHub](https://github.com/gvergnaud/ts-pattern#Parray-patterns) + * [Read the documentation for `P.array` on GitHub](https://github.com/gvergnaud/ts-pattern#Parray-patterns) * * @example * match(value) * .with({ users: P.array({ name: P.string }) }, () => 'will match { name: string }[]') */ +export function array(): ArrayChainable>; export function array< input, - p extends unknown extends input ? UnknownPattern : Pattern> ->(pattern: p): ArrayP { - return { - [symbols.matcher]() { + const p extends Pattern, unknown>> +>(pattern: p): ArrayChainable>; +export function array( + ...args: [pattern?: any] +): ArrayChainable> { + return arrayChainable({ + [matcher]() { return { - match: (value: I | input) => { + match: (value: any) => { if (!Array.isArray(value)) return { matched: false }; + if (args.length === 0) return { matched: true }; + + const pattern = args[0]; let selections: Record = {}; if (value.length === 0) { @@ -109,17 +317,153 @@ export function array< return { matched, selections }; }, - getSelectionKeys: () => getSelectionKeys(pattern), + getSelectionKeys: () => + args.length === 0 ? [] : getSelectionKeys(args[0]), }; }, - }; + }); +} + +/** + * `P.set(subpattern)` takes a sub pattern and returns a pattern that matches + * sets if all their elements match the sub pattern. + * + * [Read `P.set` documentation on GitHub](https://github.com/gvergnaud/ts-pattern#Pset-patterns) + * + * @example + * match(value) + * .with({ users: P.set(P.string) }, () => 'will match Set') + */ +export function set(): Chainable>; +export function set< + input, + const p extends Pattern, unknown>> +>(pattern: p): Chainable>; +export function set< + input, + const p extends Pattern, unknown>> +>(...args: [pattern?: p]): Chainable> { + return chainable({ + [matcher]() { + return { + match: (value: UnknownInput | input) => { + if (!(value instanceof Set)) return { matched: false }; + + let selections: Record = {}; + + if (value.size === 0) { + return { matched: true, selections }; + } + + if (args.length === 0) return { matched: true }; + + const selector = (key: string, value: unknown) => { + selections[key] = (selections[key] || []).concat([value]); + }; + + const pattern = args[0]; + + const matched = setEvery(value, (v) => + matchPattern(pattern, v, selector) + ); + + return { matched, selections }; + }, + getSelectionKeys: () => + args.length === 0 ? [] : getSelectionKeys(args[0]), + }; + }, + }); +} + +const setEvery = (set: Set, predicate: (value: T) => boolean) => { + for (const value of set) { + if (predicate(value)) continue; + return false; + } + return true; +}; + +/** + * `P.set(subpattern)` takes a sub pattern and returns a pattern that matches + * sets if all their elements match the sub pattern. + * + * [Read `P.set` documentation on GitHub](https://github.com/gvergnaud/ts-pattern#Pset-patterns) + * + * @example + * match(value) + * .with({ users: P.set(P.string) }, () => 'will match Set') + */ +export function map(): Chainable>; +export function map< + input, + const pkey extends Pattern, unknown>>, + const pvalue extends Pattern, unknown>> +>(patternKey: pkey, patternValue: pvalue): Chainable>; +export function map< + input, + const pkey extends Pattern, unknown>>, + const pvalue extends Pattern, unknown>> +>( + ...args: [patternKey?: pkey, patternValue?: pvalue] +): Chainable> { + return chainable({ + [matcher]() { + return { + match: (value: UnknownInput | input) => { + if (!(value instanceof Map)) return { matched: false }; + + let selections: Record = {}; + + if (value.size === 0) { + return { matched: true, selections }; + } + + const selector = (key: string, value: unknown) => { + selections[key] = (selections[key] || []).concat([value]); + }; + + if (args.length === 0) return { matched: true }; + if (args.length === 1) { + throw new Error( + `\`P.map\` wasn\'t given enough arguments. Expected (key, value), received ${args[0]?.toString()}` + ); + } + const [patternKey, patternValue] = args; + + const matched = mapEvery(value, (v, k) => { + const keyMatch = matchPattern(patternKey, k, selector); + const valueMatch = matchPattern(patternValue, v, selector); + return keyMatch && valueMatch; + }); + + return { matched, selections }; + }, + getSelectionKeys: () => + args.length === 0 + ? [] + : [...getSelectionKeys(args[0]), ...getSelectionKeys(args[1])], + }; + }, + }); } +const mapEvery = ( + map: Map, + predicate: (value: T, key: K) => boolean +) => { + for (const [key, value] of map.entries()) { + if (predicate(value, key)) continue; + return false; + } + return true; +}; + /** * `P.intersection(...patterns)` returns a pattern which matches * only if **every** patterns provided in parameter match the input. * - * [Read documentation for `P.intersection` on GitHub](https://github.com/gvergnaud/ts-pattern#Pintersection-patterns) + * [Read the documentation for `P.intersection` on GitHub](https://github.com/gvergnaud/ts-pattern#Pintersection-patterns) * * @example * match(value) @@ -136,100 +480,98 @@ export function array< */ export function intersection< input, - ps extends unknown extends input - ? [UnknownPattern, ...UnknownPattern[]] - : [Pattern, ...Pattern[]] ->(...patterns: ps): AndP { - return { - [symbols.matcher]: () => ({ + const ps extends readonly [Pattern, ...Pattern[]] +>(...patterns: ps): Chainable> { + return chainable({ + [matcher]: () => ({ match: (value) => { let selections: Record = {}; const selector = (key: string, value: any) => { selections[key] = value; }; - const matched = (patterns as UnknownPattern[]).every((p) => + const matched = (patterns as readonly UnknownPattern[]).every((p) => matchPattern(p, value, selector) ); return { matched, selections }; }, getSelectionKeys: () => - flatMap(patterns as UnknownPattern[], getSelectionKeys), + flatMap(patterns as readonly UnknownPattern[], getSelectionKeys), matcherType: 'and', }), - }; + }); } /** * `P.union(...patterns)` returns a pattern which matches * if **at least one** of the patterns provided in parameter match the input. * - * [Read documentation for `P.union` on GitHub](https://github.com/gvergnaud/ts-pattern#Punion-patterns) + * [Read the documentation for `P.union` on GitHub](https://github.com/gvergnaud/ts-pattern#Punion-patterns) * * @example * match(value) * .with( * { type: P.union('a', 'b', 'c') }, - * ({ user }) => 'will match { type: "a" | "b" | "c" }' + * ({ type }) => 'will match { type: "a" | "b" | "c" }' * ) */ export function union< input, - ps extends unknown extends input - ? [UnknownPattern, ...UnknownPattern[]] - : [Pattern, ...Pattern[]] ->(...patterns: ps): OrP { - return { - [symbols.matcher]: () => ({ - match: (value: I | input) => { + const ps extends readonly [Pattern, ...Pattern[]] +>(...patterns: ps): Chainable> { + return chainable({ + [matcher]: () => ({ + match: (value: UnknownInput | input) => { let selections: Record = {}; const selector = (key: string, value: any) => { selections[key] = value; }; - flatMap(patterns as UnknownPattern[], getSelectionKeys).forEach((key) => - selector(key, undefined) - ); - const matched = (patterns as UnknownPattern[]).some((p) => + flatMap( + patterns as readonly UnknownPattern[], + getSelectionKeys + ).forEach((key) => selector(key, undefined)); + const matched = (patterns as readonly UnknownPattern[]).some((p) => matchPattern(p, value, selector) ); return { matched, selections }; }, getSelectionKeys: () => - flatMap(patterns as UnknownPattern[], getSelectionKeys), + flatMap(patterns as readonly UnknownPattern[], getSelectionKeys), matcherType: 'or', }), - }; + }); } /** * `P.not(pattern)` returns a pattern which matches if the sub pattern * doesn't match. * - * [Read documentation for `P.not` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnot-patterns) + * [Read the documentation for `P.not` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnot-patterns) * * @example * match<{ a: string | number }>(value) * .with({ a: P.not(P.string) }, (x) => 'will match { a: number }' * ) */ -export function not | Primitives>( + +export function not | UnknownPattern>( pattern: p -): NotP { - return { - [symbols.matcher]: () => ({ - match: (value: I | input) => ({ +): Chainable> { + return chainable({ + [matcher]: () => ({ + match: (value: UnknownInput | input) => ({ matched: !matchPattern(pattern, value, () => {}), }), getSelectionKeys: () => [], matcherType: 'not', }), - }; + }); } /** * `P.when((value) => boolean)` returns a pattern which matches * if the predicate returns true for the current input. * - * [Read documentation for `P.when` on GitHub](https://github.com/gvergnaud/ts-pattern#Pwhen-patterns) + * [Read the documentation for `P.when` on GitHub](https://github.com/gvergnaud/ts-pattern#Pwhen-patterns) * * @example * match<{ age: number }>(value) @@ -252,8 +594,8 @@ export function when unknown>( p extends (value: any) => value is infer narrowed ? narrowed : never > { return { - [symbols.matcher]: () => ({ - match: (value: I | input) => ({ + [matcher]: () => ({ + match: (value: UnknownInput | input) => ({ matched: Boolean(predicate(value as input)), }), }), @@ -264,32 +606,35 @@ export function when unknown>( * `P.select()` is a pattern which will always match, * and will inject the selected piece of input in the handler function. * - * [Read documentation for `P.select` on GitHub](https://github.com/gvergnaud/ts-pattern#Pselect-patterns) + * [Read the documentation for `P.select` on GitHub](https://github.com/gvergnaud/ts-pattern#Pselect-patterns) * * @example * match<{ age: number }>(value) * .with({ age: P.select() }, (age) => 'age: number' * ) */ -export function select(): AnonymousSelectP; +export function select(): Chainable; export function select< input, - patternOrKey extends + const patternOrKey extends | string | (unknown extends input ? UnknownPattern : Pattern) >( patternOrKey: patternOrKey ): patternOrKey extends string - ? SelectP - : SelectP; + ? Chainable> + : Chainable< + SelectP, + 'select' | 'or' | 'and' + >; export function select< input, - p extends unknown extends input ? UnknownPattern : Pattern, - k extends string ->(key: k, pattern: p): SelectP; + const p extends unknown extends input ? UnknownPattern : Pattern, + const k extends string +>(key: k, pattern: p): Chainable, 'select' | 'or' | 'and'>; export function select( ...args: [keyOrPattern?: unknown | string, pattern?: unknown] -): SelectP { +): Chainable, 'select' | 'or' | 'and'> { const key: string | undefined = typeof args[0] === 'string' ? args[0] : undefined; const pattern: unknown = @@ -298,8 +643,8 @@ export function select( : typeof args[0] === 'string' ? undefined : args[0]; - return { - [symbols.matcher]() { + return chainable({ + [matcher]() { return { match: (value) => { let selections: Record = { @@ -322,7 +667,7 @@ export function select( ), }; }, - }; + }); } function isUnknown(x: unknown): x is unknown { @@ -360,22 +705,31 @@ function isInstanceOf(classConstructor: T) { val instanceof classConstructor; } +// These aliases could be inferred, but lead to nicer display names in IDEs. +type AnyPattern = Chainable, never>; +type StringPattern = StringChainable, never>; +type NumberPattern = NumberChainable, never>; +type BooleanPattern = Chainable, never>; +type BigIntPattern = BigIntChainable, never>; +type SymbolPattern = Chainable, never>; +type NullishPattern = Chainable, never>; + /** * `P.any` is a wildcard pattern, matching **any value**. * - * [Read documentation for `P.any` on GitHub](https://github.com/gvergnaud/ts-pattern#P_-wildcard) + * [Read the documentation for `P.any` on GitHub](https://github.com/gvergnaud/ts-pattern#P_-wildcard) * * @example * match(value) * .with(P.any, () => 'will always match') */ -export const any = when(isUnknown); +export const any: AnyPattern = chainable(when(isUnknown)); /** * `P._` is a wildcard pattern, matching **any value**. * It's an alias to `P.any`. * - * [Read documentation for `P._` on GitHub](https://github.com/gvergnaud/ts-pattern#P_-wildcard) + * [Read the documentation for `P._` on GitHub](https://github.com/gvergnaud/ts-pattern#P_-wildcard) * * @example * match(value) @@ -384,131 +738,808 @@ export const any = when(isUnknown); export const _ = any; /** - * `P.string` is a wildcard pattern matching any **string**. + * `P.string.startsWith(start)` is a pattern, matching **strings** starting with `start`. + * + * [Read the documentation for `P.string.startsWith` on GitHub](https://github.com/gvergnaud/ts-pattern#PstringstartsWith) + * + * @example + * match(value) + * .with(P.string.startsWith('A'), () => 'value starts with an A') + */ + +const startsWith = ( + start: start +): GuardP => + when((value) => isString(value) && value.startsWith(start)); + +/** + * `P.string.endsWith(end)` is a pattern, matching **strings** ending with `end`. + * + * [Read the documentation for `P.string.endsWith` on GitHub](https://github.com/gvergnaud/ts-pattern#PstringendsWith) + * + * @example + * match(value) + * .with(P.string.endsWith('!'), () => 'value ends with an !') + */ +const endsWith = ( + end: end +): GuardP => + when((value) => isString(value) && value.endsWith(end)); + +/** + * `P.string.minLength(min)` is a pattern, matching **strings** with at least `min` characters. + * + * [Read the documentation for `P.string.minLength` on GitHub](https://github.com/gvergnaud/ts-pattern#PstringminLength) + * + * @example + * match(value) + * .with(P.string.minLength(10), () => 'string with more length >= 10') + */ +const minLength = (min: min) => + when((value) => isString(value) && value.length >= min); + +/** + * `P.string.maxLength(max)` is a pattern, matching **strings** with at most `max` characters. + * + * [Read the documentation for `P.string.maxLength` on GitHub](https://github.com/gvergnaud/ts-pattern#PstringmaxLength) + * + * @example + * match(value) + * .with(P.string.maxLength(10), () => 'string with more length <= 10') + */ +const maxLength = (max: max) => + when((value) => isString(value) && value.length <= max); + +/** + * `P.string.includes(substr)` is a pattern, matching **strings** containing `substr`. + * + * [Read the documentation for `P.string.includes` on GitHub](https://github.com/gvergnaud/ts-pattern#Pstringincludes) + * + * @example + * match(value) + * .with(P.string.includes('http'), () => 'value contains http') + */ +const includes = ( + substr: substr +): GuardExcludeP => + when((value) => isString(value) && value.includes(substr)); + +/** + * `P.string.regex(expr)` is a pattern, matching **strings** that `expr` regular expression. + * + * [Read the documentation for `P.string.regex` on GitHub](https://github.com/gvergnaud/ts-pattern#Pstringregex) + * + * @example + * match(value) + * .with(P.string.regex(/^https?:\/\//), () => 'url') + */ +const regex = ( + expr: expr +): GuardExcludeP => + when((value) => isString(value) && Boolean(value.match(expr))); + +type MaybeAnd = [omitted] extends [never] + ? p2 + : AndP; + +type StringChainable< + p extends Matcher, + omitted extends string = never +> = Chainable & + Omit< + { + /** + * `P.string.startsWith(start)` is a pattern, matching **strings** starting with `start`. + * + * [Read the documentation for `P.string.startsWith` on GitHub](https://github.com/gvergnaud/ts-pattern#PstringstartsWith) + * + * @example + * match(value) + * .with(P.string.startsWith('A'), () => 'value starts with an A') + */ + startsWith( + start: start + ): StringChainable< + MaybeAnd>, + omitted | 'startsWith' + >; + /** + * `P.string.endsWith(end)` is a pattern, matching **strings** ending with `end`. + * + * [Read the documentation for `P.string.endsWith` on GitHub](https://github.com/gvergnaud/ts-pattern#PstringendsWith) + * + * @example + * match(value) + * .with(P.string.endsWith('!'), () => 'value ends with an !') + */ + endsWith( + end: end + ): StringChainable< + MaybeAnd>, + omitted | 'endsWith' + >; + /** + * `P.string.minLength(min)` is a pattern, matching **strings** with at least `min` characters. + * + * [Read the documentation for `P.string.minLength` on GitHub](https://github.com/gvergnaud/ts-pattern#PstringminLength) + * + * @example + * match(value) + * .with(P.string.minLength(10), () => 'string with more length <= 10') + */ + minLength( + min: min + ): StringChainable< + MaybeAnd>, + omitted | 'minLength' + >; + /** + * `P.string.maxLength(max)` is a pattern, matching **strings** with at most `max` characters. + * + * [Read the documentation for `P.string.maxLength` on GitHub](https://github.com/gvergnaud/ts-pattern#PstringmaxLength) + * + * @example + * match(value) + * .with(P.string.maxLength(10), () => 'string with more length >= 10') + */ + maxLength( + max: max + ): StringChainable< + MaybeAnd>, + omitted | 'maxLength' + >; + /** + * `P.string.includes(substr)` is a pattern, matching **strings** containing `substr`. + * + * [Read the documentation for `P.string.includes` on GitHub](https://github.com/gvergnaud/ts-pattern#Pstringincludes) + * + * @example + * match(value) + * .with(P.string.includes('http'), () => 'value contains http') + */ + includes( + substr: substr + ): StringChainable< + MaybeAnd>, + omitted + >; + /** + * `P.string.regex(expr)` is a pattern, matching **strings** that `expr` regular expression. + * + * [Read the documentation for `P.string.regex` on GitHub](https://github.com/gvergnaud/ts-pattern#Pstringregex) + * + * @example + * match(value) + * .with(P.string.regex(/^https?:\/\//), () => 'url') + */ + regex( + expr: expr + ): StringChainable< + MaybeAnd>, + omitted + >; + }, + omitted + >; + +const stringChainable =

>( + pattern: p +): StringChainable

=> + Object.assign(chainable(pattern), { + startsWith: (str: string) => + stringChainable(intersection(pattern, startsWith(str))), + endsWith: (str: string) => + stringChainable(intersection(pattern, endsWith(str))), + minLength: (min: number) => + stringChainable(intersection(pattern, minLength(min))), + maxLength: (max: number) => + stringChainable(intersection(pattern, maxLength(max))), + includes: (str: string) => + stringChainable(intersection(pattern, includes(str))), + regex: (str: string) => stringChainable(intersection(pattern, regex(str))), + }) as any; + +/** + * `P.string` is a wildcard pattern, matching any **string**. * - * [Read documentation for `P.string` on GitHub](https://github.com/gvergnaud/ts-pattern#Pstring-wildcard) + * [Read the documentation for `P.string` on GitHub](https://github.com/gvergnaud/ts-pattern#Pstring-wildcard) * * @example * match(value) * .with(P.string, () => 'will match on strings') */ +export const string: StringPattern = stringChainable(when(isString)); + +/** + * `P.number.between(min, max)` matches **number** between `min` and `max`, + * equal to min or equal to max. + * + * [Read the documentation for `P.number.between` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberbetween) + * + * @example + * match(value) + * .with(P.number.between(0, 10), () => '0 <= numbers <= 10') + */ +export const between = < + input, + const min extends number, + const max extends number +>( + min: min, + max: max +): GuardExcludeP => + when((value) => isNumber(value) && min <= value && max >= value); + +/** + * `P.number.lt(max)` matches **number** smaller than `max`. + * + * [Read the documentation for `P.number.lt` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberlt) + * + * @example + * match(value) + * .with(P.number.lt(10), () => 'numbers < 10') + */ +export const lt = ( + max: max +): GuardExcludeP => + when((value) => isNumber(value) && value < max); + +/** + * `P.number.gt(min)` matches **number** greater than `min`. + * + * [Read the documentation for `P.number.gt` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumbergt) + * + * @example + * match(value) + * .with(P.number.gt(10), () => 'numbers > 10') + */ +export const gt = ( + min: min +): GuardExcludeP => + when((value) => isNumber(value) && value > min); + +/** + * `P.number.lte(max)` matches **number** smaller than or equal to `max`. + * + * [Read the documentation for `P.number.lte` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberlte) + * + * @example + * match(value) + * .with(P.number.lte(10), () => 'numbers <= 10') + */ +export const lte = ( + max: max +): GuardExcludeP => + when((value) => isNumber(value) && value <= max); + +/** + * `P.number.gte(min)` matches **number** greater than or equal to `min`. + * + * [Read the documentation for `P.number.gte` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumbergte) + * + * @example + * match(value) + * .with(P.number.gte(10), () => 'numbers >= 10') + */ +export const gte = ( + min: min +): GuardExcludeP => + when((value) => isNumber(value) && value >= min); + +/** + * `P.number.int` matches **integer** numbers. + * + * [Read the documentation for `P.number.int` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberint) + * + * @example + * match(value) + * .with(P.number.int, () => 'an integer') + */ +export const int = (): GuardExcludeP => + when((value) => isNumber(value) && Number.isInteger(value)); + +/** + * `P.number.finite` matches **finite numbers**. + * + * [Read the documentation for `P.number.finite` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberfinite) + * + * @example + * match(value) + * .with(P.number.finite, () => 'not Infinity') + */ +export const finite = (): GuardExcludeP => + when((value) => isNumber(value) && Number.isFinite(value)); + +/** + * `P.number.positive` matches **positive** numbers. + * + * [Read the documentation for `P.number.positive` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberpositive) + * + * @example + * match(value) + * .with(P.number.positive, () => 'number > 0') + */ +export const positive = (): GuardExcludeP => + when((value) => isNumber(value) && value > 0); + +/** + * `P.number.negative` matches **negative** numbers. + * + * [Read the documentation for `P.number.negative` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumbernegative) + * + * @example + * match(value) + * .with(P.number.negative, () => 'number < 0') + */ +export const negative = (): GuardExcludeP => + when((value) => isNumber(value) && value < 0); -export const string = when(isString); +type NumberChainable = Chainable< + p, + omitted +> & + Omit< + { + /** + * `P.number.between(min, max)` matches **number** between `min` and `max`, + * equal to min or equal to max. + * + * [Read the documentation for `P.number.between` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberbetween) + * + * @example + * match(value) + * .with(P.number.between(0, 10), () => '0 <= numbers <= 10') + */ + between( + min: min, + max: max + ): NumberChainable< + MaybeAnd>, + omitted + >; + /** + * `P.number.lt(max)` matches **number** smaller than `max`. + * + * [Read the documentation for `P.number.lt` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberlt) + * + * @example + * match(value) + * .with(P.number.lt(10), () => 'numbers < 10') + */ + lt( + max: max + ): NumberChainable< + MaybeAnd>, + omitted + >; + /** + * `P.number.gt(min)` matches **number** greater than `min`. + * + * [Read the documentation for `P.number.gt` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumbergt) + * + * @example + * match(value) + * .with(P.number.gt(10), () => 'numbers > 10') + */ + gt( + min: min + ): NumberChainable< + MaybeAnd>, + omitted + >; + /** + * `P.number.lte(max)` matches **number** smaller than or equal to `max`. + * + * [Read the documentation for `P.number.lte` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberlte) + * + * @example + * match(value) + * .with(P.number.lte(10), () => 'numbers <= 10') + */ + lte( + max: max + ): NumberChainable< + MaybeAnd>, + omitted + >; + /** + * `P.number.gte(min)` matches **number** greater than or equal to `min`. + * + * [Read the documentation for `P.number.gte` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumbergte) + * + * @example + * match(value) + * .with(P.number.gte(10), () => 'numbers >= 10') + */ + gte( + min: min + ): NumberChainable< + MaybeAnd>, + omitted + >; + /** + * `P.number.int` matches **integer** numbers. + * + * [Read the documentation for `P.number.int` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberint) + * + * @example + * match(value) + * .with(P.number.int, () => 'an integer') + */ + int(): NumberChainable< + MaybeAnd>, + omitted | 'int' + >; + /** + * `P.number.finite` matches **finite numbers**. + * + * [Read the documentation for `P.number.finite` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberfinite) + * + * @example + * match(value) + * .with(P.number.finite, () => 'not Infinity') + */ + finite(): NumberChainable< + MaybeAnd>, + omitted | 'finite' + >; + /** + * `P.number.positive` matches **positive** numbers. + * + * [Read the documentation for `P.number.positive` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberpositive) + * + * @example + * match(value) + * .with(P.number.positive, () => 'number > 0') + */ + positive(): NumberChainable< + MaybeAnd>, + omitted | 'positive' | 'negative' + >; + /** + * `P.number.negative` matches **negative** numbers. + * + * [Read the documentation for `P.number.negative` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumbernegative) + * + * @example + * match(value) + * .with(P.number.negative, () => 'number < 0') + */ + negative(): NumberChainable< + MaybeAnd>, + omitted | 'positive' | 'negative' | 'negative' + >; + }, + omitted + >; + +const numberChainable =

>( + pattern: p +): NumberChainable

=> + Object.assign(chainable(pattern), { + between: (min: number, max: number) => + numberChainable(intersection(pattern, between(min, max))), + lt: (max: number) => numberChainable(intersection(pattern, lt(max))), + gt: (min: number) => numberChainable(intersection(pattern, gt(min))), + lte: (max: number) => numberChainable(intersection(pattern, lte(max))), + gte: (min: number) => numberChainable(intersection(pattern, gte(min))), + int: () => numberChainable(intersection(pattern, int())), + finite: () => numberChainable(intersection(pattern, finite())), + positive: () => numberChainable(intersection(pattern, positive())), + negative: () => numberChainable(intersection(pattern, negative())), + }) as any; /** - * `P.number` is a wildcard pattern matching any **number**. + * `P.number` is a wildcard pattern, matching any **number**. * - * [Read documentation for `P.number` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumber-wildcard) + * [Read the documentation for `P.number` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumber-wildcard) * * @example * match(value) * .with(P.number, () => 'will match on numbers') */ -export const number = when(isNumber); +export const number: NumberPattern = numberChainable(when(isNumber)); /** - * `P.boolean` is a wildcard pattern matching any **boolean**. + * `P.bigint.between(min, max)` matches **bigint** between `min` and `max`, + * equal to min or equal to max. * - * [Read documentation for `P.boolean` on GitHub](https://github.com/gvergnaud/ts-pattern#boolean-wildcard) + * [Read the documentation for `P.bigint.between` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberbetween) * * @example - * .with(P.boolean, () => 'will match on booleans') + * match(value) + * .with(P.bigint.between(0, 10), () => '0 <= numbers <= 10') + */ +export const betweenBigInt = < + input, + const min extends bigint, + const max extends bigint +>( + min: min, + max: max +): GuardExcludeP => + when((value) => isBigInt(value) && min <= value && max >= value); + +/** + * `P.bigint.lt(max)` matches **bigint** smaller than `max`. + * + * [Read the documentation for `P.bigint.lt` on GitHub](https://github.com/gvergnaud/ts-pattern#bigintlt) + * + * @example + * match(value) + * .with(P.bigint.lt(10), () => 'numbers < 10') */ -export const boolean = when(isBoolean); +export const ltBigInt = ( + max: max +): GuardExcludeP => + when((value) => isBigInt(value) && value < max); /** - * `P.bigint` is a wildcard pattern matching any **bigint**. + * `P.bigint.gt(min)` matches **bigint** greater than `min`. * - * [Read documentation for `P.bigint` on GitHub](https://github.com/gvergnaud/ts-pattern#bigint-wildcard) + * [Read the documentation for `P.bigint.gt` on GitHub](https://github.com/gvergnaud/ts-pattern#bigintgt) + * + * @example + * match(value) + * .with(P.bigint.gt(10), () => 'numbers > 10') + */ +export const gtBigInt = ( + min: min +): GuardExcludeP => + when((value) => isBigInt(value) && value > min); + +/** + * `P.bigint.lte(max)` matches **bigint** smaller than or equal to `max`. + * + * [Read the documentation for `P.bigint.lte` on GitHub](https://github.com/gvergnaud/ts-pattern#bigintlte) + * + * @example + * match(value) + * .with(P.bigint.lte(10), () => 'bigints <= 10') + */ +export const lteBigInt = ( + max: max +): GuardExcludeP => + when((value) => isBigInt(value) && value <= max); + +/** + * `P.bigint.gte(min)` matches **bigint** greater than or equal to `min`. + * + * [Read the documentation for `P.bigint.gte` on GitHub](https://github.com/gvergnaud/ts-pattern#Pbigintgte) + * + * @example + * match(value) + * .with(P.bigint.gte(10), () => 'bigints >= 10') + */ +export const gteBigInt = ( + min: min +): GuardExcludeP => + when((value) => isBigInt(value) && value >= min); + +/** + * `P.bigint.positive` matches **positive** bigints. + * + * [Read the documentation for `P.bigint.positive` on GitHub](https://github.com/gvergnaud/ts-pattern#Pbigintpositive) + * + * @example + * match(value) + * .with(P.bigint.positive, () => 'bigint > 0') + */ +export const positiveBigInt = (): GuardExcludeP => + when((value) => isBigInt(value) && value > 0); + +/** + * `P.bigint.negative` matches **negative** bigints. + * + * [Read the documentation for `P.bigint.negative` on GitHub](https://github.com/gvergnaud/ts-pattern#Pbigintnegative) + * + * @example + * match(value) + * .with(P.bigint.negative, () => 'bigint < 0') + */ +export const negativeBigInt = (): GuardExcludeP => + when((value) => isBigInt(value) && value < 0); + +type BigIntChainable = Chainable< + p, + omitted +> & + Omit< + { + /** + * `P.bigint.between(min, max)` matches **bigint** between `min` and `max`, + * equal to min or equal to max. + * + * [Read the documentation for `P.bigint.between` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberbetween) + * + * @example + * match(value) + * .with(P.bigint.between(0, 10), () => '0 <= numbers <= 10') + */ + between( + min: min, + max: max + ): BigIntChainable< + MaybeAnd>, + omitted + >; + /** + * `P.bigint.lt(max)` matches **bigint** smaller than `max`. + * + * [Read the documentation for `P.bigint.lt` on GitHub](https://github.com/gvergnaud/ts-pattern#bigintlt) + * + * @example + * match(value) + * .with(P.bigint.lt(10), () => 'numbers < 10') + */ + lt( + max: max + ): BigIntChainable< + MaybeAnd>, + omitted + >; + /** + * `P.bigint.gt(min)` matches **bigint** greater than `min`. + * + * [Read the documentation for `P.bigint.gt` on GitHub](https://github.com/gvergnaud/ts-pattern#bigintgt) + * + * @example + * match(value) + * .with(P.bigint.gt(10), () => 'numbers > 10') + */ + gt( + min: min + ): BigIntChainable< + MaybeAnd>, + omitted + >; + /** + * `P.bigint.lte(max)` matches **bigint** smaller than or equal to `max`. + * + * [Read the documentation for `P.bigint.lte` on GitHub](https://github.com/gvergnaud/ts-pattern#bigintlte) + * + * @example + * match(value) + * .with(P.bigint.lte(10), () => 'bigints <= 10') + */ + lte( + max: max + ): BigIntChainable< + MaybeAnd>, + omitted + >; + /** + * `P.bigint.gte(min)` matches **bigint** greater than or equal to `min`. + * + * [Read the documentation for `P.bigint.gte` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumbergte) + * + * @example + * match(value) + * .with(P.bigint.gte(10), () => 'bigints >= 10') + */ + gte( + min: min + ): BigIntChainable< + MaybeAnd>, + omitted + >; + /** + * `P.bigint.positive` matches **positive** bigints. + * + * [Read the documentation for `P.bigint.positive` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumberpositive) + * + * @example + * match(value) + * .with(P.bigint.positive, () => 'bigint > 0') + */ + positive(): BigIntChainable< + MaybeAnd>, + omitted | 'positive' | 'negative' + >; + /** + * `P.bigint.negative` matches **negative** bigints. + * + * [Read the documentation for `P.bigint.negative` on GitHub](https://github.com/gvergnaud/ts-pattern#Pnumbernegative) + * + * @example + * match(value) + * .with(P.bigint.negative, () => 'bigint < 0') + */ + negative(): BigIntChainable< + MaybeAnd>, + omitted | 'positive' | 'negative' | 'negative' + >; + }, + omitted + >; + +const bigintChainable =

>( + pattern: p +): BigIntChainable

=> + Object.assign(chainable(pattern), { + between: (min: bigint, max: bigint) => + bigintChainable(intersection(pattern, betweenBigInt(min, max))), + lt: (max: bigint) => bigintChainable(intersection(pattern, ltBigInt(max))), + gt: (min: bigint) => bigintChainable(intersection(pattern, gtBigInt(min))), + lte: (max: bigint) => + bigintChainable(intersection(pattern, lteBigInt(max))), + gte: (min: bigint) => + bigintChainable(intersection(pattern, gteBigInt(min))), + positive: () => bigintChainable(intersection(pattern, positiveBigInt())), + negative: () => bigintChainable(intersection(pattern, negativeBigInt())), + }) as any; + +/** + * `P.bigint` is a wildcard pattern, matching any **bigint**. + * + * [Read the documentation for `P.bigint` on GitHub](https://github.com/gvergnaud/ts-pattern#bigint-wildcard) * * @example * .with(P.bigint, () => 'will match on bigints') */ -export const bigint = when(isBigInt); +export const bigint: BigIntPattern = bigintChainable(when(isBigInt)); + +/** + * `P.boolean` is a wildcard pattern, matching any **boolean**. + * + * [Read the documentation for `P.boolean` on GitHub](https://github.com/gvergnaud/ts-pattern#boolean-wildcard) + * + * @example + * .with(P.boolean, () => 'will match on booleans') + */ +export const boolean: BooleanPattern = chainable(when(isBoolean)); /** - * `P.symbol` is a wildcard pattern matching any **symbol**. + * `P.symbol` is a wildcard pattern, matching any **symbol**. * - * [Read documentation for `P.symbol` on GitHub](https://github.com/gvergnaud/ts-pattern#symbol-wildcard) + * [Read the documentation for `P.symbol` on GitHub](https://github.com/gvergnaud/ts-pattern#symbol-wildcard) * * @example * .with(P.symbol, () => 'will match on symbols') */ -export const symbol = when(isSymbol); +export const symbol: SymbolPattern = chainable(when(isSymbol)); /** - * `P.nullish` is a wildcard pattern matching **null** or **undefined**. + * `P.nullish` is a wildcard pattern, matching **null** or **undefined**. * - * [Read documentation for `P.nullish` on GitHub](https://github.com/gvergnaud/ts-pattern#nullish-wildcard) + * [Read the documentation for `P.nullish` on GitHub](https://github.com/gvergnaud/ts-pattern#nullish-wildcard) * * @example * .with(P.nullish, () => 'will match on null or undefined') */ -export const nullish = when(isNullish); +export const nullish: NullishPattern = chainable(when(isNullish)); /** * `P.instanceOf(SomeClass)` is a pattern matching instances of a given class. * - * [Read documentation for `P.instanceOf` on GitHub](https://github.com/gvergnaud/ts-pattern#Pinstanceof-patterns) + * [Read the documentation for `P.instanceOf` on GitHub](https://github.com/gvergnaud/ts-pattern#Pinstanceof-patterns) * * @example * .with(P.instanceOf(SomeClass), () => 'will match on SomeClass instances') */ export function instanceOf( classConstructor: T -): GuardP> { - return when(isInstanceOf(classConstructor)); +): Chainable>> { + return chainable(when(isInstanceOf(classConstructor))); } /** - * `P.typed()` is a way to set the input type this - * pattern should match on. + * `P.shape(somePattern)` lets you call methods like `.optional()`, `.and`, `.or` and `.select()` + * On structural patterns, like objects and arrays. * - * It returns all utility functions to create patterns, - * Like `array`, `union`, `intersection`, etc. + * [Read the documentation for `P.shape` on GitHub](https://github.com/gvergnaud/ts-pattern#Pshape-patterns) * - * [Read documentation for `P.typed` on GitHub](https://github.com/gvergnaud/ts-pattern#Ptyped) - * - * @example - * .with( - * P.typed().array(P.string), - * (arrayOfString) => arrayOfString.join(', ') - * ) + * @example + * .with( + * { + * state: P.shape({ status: "success" }).optional().select() + * }, + * (state) => 'match the success state, or undefined.' + * ) */ -export function typed(): { - array

>>(pattern: p): ArrayP; - - optional

>(pattern: p): OptionalP; - - intersection, ...Pattern[]]>( - ...patterns: ps - ): AndP; - - union, ...Pattern[]]>( - ...patterns: ps - ): OrP; - - not

>(pattern: p): NotP; - - when( - predicate: GuardFunction - ): GuardP; - - select>( - pattern: pattern - ): SelectP; - select

, k extends string>( - key: k, - pattern: p - ): SelectP; -} { - return { - array: array as any, - optional: optional as any, - intersection: intersection as any, - union: union as any, - not: not as any, - select: select as any, - when: when as any, - }; +export function shape>( + pattern: p +): Chainable>>; +export function shape(pattern: UnknownPattern) { + return chainable(when(isMatching(pattern))); } diff --git a/src/types/BuildMany.ts b/src/types/BuildMany.ts index 69892883..9c39f7d0 100644 --- a/src/types/BuildMany.ts +++ b/src/types/BuildMany.ts @@ -1,18 +1,18 @@ -import { Cast, Compute, Iterator, UpdateAt } from './helpers'; +import { Compute, Iterator, UpdateAt } from './helpers'; // BuildMany :: DataStructure -> Union<[value, path][]> -> Union -export type BuildMany = xs extends any +export type BuildMany = xs extends any ? BuildOne : never; // BuildOne :: DataStructure // -> [value, path][] // -> DataStructure -type BuildOne = xs extends [ +type BuildOne = xs extends [ [infer value, infer path], ...infer tail ] - ? BuildOne>, tail> + ? BuildOne>, tail> : data; type SafeGet = k extends keyof data @@ -20,30 +20,31 @@ type SafeGet = k extends keyof data : def; // Update :: a -> b -> PropertyKey[] -> a -type Update = path extends [ - infer head, - ...infer tail -] +type Update< + data, + value, + path extends readonly PropertyKey[] +> = path extends readonly [infer head, ...infer tail] ? data extends readonly [any, ...any] ? head extends number ? UpdateAt< data, Iterator, - Update> + Update> > : never : data extends readonly (infer a)[] - ? Update>[] + ? Update>[] : data extends Set - ? Set>> + ? Set>> : data extends Map - ? Map>> + ? Map>> : Compute< - Omit> & { - [k in Cast]: Update< + Omit> & { + [k in Extract]: Update< SafeGet, value, - Cast + Extract >; } > diff --git a/src/types/DistributeUnions.ts b/src/types/DistributeUnions.ts index 7a4bc194..81381ef5 100644 --- a/src/types/DistributeUnions.ts +++ b/src/types/DistributeUnions.ts @@ -1,13 +1,16 @@ import { BuildMany } from './BuildMany'; import type { IsAny, - Cast, Values, Flatten, IsUnion, IsPlainObject, Length, UnionToTuple, + IsReadonlyArray, + ValueOf, + MaybeAddReadonly, + IsStrictArray, } from './helpers'; import { IsMatching } from './IsMatching'; @@ -51,7 +54,7 @@ export type FindUnionsMany< ? FindUnions : [] : never - ) extends (infer T)[] + ) extends readonly (infer T)[] ? T : never >; @@ -134,6 +137,35 @@ export type FindUnions< ? [...FindUnions, ...FindUnions] : [a, p] extends [readonly [infer a1], readonly [infer p1]] ? FindUnions + : /** + * Special case when matching with a variadic tuple on a regular array. + * in this case we turne the input array `A[]` into `[] | [A, ...A[]]` + * to remove one of these cases during DeepExclude. + */ + p extends readonly [] | readonly [any, ...any] | readonly [...any, any] + ? IsStrictArray> extends false + ? [] + : [ + MaybeAddReadonly< + | (a extends readonly [any, ...any] | readonly [...any, any] + ? never + : []) + | (p extends readonly [...any, any] + ? [...Extract, ValueOf] + : [ValueOf, ...Extract]), + IsReadonlyArray + > extends infer aUnion + ? { + cases: aUnion extends any + ? { + value: aUnion; + subUnions: []; + } + : never; + path: path; + } + : never + ] : [] : a extends Set ? [] @@ -148,15 +180,16 @@ export type FindUnions< : []; // Distribute :: UnionConfig[] -> Union<[a, path][]> -export type Distribute = unions extends [ - { cases: infer cases; path: infer path }, - ...infer tail -] - ? cases extends { value: infer value; subUnions: infer subUnions } - ? [ - [value, path], - ...Distribute>, - ...Distribute - ] - : never - : []; +export type Distribute = + unions extends readonly [ + { cases: infer cases; path: infer path }, + ...infer tail + ] + ? cases extends { value: infer value; subUnions: infer subUnions } + ? [ + [value, path], + ...Distribute>, + ...Distribute + ] + : never + : []; diff --git a/src/types/ExtractPreciseValue.ts b/src/types/ExtractPreciseValue.ts index 94bec685..8f61ff12 100644 --- a/src/types/ExtractPreciseValue.ts +++ b/src/types/ExtractPreciseValue.ts @@ -1,77 +1,29 @@ -import type { ToExclude } from './Pattern'; +import type { Override } from './Pattern'; import type { BuiltInObjects, Compute, ExcludeObjectIfContainsNever, - IsAny, IsPlainObject, + IsReadonlyArray, LeastUpperBound, + MaybeAddReadonly, + ValueOf, } from './helpers'; -import { DeepExclude } from './DeepExclude'; -export type ExtractPreciseValue = unknown extends b +export type ExtractPreciseValue = b extends Override + ? b1 + : unknown extends b ? a - : IsAny extends true + : // inlining IsAny for perf + 0 extends 1 & b + ? a + : // inlining IsAny for perf + 0 extends 1 & a ? b : b extends readonly [] ? [] - : b extends ToExclude - ? DeepExclude - : b extends readonly (infer bItem)[] - ? a extends readonly (infer aItem)[] - ? b extends readonly [infer b1, infer b2, infer b3, infer b4, infer b5] - ? a extends readonly [infer a1, infer a2, infer a3, infer a4, infer a5] - ? ExcludeObjectIfContainsNever< - [ - ExtractPreciseValue, - ExtractPreciseValue, - ExtractPreciseValue, - ExtractPreciseValue, - ExtractPreciseValue - ], - '0' | '1' | '2' | '3' | '4' - > - : LeastUpperBound - : b extends readonly [infer b1, infer b2, infer b3, infer b4] - ? a extends readonly [infer a1, infer a2, infer a3, infer a4] - ? ExcludeObjectIfContainsNever< - [ - ExtractPreciseValue, - ExtractPreciseValue, - ExtractPreciseValue, - ExtractPreciseValue - ], - '0' | '1' | '2' | '3' - > - : LeastUpperBound - : b extends readonly [infer b1, infer b2, infer b3] - ? a extends readonly [infer a1, infer a2, infer a3] - ? ExcludeObjectIfContainsNever< - [ - ExtractPreciseValue, - ExtractPreciseValue, - ExtractPreciseValue - ], - '0' | '1' | '2' - > - : LeastUpperBound - : b extends readonly [infer b1, infer b2] - ? a extends readonly [infer a1, infer a2] - ? ExcludeObjectIfContainsNever< - [ExtractPreciseValue, ExtractPreciseValue], - '0' | '1' - > - : LeastUpperBound - : b extends readonly [infer b1] - ? a extends readonly [infer a1] - ? ExcludeObjectIfContainsNever<[ExtractPreciseValue], '0'> - : LeastUpperBound - : ExtractPreciseValue extends infer preciseValue - ? [preciseValue] extends [never] - ? never - : preciseValue[] - : never - : LeastUpperBound + : b extends readonly any[] + ? ExtractPreciseArrayValue> : b extends Map ? a extends Map ? Map, ExtractPreciseValue> @@ -89,7 +41,7 @@ export type ExtractPreciseValue = unknown extends b : b extends a ? [Exclude] extends [never] ? b - : Compute> + : Compute & Omit> : [keyof a & keyof b] extends [never] ? never : ExcludeObjectIfContainsNever< @@ -110,3 +62,70 @@ export type ExtractPreciseValue = unknown extends b > : LeastUpperBound : LeastUpperBound; + +type ExtractPreciseArrayValue< + a, + b, + isReadonly extends boolean, + startOutput extends any[] = [], + endOutput extends any[] = [] +> = a extends readonly (infer aItem)[] + ? b extends readonly [] + ? MaybeAddReadonly<[...startOutput, ...endOutput], isReadonly> + : b extends readonly [infer b1, ...infer bRest] + ? a extends readonly [infer a1, ...infer aRest] + ? ExtractPreciseValue extends infer currentValue + ? [currentValue] extends [never] + ? never + : ExtractPreciseArrayValue< + aRest, + bRest, + isReadonly, + [...startOutput, currentValue], + endOutput + > + : never + : ExtractPreciseValue extends infer currentValue + ? [currentValue] extends [never] + ? never + : ExtractPreciseArrayValue< + aItem[], + bRest, + isReadonly, + [...startOutput, currentValue], + endOutput + > + : never + : b extends readonly [...infer bInit, infer b1] + ? a extends readonly [...infer aInit, infer a1] + ? ExtractPreciseValue extends infer currentValue + ? [currentValue] extends [never] + ? never + : ExtractPreciseArrayValue< + aInit, + bInit, + isReadonly, + startOutput, + [...endOutput, currentValue] + > + : never + : ExtractPreciseValue extends infer currentValue + ? [currentValue] extends [never] + ? never + : ExtractPreciseArrayValue< + aItem[], + bInit, + isReadonly, + startOutput, + [...endOutput, currentValue] + > + : never + : ExtractPreciseValue> extends infer currentValue + ? [currentValue] extends [never] + ? never + : MaybeAddReadonly< + [...startOutput, ...currentValue[], ...endOutput], + isReadonly + > + : never + : LeastUpperBound; diff --git a/src/types/FindSelected.ts b/src/types/FindSelected.ts index eed9b07d..ec813459 100644 --- a/src/types/FindSelected.ts +++ b/src/types/FindSelected.ts @@ -1,6 +1,6 @@ import type * as symbols from '../internals/symbols'; -import type { Cast, Equal, IsAny, TupleKeys, UnionToTuple } from './helpers'; -import type { Matcher, Pattern } from './Pattern'; +import type { AnyMatcher, Matcher, Pattern } from './Pattern'; +import type { Equal, Primitives, ValueOf, UnionToTuple } from './helpers'; type SelectionsRecord = Record; @@ -28,49 +28,97 @@ type MapList = { type ReduceFindSelectionUnion< i, - ps extends any[], + ps extends readonly any[], output = never -> = ps extends [infer head, ...infer tail] +> = ps extends readonly [infer head, ...infer tail] ? ReduceFindSelectionUnion> : output; +type FindSelectionUnionInArray< + i, + p, + path extends any[] = [], + output = never +> = i extends readonly (infer ii)[] + ? p extends readonly [] + ? output + : p extends readonly [infer p1, ...infer pRest] + ? i extends readonly [infer i1, ...infer iRest] + ? FindSelectionUnionInArray< + iRest, + pRest, + [...path, p['length']], + output | FindSelectionUnion + > + : FindSelectionUnionInArray< + ii[], + pRest, + [...path, p['length']], + output | FindSelectionUnion + > + : p extends readonly [...infer pInit, infer p1] + ? i extends readonly [...infer iInit, infer i1] + ? FindSelectionUnionInArray< + iInit, + pInit, + [...path, p['length']], + output | FindSelectionUnion + > + : FindSelectionUnionInArray< + ii[], + pInit, + [...path, p['length']], + output | FindSelectionUnion + > + : // If P is a matcher, in this case, it's likely an array matcher + p extends readonly [...(readonly (infer pRest & AnyMatcher)[])] + ? output | FindSelectionUnion + : + | output + | FindSelectionUnion< + ii, + ValueOf

, + [...path, Extract['length']] + > + : output; + export type FindSelectionUnion< i, p, // path just serves as an id, to identify different anonymous patterns which have the same type path extends any[] = [] -> = IsAny extends true + // inlining IsAny for perf +> = 0 extends 1 & i + ? never + : // inlining IsAny for perf + 0 extends 1 & p + ? never + : p extends Primitives ? never : p extends Matcher ? { select: sel extends Some ? { [kk in k]: [i, path] } | FindSelectionUnion : never; - array: i extends (infer ii)[] + array: i extends readonly (infer ii)[] ? MapList> : never; + // FIXME: selection for map and set is supported at the value level + map: never; + set: never; optional: MapOptional>; - or: MapOptional>>; - and: ReduceFindSelectionUnion>; + or: MapOptional< + ReduceFindSelectionUnion> + >; + and: ReduceFindSelectionUnion>; not: never; default: sel extends Some ? { [kk in k]: [i, path] } : never; + custom: never; }[matcherType] - : p extends readonly (infer pp)[] - ? i extends readonly (infer ii)[] - ? p extends readonly [any, ...any[]] - ? i extends readonly [any, ...any[]] - ? { - [k in TupleKeys & keyof i & keyof p]: FindSelectionUnion< - i[k], - p[k], - [...path, k] - >; - }[TupleKeys & keyof i & keyof p] - : FindSelectionUnion - : FindSelectionUnion - : never - : p extends object - ? i extends object + : p extends readonly any[] + ? FindSelectionUnionInArray + : p extends {} + ? i extends {} ? { [k in keyof p]: k extends keyof i ? FindSelectionUnion @@ -119,7 +167,10 @@ type ReduceToRecord< selections extends any[], output extends SelectionsRecord = {} > = selections extends [infer sel, ...infer rest] - ? ReduceToRecord, output>> + ? ReduceToRecord< + rest, + ConcatSelections, output> + > : output; export type Selections = FindSelectionUnion extends infer u diff --git a/src/types/InvertPattern.ts b/src/types/InvertPattern.ts index 5c0ac0e3..8bc27ae6 100644 --- a/src/types/InvertPattern.ts +++ b/src/types/InvertPattern.ts @@ -5,106 +5,170 @@ import { IsLiteral, ValueOf, Compute, - Cast, Equal, Extends, Not, All, NonLiteralPrimitive, + MaybeAddReadonly, + IsReadonlyArray, + MapKey, + MapValue, + SetValue, + ExtractPlainObject, + GetKey, + Call, + Fn, + ReadonlyArrayValue, + ExtractWithDefault, + WithDefault, } from './helpers'; -import type { Matcher, Pattern, ToExclude } from './Pattern'; +import type { Matcher, Pattern, Override, AnyMatcher } from './Pattern'; type OptionalKeys

= ValueOf<{ - [k in keyof p]: p[k] extends Matcher + [k in keyof p]: 0 extends 1 & p[k] // inlining IsAny for perf + ? never + : p[k] extends Matcher ? matcherType extends 'optional' ? k : never : never; }>; -type ReduceUnion = tuple extends readonly [ - infer p, - ...infer tail -] - ? ReduceUnion> +type ReduceUnion< + tuple extends readonly any[], + i, + output = never +> = tuple extends readonly [infer p, ...infer tail] + ? ReduceUnion> : output; type ReduceIntersection< - tuple extends any[], + tuple extends readonly any[], + i, output = unknown > = tuple extends readonly [infer p, ...infer tail] - ? ReduceIntersection> + ? ReduceIntersection> : output; +type InvertArrayPattern< + p, + i, + startOutput extends any[] = [], + endOutput extends any[] = [] +> = i extends readonly (infer ii)[] + ? p extends readonly [] + ? [...startOutput, ...endOutput] + : p extends readonly [infer p1, ...infer pRest] + ? i extends readonly [infer i1, ...infer iRest] + ? InvertArrayPattern< + pRest, + iRest, + [...startOutput, InvertPatternInternal], + endOutput + > + : InvertArrayPattern< + pRest, + ii[], + [...startOutput, InvertPatternInternal], + endOutput + > + : p extends readonly [...infer pInit, infer p1] + ? i extends readonly [...infer iInit, infer i1] + ? InvertArrayPattern< + pInit, + iInit, + startOutput, + [...endOutput, InvertPatternInternal] + > + : InvertArrayPattern< + pInit, + ii[], + startOutput, + [...endOutput, InvertPatternInternal] + > + : // If P is a matcher, in this case, it's likely an array matcher + p extends readonly [...(readonly (infer pRest & AnyMatcher)[])] + ? [ + ...startOutput, + ...Extract, readonly any[]>, + ...endOutput + ] + : [...startOutput, ...InvertPatternInternal, ii>[], ...endOutput] + : never; + /** - * ### InvertPattern + * ### InvertPatternInternal * Since patterns have special wildcard values, we need a way * to transform a pattern into the type of value it represents */ -export type InvertPattern

= p extends Matcher< - infer input, - infer narrowed, - infer matcherType, - any -> +export type InvertPattern = Equal, p> extends true + ? never + : InvertPatternInternal; + +type InvertPatternInternal = 0 extends 1 & p + ? never + : p extends Matcher< + infer _input, + infer subpattern, + infer matcherType, + any, + infer narrowedOrFn + > ? { - not: ToExclude>; - select: InvertPattern; - array: InvertPattern[]; - optional: InvertPattern | undefined; - and: ReduceIntersection>; - or: ReduceUnion>; - default: [narrowed] extends [never] ? input : narrowed; + not: DeepExclude>; + select: InvertPatternInternal; + array: InvertPatternInternal>[]; + map: subpattern extends [infer pk, infer pv] + ? Map< + InvertPatternInternal>>>, + InvertPatternInternal>>> + > + : never; + set: Set< + InvertPatternInternal>>> + >; + optional: + | InvertPatternInternal> + | undefined; + and: ReduceIntersection, input>; + or: ReduceUnion, input>; + default: [subpattern] extends [never] ? input : subpattern; + custom: Override< + narrowedOrFn extends Fn ? Call : narrowedOrFn + >; }[matcherType] : p extends Primitives ? p - : p extends readonly (infer pp)[] - ? p extends readonly [infer p1, infer p2, infer p3, infer p4, infer p5] - ? [ - InvertPattern, - InvertPattern, - InvertPattern, - InvertPattern, - InvertPattern - ] - : p extends readonly [infer p1, infer p2, infer p3, infer p4] - ? [ - InvertPattern, - InvertPattern, - InvertPattern, - InvertPattern - ] - : p extends readonly [infer p1, infer p2, infer p3] - ? [InvertPattern, InvertPattern, InvertPattern] - : p extends readonly [infer p1, infer p2] - ? [InvertPattern, InvertPattern] - : p extends readonly [infer p1] - ? [InvertPattern] - : p extends readonly [] - ? [] - : InvertPattern[] - : p extends Map - ? Map> - : p extends Set - ? Set> + : p extends readonly any[] + ? InvertArrayPattern> : IsPlainObject

extends true ? OptionalKeys

extends infer optKeys ? [optKeys] extends [never] ? { - [k in Exclude]: InvertPattern; + [k in Exclude]: InvertPatternInternal< + p[k], + WithDefault, k>, unknown> + >; } : Compute< { - [k in Exclude]: InvertPattern; + [k in Exclude]: InvertPatternInternal< + p[k], + WithDefault, k>, unknown> + >; } & { - [k in Cast]?: InvertPattern; + [k in Extract]?: InvertPatternInternal< + p[k], + WithDefault, k>, unknown> + >; } > : never : p; export type ReduceIntersectionForExclude< - tuple extends any[], + tuple extends readonly any[], i, output = unknown > = tuple extends readonly [infer p, ...infer tail] @@ -116,7 +180,7 @@ export type ReduceIntersectionForExclude< : output; export type ReduceUnionForExclude< - tuple extends any[], + tuple extends readonly any[], i, output = never > = tuple extends readonly [infer p, ...infer tail] @@ -154,10 +218,79 @@ type ExcludeIfExists = never : DeepExclude; +type InvertArrayPatternForExclude< + p, + i, + empty, + isReadonly extends boolean, + startOutput extends any[] = [], + endOutput extends any[] = [] +> = i extends readonly (infer ii)[] + ? p extends readonly [] + ? MaybeAddReadonly<[...startOutput, ...endOutput], isReadonly> + : p extends readonly [infer p1, ...infer pRest] + ? i extends readonly [infer i1, ...infer iRest] + ? InvertArrayPatternForExclude< + pRest, + iRest, + empty, + isReadonly, + [...startOutput, InvertPatternForExcludeInternal], + endOutput + > + : InvertArrayPatternForExclude< + pRest, + ii[], + empty, + isReadonly, + [...startOutput, InvertPatternForExcludeInternal], + endOutput + > + : p extends readonly [...infer pInit, infer p1] + ? i extends readonly [...infer iInit, infer i1] + ? InvertArrayPatternForExclude< + pInit, + iInit, + empty, + isReadonly, + startOutput, + [...endOutput, InvertPatternForExcludeInternal] + > + : InvertArrayPatternForExclude< + pInit, + ii[], + empty, + isReadonly, + startOutput, + [...endOutput, InvertPatternForExcludeInternal] + > + : // If P is a matcher, in this case, it's likely an array matcher + p extends readonly [...(readonly (infer pRest & AnyMatcher)[])] + ? MaybeAddReadonly< + [ + ...startOutput, + ...Extract< + InvertPatternForExcludeInternal, + readonly any[] + >, + ...endOutput + ], + isReadonly + > + : MaybeAddReadonly< + [ + ...startOutput, + ...InvertPatternForExcludeInternal, ii, empty>[], + ...endOutput + ], + isReadonly + > + : empty; + /** * ### InvertPatternForExclude */ -export type InvertPatternForExclude = Equal> extends true +export type InvertPatternForExclude = Equal, p> extends true ? never : InvertPatternForExcludeInternal; @@ -165,7 +298,9 @@ type InvertPatternForExcludeInternal = // We need to prevent distribution because the boolean // type is a union of literal as well as a Primitive type // and it will end up being a false positif if we distribute it. - [p] extends [Primitives] + unknown extends p + ? i + : [p] extends [Primitives] ? IsLiteral

extends true ? p : IsLiteral extends true @@ -183,11 +318,25 @@ type InvertPatternForExcludeInternal = array: i extends readonly (infer ii)[] ? InvertPatternForExcludeInternal[] : empty; + map: subpattern extends [infer pk, infer pv] + ? i extends Map + ? Map< + InvertPatternForExcludeInternal, + InvertPatternForExcludeInternal + > + : empty + : empty; + set: i extends Set + ? Set> + : empty; optional: | InvertPatternForExcludeInternal | undefined; - and: ReduceIntersectionForExclude, i>; - or: ReduceUnionForExclude, i>; + and: ReduceIntersectionForExclude< + Extract, + i + >; + or: ReduceUnionForExclude, i>; not: ExcludeIfExists< // we use matchableInput if possible because it represent the // union of all possible value, but i is only one of these values. @@ -195,59 +344,19 @@ type InvertPatternForExcludeInternal = InvertPatternForExcludeInternal >; default: excluded; + custom: excluded extends infer narrowedOrFn extends Fn + ? Call + : excluded; }[matcherType] - : p extends readonly (infer pp)[] - ? i extends readonly (infer ii)[] - ? p extends readonly [infer p1, infer p2, infer p3, infer p4, infer p5] - ? i extends readonly [infer i1, infer i2, infer i3, infer i4, infer i5] - ? readonly [ - InvertPatternForExcludeInternal, - InvertPatternForExcludeInternal, - InvertPatternForExcludeInternal, - InvertPatternForExcludeInternal, - InvertPatternForExcludeInternal - ] - : empty - : p extends readonly [infer p1, infer p2, infer p3, infer p4] - ? i extends readonly [infer i1, infer i2, infer i3, infer i4] - ? readonly [ - InvertPatternForExcludeInternal, - InvertPatternForExcludeInternal, - InvertPatternForExcludeInternal, - InvertPatternForExcludeInternal - ] - : empty - : p extends readonly [infer p1, infer p2, infer p3] - ? i extends readonly [infer i1, infer i2, infer i3] - ? readonly [ - InvertPatternForExcludeInternal, - InvertPatternForExcludeInternal, - InvertPatternForExcludeInternal - ] - : empty - : p extends readonly [infer p1, infer p2] - ? i extends readonly [infer i1, infer i2] - ? readonly [ - InvertPatternForExcludeInternal, - InvertPatternForExcludeInternal - ] - : empty - : p extends readonly [infer p1] - ? i extends readonly [infer i1] - ? readonly [InvertPatternForExcludeInternal] - : empty - : p extends readonly [] - ? [] - : InvertPatternForExcludeInternal[] - : empty - : p extends Map - ? i extends Map - ? Map> - : empty - : p extends Set - ? i extends Set - ? Set> - : empty + : p extends readonly any[] + ? Extract extends infer arrayInput + ? InvertArrayPatternForExclude< + p, + arrayInput, + empty, + IsReadonlyArray + > + : never : IsPlainObject

extends true ? i extends object ? [keyof p & keyof i] extends [never] @@ -257,17 +366,17 @@ type InvertPatternForExcludeInternal = ? { readonly [k in keyof p]: k extends keyof i ? InvertPatternForExcludeInternal - : InvertPattern; + : InvertPatternInternal; } : Compute< { readonly [k in Exclude]: k extends keyof i ? InvertPatternForExcludeInternal - : InvertPattern; + : InvertPatternInternal; } & { - readonly [k in Cast]?: k extends keyof i + readonly [k in Extract]?: k extends keyof i ? InvertPatternForExcludeInternal - : InvertPattern; + : InvertPatternInternal; } > : empty diff --git a/src/types/IsMatching.ts b/src/types/IsMatching.ts index c608c344..f90875f7 100644 --- a/src/types/IsMatching.ts +++ b/src/types/IsMatching.ts @@ -1,79 +1,100 @@ -import { Primitives, IsPlainObject, IsUnion } from './helpers'; +import { + Primitives, + IsPlainObject, + IsUnion, + ValueOf, + Length, + IsLiteral, + All, + Equal, +} from './helpers'; -export type IsMatching = true extends IsUnion | IsUnion

+type IsMatchingTuple = [ + a, + b +] extends [readonly [], readonly []] + ? true + : [a, b] extends [ + readonly [infer a1, ...infer aRest], + readonly [infer b1, ...infer bRest] + ] + ? IsMatching extends true + ? IsMatchingTuple + : false + : false; + +type IsMatchingArray< + a extends readonly any[], + b extends readonly any[] +> = b extends readonly [] + ? true // if b is an empty array and a is an array, the pattern matches. + : b extends readonly [infer b1, ...infer bRest] + ? a extends readonly [infer a1, ...infer aRest] + ? IsMatching extends true + ? IsMatchingArray + : false + : // if a is shorter than b, doesn't match + // example: a is [], b is [any, ...any[]] + a extends readonly [] + ? false + : IsMatching, b1> extends true + ? IsMatchingArray + : false + : b extends readonly [...infer bInit, infer b1] + ? a extends readonly [...infer aInit, infer a1] + ? IsMatching extends true + ? IsMatchingArray + : false + : // if a is shorter than b, doesn't match + // example: a is [], b is [any, ...any[]] + a extends readonly [] + ? false + : IsMatching, b1> extends true + ? IsMatchingArray + : false + : IsMatching, ValueOf>; + +export type IsMatching = true extends IsUnion | IsUnion ? true extends ( - p extends any ? (a extends any ? IsMatching : never) : never + b extends any ? (a extends any ? IsMatching : never) : never ) ? true : false : // Special case for unknown, because this is the type // of the inverted `_` wildcard pattern, which should // match everything. - unknown extends p + unknown extends b ? true - : p extends Primitives - ? p extends a + : b extends Primitives + ? // if the pattern is a primitive, we want to check if there is + // an overlap between a and b! + a extends b ? true - : false - : [p, a] extends [readonly any[], readonly any[]] - ? [p, a] extends [ - readonly [infer p1, infer p2, infer p3, infer p4, infer p5], - readonly [infer a1, infer a2, infer a3, infer a4, infer a5] - ] - ? [ - IsMatching, - IsMatching, - IsMatching, - IsMatching, - IsMatching - ] extends [true, true, true, true, true] - ? true - : false - : [p, a] extends [ - readonly [infer p1, infer p2, infer p3, infer p4], - readonly [infer a1, infer a2, infer a3, infer a4] - ] - ? [ - IsMatching, - IsMatching, - IsMatching, - IsMatching - ] extends [true, true, true, true] - ? true - : false - : [p, a] extends [ - readonly [infer p1, infer p2, infer p3], - readonly [infer a1, infer a2, infer a3] - ] - ? [IsMatching, IsMatching, IsMatching] extends [ - true, - true, - true - ] - ? true - : false - : [p, a] extends [ - readonly [infer p1, infer p2], - readonly [infer a1, infer a2] - ] - ? [IsMatching, IsMatching] extends [true, true] - ? true - : false - : [p, a] extends [readonly [infer p1], readonly [infer a1]] - ? IsMatching - : p extends a + : b extends a ? true : false - : IsPlainObject

extends true + : Equal extends true + ? true + : b extends readonly any[] + ? a extends readonly any[] + ? // both tuples + All<[IsLiteral>, IsLiteral>]> extends true + ? // lengths are different + Equal, Length> extends false + ? false + : IsMatchingTuple + : IsMatchingArray + : false + : IsPlainObject extends true ? true extends ( // `true extends union` means "if some cases of the a union are matching" a extends any // loop over the `a` union - ? [keyof p & keyof a] extends [never] // if no common keys + ? [keyof b & keyof a] extends [never] // if no common keys ? false : /** * Intentionally not using ValueOf, to avoid reaching the * 'type instanciation is too deep error'. */ - { [k in keyof p & keyof a]: IsMatching }[keyof p & + { [k in keyof b & keyof a]: IsMatching }[keyof b & keyof a] extends true ? true // all values are matching : false @@ -81,6 +102,6 @@ export type IsMatching = true extends IsUnion | IsUnion

) ? true : false - : p extends a + : b extends a ? true : false; diff --git a/src/types/Match.ts b/src/types/Match.ts index 0316895b..da2d2663 100644 --- a/src/types/Match.ts +++ b/src/types/Match.ts @@ -1,20 +1,19 @@ import type * as symbols from '../internals/symbols'; -import type { Pattern, Matcher } from './Pattern'; -import type { ExtractPreciseValue } from './ExtractPreciseValue'; +import type { Pattern, MatchedValue } from './Pattern'; import type { InvertPatternForExclude, InvertPattern } from './InvertPattern'; import type { DeepExclude } from './DeepExclude'; -import type { WithDefault, Union, GuardValue, IsNever } from './helpers'; +import type { Union, GuardValue, IsNever } from './helpers'; import type { FindSelected } from './FindSelected'; -// We fall back to `a` if we weren't able to extract anything more precise -export type MatchedValue = WithDefault< - ExtractPreciseValue, - a ->; - export type PickReturnValue = a extends symbols.unset ? b : a; -type NonExhaustiveError = { __nonExhaustive: never } & i; +interface NonExhaustiveError { + __nonExhaustive: never; +} + +interface TSPatternError { + __nonExhaustive: never; +} /** * #### Match @@ -23,19 +22,20 @@ type NonExhaustiveError = { __nonExhaustive: never } & i; export type Match< i, o, - patternValueTuples extends any[] = [], + handledCases extends any[] = [], inferredOutput = never > = { /** - * `.with(pattern, handler)` Registers a pattern and an handler function which - * will be called if this pattern matches the input value. + * `.with(pattern, handler)` Registers a pattern and an handler function that + * will be called if the pattern matches the input value. * - * [Read documentation for `.with()` on GitHub](https://github.com/gvergnaud/ts-pattern#with) + * [Read the documentation for `.with()` on GitHub](https://github.com/gvergnaud/ts-pattern#with) **/ with< - p extends Pattern, + const p extends Pattern, c, - value extends MatchedValue> + value extends MatchedValue>, + excluded = InvertPatternForExclude >( /** * HACK: Using `IsNever

` here is a hack to @@ -50,21 +50,19 @@ export type Match< selections: FindSelected, value: value ) => PickReturnValue - ): [InvertPatternForExclude] extends [infer excluded] - ? Match< - Exclude, - o, - [...patternValueTuples, excluded], - Union - > - : never; + ): Match< + Exclude, + o, + [...handledCases, excluded], + Union + >; with< - p1 extends Pattern, - p2 extends Pattern, + const p1 extends Pattern, + const p2 extends Pattern, c, p extends p1 | p2, - value extends p extends any ? MatchedValue> : never + value extends p extends any ? MatchedValue> : never >( p1: p1, p2: p2, @@ -76,19 +74,19 @@ export type Match< ? Match< Exclude, o, - [...patternValueTuples, excluded1, excluded2], + [...handledCases, excluded1, excluded2], Union > : never; with< - p1 extends Pattern, - p2 extends Pattern, - p3 extends Pattern, - ps extends Pattern[], + const p1 extends Pattern, + const p2 extends Pattern, + const p3 extends Pattern, + const ps extends readonly Pattern[], c, p extends p1 | p2 | p3 | ps[number], - value extends p extends any ? MatchedValue> : never + value extends MatchedValue> >( ...args: [ p1: p1, @@ -118,7 +116,7 @@ export type Match< >, o, [ - ...patternValueTuples, + ...handledCases, excluded1, excluded2, excluded3, @@ -129,8 +127,8 @@ export type Match< : never; with< - pat extends Pattern, - pred extends (value: MatchedValue>) => unknown, + const pat extends Pattern, + pred extends (value: MatchedValue>) => unknown, c, value extends GuardValue >( @@ -144,16 +142,16 @@ export type Match< ? Match< Exclude, o, - [...patternValueTuples, narrowed], + [...handledCases, narrowed], Union > - : Match>; + : Match>; /** * `.when(predicate, handler)` Registers a predicate function and an handler function. - * If the predicate returns true, the handler function will be chosen to handle the input. + * If the predicate returns true, the handler function will be called. * - * [Read documentation for `.when()` on GitHub](https://github.com/gvergnaud/ts-pattern#when) + * [Read the documentation for `.when()` on GitHub](https://github.com/gvergnaud/ts-pattern#when) **/ when unknown, c, value extends GuardValue>( predicate: pred, @@ -162,18 +160,18 @@ export type Match< ? Match< Exclude, o, - [...patternValueTuples, narrowed], + [...handledCases, narrowed], Union > - : Match>; + : Match>; /** - * `.otherwise()` takes a function returning the **default value**, and - * will be used to handle the input value if no previous pattern matched. + * `.otherwise()` takes a **default handler function** that will be + * called if no previous pattern matched your input. * * Equivalent to `.with(P._, () => x).exhaustive()` * - * [Read documentation for `.otherwise()` on GitHub](https://github.com/gvergnaud/ts-pattern#otherwise) + * [Read the documentation for `.otherwise()` on GitHub](https://github.com/gvergnaud/ts-pattern#otherwise) * **/ otherwise( @@ -181,25 +179,36 @@ export type Match< ): PickReturnValue>; /** - * `.exhaustive()` runs the pattern matching expression and return the result value. + * `.exhaustive()` checks that all cases are handled, and return the result value. * - * If this is of type `NonExhaustiveError`, it means you aren't matching - * every case, and you should add another `.with(...)` clause - * to prevent potential runtime errors. + * If you get a `NonExhaustiveError`, it means that you aren't handling + * all cases. You should probably add another `.with(...)` clause + * to match the missing case and prevent runtime errors. * - * [Read documentation for `.exhaustive()` on GitHub](https://github.com/gvergnaud/ts-pattern#exhaustive) + * [Read the documentation for `.exhaustive()` on GitHub](https://github.com/gvergnaud/ts-pattern#exhaustive) * * */ - exhaustive: DeepExcludeAll extends infer remainingCases + exhaustive: DeepExcludeAll extends infer remainingCases ? [remainingCases] extends [never] ? () => PickReturnValue : NonExhaustiveError : never; /** - * `.run()` runs the pattern matching expression and return the result value. + * `.run()` return the resulting value. + * + * ⚠️ calling this function is unsafe, and may throw if no pattern matches your input. * */ run(): PickReturnValue; + + /** + * `.returnType()` Lets you specific the return type of all of your branches. + * + * [Read the documentation for `.returnType()` on GitHub](https://github.com/gvergnaud/ts-pattern#returnType) + * */ + returnType: [inferredOutput] extends [never] + ? () => Match + : TSPatternError<'calling `.returnType()` is only allowed directly after `match(...)`.'>; }; /** @@ -225,6 +234,6 @@ type DeepExcludeAll = [a] extends [never] ? DeepExcludeAll, tail> : a; -type MakeTuples = { +type MakeTuples = { -readonly [index in keyof ps]: InvertPatternForExclude; }; diff --git a/src/types/Pattern.ts b/src/types/Pattern.ts index a34ed0ab..8e18d8fe 100644 --- a/src/types/Pattern.ts +++ b/src/types/Pattern.ts @@ -1,6 +1,8 @@ import type * as symbols from '../internals/symbols'; -import { Primitives } from './helpers'; +import { MergeUnion, Primitives, WithDefault } from './helpers'; import { None, Some, SelectionType } from './FindSelected'; +import { matcher } from '../patterns'; +import { ExtractPreciseValue } from './ExtractPreciseValue'; export type MatcherType = | 'not' @@ -8,8 +10,11 @@ export type MatcherType = | 'or' | 'and' | 'array' + | 'map' + | 'set' | 'select' - | 'default'; + | 'default' + | 'custom'; // We use a separate MatcherProtocol type to preserves // the type level information (selections and excluded) used @@ -51,21 +56,48 @@ export interface Matcher< // it has been fully matched by this pattern excluded = narrowed > { - [symbols.matcher](): MatcherProtocol< + [matcher](): MatcherProtocol< input, narrowed, matcherType, selections, excluded >; + // only used for array matchers + [symbols.isVariadic]?: boolean; } -type UnknownMatcher = Matcher; +type PatternMatcher = Matcher; -export type OptionalP = Matcher; +// We fall back to `a` if we weren't able to extract anything more precise +export type MatchedValue = WithDefault< + ExtractPreciseValue, + a +>; + +export type AnyMatcher = Matcher; + +type UnknownMatcher = PatternMatcher; + +export type CustomP = Matcher< + input, + pattern, + // 👆 + // for the input type to be instantiated correctly + // on subpatterns, it has to be passed through. + 'custom', + None, + narrowedOrFn +>; export type ArrayP = Matcher; +export type OptionalP = Matcher; + +export type MapP = Matcher; + +export type SetP = Matcher; + export type AndP = Matcher; export type OrP = Matcher; @@ -90,16 +122,15 @@ export type SelectP< export type AnonymousSelectP = SelectP; -export interface ToExclude { - [symbols.toExclude]: a; +export interface Override { + [symbols.override]: a; } export type UnknownPattern = | readonly [] - | readonly [UnknownPattern, ...UnknownPattern[]] - | { readonly [k: string]: UnknownPattern } - | Set - | Map + | readonly [unknown, ...unknown[]] + | readonly [...unknown[], unknown] + | { readonly [k: string]: unknown } | Primitives | UnknownMatcher; @@ -109,25 +140,37 @@ export type UnknownPattern = * They can also be wildcards, like `P._`, `P.string`, `P.number`, * or other matchers, like `P.when(predicate)`, `P.not(pattern)`, etc. * - * [Read documentation for `P.Pattern` on GitHub](https://github.com/gvergnaud/ts-pattern#patterns) + * [Read the documentation for `P.Pattern` on GitHub](https://github.com/gvergnaud/ts-pattern#patterns) * * @example * const pattern: P.Pattern = { name: P.string } */ -export type Pattern = - | Matcher - | (a extends Primitives - ? a - : unknown extends a - ? UnknownPattern - : a extends readonly (infer i)[] - ? a extends readonly [any, ...any] - ? { readonly [index in keyof a]: Pattern } - : readonly [] | readonly [Pattern, ...Pattern[]] - : a extends Map - ? Map> - : a extends Set - ? Set> - : a extends object - ? { readonly [k in keyof a]?: Pattern> } - : a); +export type Pattern = unknown extends a ? UnknownPattern : KnownPattern; + +type KnownPattern = KnownPatternInternal; + +type KnownPatternInternal< + a, + objs = Exclude | Set | readonly any[]>, + arrays = Extract, + primitives = Exclude +> = + | primitives + | PatternMatcher + | ([objs] extends [never] ? never : ObjectPattern>) + | ([arrays] extends [never] ? never : ArrayPattern); + +type ObjectPattern = + | { + readonly [k in keyof a]?: Pattern; + } + | never; + +type ArrayPattern = a extends readonly (infer i)[] + ? a extends readonly [any, ...any] + ? { readonly [index in keyof a]: Pattern } + : + | readonly [] + | readonly [Pattern, ...Pattern[]] + | readonly [...Pattern[], Pattern] + : never; diff --git a/src/types/helpers.ts b/src/types/helpers.ts index 1617521b..f106820e 100644 --- a/src/types/helpers.ts +++ b/src/types/helpers.ts @@ -1,4 +1,4 @@ -export type ValueOf = a extends any[] ? a[number] : a[keyof a]; +export type ValueOf = a extends readonly any[] ? a[number] : a[keyof a]; export type Values = UnionToTuple>; @@ -22,7 +22,7 @@ export type ExcludeIfContainsNever = b extends Map | Set ? a : b extends readonly [any, ...any] ? ExcludeObjectIfContainsNever - : b extends any[] + : b extends readonly any[] ? ExcludeObjectIfContainsNever : ExcludeObjectIfContainsNever; @@ -57,13 +57,11 @@ export type UnionToTuple< ? UnionToTuple, [elem, ...output]> : output; -export type Cast = a extends b ? a : never; - export type Flatten< - xs extends any[], + xs extends readonly any[], output extends any[] = [] > = xs extends readonly [infer head, ...infer tail] - ? Flatten]> + ? Flatten]> : output; export type Equal = (() => T extends a ? 1 : 2) extends < @@ -147,7 +145,7 @@ export type IntersectObjects = ( a extends any ? keyof a : never ) extends infer allKeys ? { - [k in Cast]: a extends any + [k in Extract]: a extends any ? k extends keyof a ? a[k] : never @@ -157,6 +155,8 @@ export type IntersectObjects = ( export type WithDefault = [a] extends [never] ? def : a; +export type ExtractWithDefault = a extends b ? a : def; + export type IsLiteral = [a] extends [null | undefined] ? true : [a] extends [string] @@ -192,7 +192,7 @@ export type Primitives = export type NonLiteralPrimitive = Exclude; -export type TupleKeys = 0 | 1 | 2 | 3 | 4; +export type TupleKeys = '0' | '1' | '2' | '3' | '4'; export type Union = [b] extends [a] ? a : [a] extends [b] ? b : a | b; @@ -206,7 +206,7 @@ export type GuardValue = fn extends (value: any) => value is infer b : never; export type GuardFunction = - | ((value: input) => value is Cast) + | ((value: input) => value is Extract) | ((value: input) => boolean); export type Some = true extends bools[number] @@ -220,3 +220,70 @@ export type All = bools[number] extends true export type Extends = [a] extends [b] ? true : false; export type Not = a extends true ? false : true; + +type AllKeys = a extends any ? keyof a : never; + +// Merge unions of objects into a single object with unions of keys +export type MergeUnion = + | { + readonly [k in AllKeys]: a extends any + ? k extends keyof a + ? a[k] + : never + : never; + } + | never; + +export type IsFixedSizeTuple = IsLiteral>; + +// is it a fixed size or a variadic tuple +export type IsTuple = a extends + | readonly [] + | readonly [any, ...any] + | readonly [...any, any] + ? true + : false; + +export type IsStrictArray = Not>; + +export type IsReadonlyArray = a extends readonly any[] + ? a extends any[] // mutable array + ? false + : true + : false; + +export type MaybeAddReadonly< + a, + shouldAdd extends boolean +> = shouldAdd extends true ? Readonly : a; + +export type MapKey = T extends Map ? K : never; + +export type MapValue = T extends Map ? V : never; + +export type SetValue = T extends Set ? V : never; + +export type ReadonlyArrayValue = T extends ReadonlyArray + ? V + : never; + +export type ExtractPlainObject = T extends any + ? IsPlainObject extends true + ? T + : never + : never; + +export type GetKey = O extends any + ? K extends keyof O + ? O[K] + : never + : never; + +export interface Fn { + input: unknown; + output: unknown; +} + +export type Call = (fn & { + input: input; +})['output']; diff --git a/tests/bigints.test.ts b/tests/bigints.test.ts new file mode 100644 index 00000000..ab1cc5b4 --- /dev/null +++ b/tests/bigints.test.ts @@ -0,0 +1,119 @@ +import { P, match } from '../src'; +import { Equal, Expect } from '../src/types/helpers'; + +describe('BigInts', () => { + it(`P.bigint.between(1, 10)`, () => { + const f = (input: string | bigint) => + match(input) + .with(P.bigint.between(0n, 10n), (value) => { + type t = Expect>; + return 'between 0 and 10'; + }) + .otherwise((value) => { + type t = Expect>; + return 'something else'; + }); + + expect(f(5n)).toBe('between 0 and 10'); + expect(f(0n)).toBe('between 0 and 10'); + expect(f(10n)).toBe('between 0 and 10'); + expect(f('gabriel')).toBe('something else'); + }); + + it(`P.bigint.lt(..)`, () => { + const f = (input: string | bigint) => + match(input) + .with(P.bigint.lt(10n), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5n)).toBe('yes'); + expect(f(12n)).toBe('no'); + expect(f(10n)).toBe('no'); + }); + it(`P.bigint.gt(..)`, () => { + const f = (input: string | bigint) => + match(input) + .with(P.bigint.gt(10n), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5n)).toBe('no'); + expect(f(10n)).toBe('no'); + expect(f(12n)).toBe('yes'); + }); + it(`P.bigint.gte(..)`, () => { + const f = (input: string | bigint) => + match(input) + .with(P.bigint.gte(10n), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5n)).toBe('no'); + expect(f(10n)).toBe('yes'); + expect(f(12n)).toBe('yes'); + }); + it(`P.bigint.lte(..)`, () => { + const f = (input: string | bigint) => + match(input) + .with(P.bigint.lte(10n), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5n)).toBe('yes'); + expect(f(10n)).toBe('yes'); + expect(f(12n)).toBe('no'); + }); + it(`P.bigint.positive()`, () => { + const f = (input: string | bigint) => + match(input) + .with(P.bigint.positive(), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5n)).toBe('yes'); + expect(f(10123n)).toBe('yes'); + expect(f(-10123n)).toBe('no'); + }); + it(`P.bigint.negative()`, () => { + const f = (input: string | bigint) => + match(input) + .with(P.bigint.negative(), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5n)).toBe('no'); + expect(f(10123n)).toBe('no'); + expect(f(-10123n)).toBe('yes'); + }); +}); diff --git a/tests/chainable.test.ts b/tests/chainable.test.ts new file mode 100644 index 00000000..b3a37584 --- /dev/null +++ b/tests/chainable.test.ts @@ -0,0 +1,259 @@ +import { P, match } from '../src'; +import { Equal, Expect } from '../src/types/helpers'; + +describe('chainable methods', () => { + describe('string compositions', () => { + it(`P.string.optional()`, () => { + const f = (input?: string | number) => + match(input) + .with(P.string.optional(), (value) => { + type t = Expect>; + return `yes ${value}`; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(102)).toBe('no'); + expect(f()).toBe('yes undefined'); + expect(f('gabriel')).toBe('yes gabriel'); + }); + + it(`P.string.select()`, () => { + const f = (input?: string | number) => + match({ input }) + .with({ input: P.string.select() }, (value) => { + type t = Expect>; + return `yes ${value}`; + }) + .otherwise(() => 'no'); + + expect(f(102)).toBe('no'); + expect(f()).toBe('no'); + expect(f('gabriel')).toBe('yes gabriel'); + }); + it(`P.number.optional.select()`, () => { + const f = (input?: string | number) => + match({ input }) + .with({ input: P.number.optional().select() }, (value) => { + type t = Expect>; + return `yes ${value}`; + }) + .otherwise(() => 'no'); + + expect(f(102)).toBe('yes 102'); + expect(f()).toBe('yes undefined'); + expect(f('gabriel')).toBe('no'); + }); + it(`P.string.optional.select()`, () => { + const f = (input?: string | number) => + match({ input }) + .with({ input: P.string.optional().select() }, (value) => { + type t = Expect>; + return `yes ${value}`; + }) + .otherwise(() => 'no'); + + expect(f(102)).toBe('no'); + expect(f()).toBe('yes undefined'); + expect(f('gabriel')).toBe('yes gabriel'); + }); + it(`P.string.startsWith(..).optional().select()`, () => { + const f = (input?: string | number) => + match({ input }) + .with( + { + input: P.string.startsWith('hello ').optional().select(), + }, + (value) => { + type t = Expect< + Equal + >; + return `starts with hello: ${value}`; + } + ) + .otherwise(() => 'no'); + + expect(f('hello gabriel')).toBe('starts with hello: hello gabriel'); + expect(f('gabriel')).toBe('no'); + }); + + it('P.string.startsWith(..).endsWith(..)', () => { + const f = (input?: string | number) => + match(input) + .with(P.string.startsWith('hello ').endsWith('!'), (value) => { + type t = Expect< + Equal + >; + return `yes: ${value}`; + }) + .otherwise(() => 'no'); + + expect(f('hello gabriel!')).toBe('yes: hello gabriel!'); + expect(f('hello gabriel')).toBe('no'); + expect(f('gabriel!')).toBe('no'); + expect(f('gabriel')).toBe('no'); + }); + }); + + describe('number compositions', () => { + it(`P.number.optional()`, () => { + const f = (input?: string | number) => + match(input) + .with(P.number.optional(), (value) => { + type t = Expect>; + return `yes ${value}`; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(102)).toBe('yes 102'); + expect(f()).toBe('yes undefined'); + expect(f('gabriel')).toBe('no'); + }); + + it(`P.number.select()`, () => { + const f = (input?: string | number) => + match({ input }) + .with({ input: P.number.select() }, (value) => { + type t = Expect>; + return `yes ${value}`; + }) + .otherwise(() => 'no'); + + expect(f(102)).toBe('yes 102'); + expect(f()).toBe('no'); + expect(f('gabriel')).toBe('no'); + }); + + it(`P.number.int().positive().finite().between(..).optional().select(),`, () => { + const f = (input?: string | number) => + match({ input }) + .with( + { + input: P.number + .int() + .positive() + .finite() + .between(3, 7) + .optional() + .select(), + }, + (value) => { + type t = Expect>; + return `yes ${value}`; + } + ) + .otherwise(() => 'no'); + + expect(f(5)).toBe('yes 5'); + expect(f()).toBe('yes undefined'); + expect(f(1)).toBe('no'); + expect(f(8)).toBe('no'); + expect(f(-2)).toBe('no'); + expect(f(4.123)).toBe('no'); + expect(f(Infinity)).toBe('no'); + }); + }); + + describe('bigint compositions', () => { + it(`P.bigint.optional()`, () => { + const f = (input?: string | bigint) => + match(input) + .with(P.bigint.optional(), (value) => { + type t = Expect>; + return `yes ${value}`; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(102n)).toBe('yes 102'); + expect(f()).toBe('yes undefined'); + expect(f('gabriel')).toBe('no'); + }); + + it(`P.bigint.select()`, () => { + const f = (input?: string | bigint) => + match({ input }) + .with({ input: P.bigint.select() }, (value) => { + type t = Expect>; + return `yes ${value}`; + }) + .otherwise(() => 'no'); + + expect(f(102n)).toBe('yes 102'); + expect(f()).toBe('no'); + expect(f('gabriel')).toBe('no'); + }); + + it(`P.bigint.positive().between(..).optional().select(),`, () => { + const f = (input?: string | bigint) => + match({ input }) + .with( + { + input: P.bigint.positive().between(3n, 7n).optional().select(), + }, + (value) => { + type t = Expect>; + return `yes ${value}`; + } + ) + .otherwise(() => 'no'); + + expect(f(5n)).toBe('yes 5'); + expect(f()).toBe('yes undefined'); + expect(f(1n)).toBe('no'); + expect(f(8n)).toBe('no'); + expect(f(-2n)).toBe('no'); + }); + }); + + describe('and', () => { + it('should infer the intersection of narrowed patterns', () => { + const f = (input?: string | number) => + match(input) + .with( + P.string.startsWith('hello ').and(P.string.endsWith('!')), + (value) => { + type t = Expect< + Equal + >; + return `yes: ${value}`; + } + ) + .otherwise(() => 'no'); + + expect(f('hello gabriel!')).toBe('yes: hello gabriel!'); + expect(f('hello gabriel')).toBe('no'); + expect(f('gabriel!')).toBe('no'); + expect(f('gabriel')).toBe('no'); + }); + }); + + describe('or', () => { + it('should infer the union of narrowed patterns', () => { + const f = (input?: string | number) => + match(input) + .with( + P.string.startsWith('hello ').or(P.string.endsWith('!')), + (value) => { + type t = Expect< + Equal + >; + return `yes: ${value}`; + } + ) + .otherwise(() => 'no'); + + expect(f('hello gabriel!')).toBe('yes: hello gabriel!'); + expect(f('hello gabriel')).toBe('yes: hello gabriel'); + expect(f('gabriel!')).toBe('yes: gabriel!'); + expect(f('gabriel')).toBe('no'); + }); + }); +}); diff --git a/tests/deep-exclude.test.ts b/tests/deep-exclude.test.ts index 96598eca..4a252175 100644 --- a/tests/deep-exclude.test.ts +++ b/tests/deep-exclude.test.ts @@ -226,6 +226,35 @@ describe('DeepExclude', () => { }); }); + describe('Variadic', () => { + it('should correctly turn variadic exclude into their opposite', () => { + type res1 = DeepExclude; + type test1 = Expect>; + + type res2 = DeepExclude; + type test2 = Expect>; + + type res3 = DeepExclude; + type test3 = Expect>; + + type res4 = DeepExclude<[number, ...number[]], [...number[], number]>; + // @ts-expect-error fixme! never would make more sense here. + type test4 = Expect>; + }); + + it('should only exclude if the pattern really matches', () => { + type res1 = DeepExclude; + type test1 = Expect>; + + type res3 = DeepExclude; + type test3 = Expect>; + + // matches, but some cases may not have been handled. + type res4 = DeepExclude<[number, ...string[]], [...number[], string]>; + type test4 = Expect>; + }); + }); + describe('List', () => { type cases = [ Expect, (1 | 2 | 3)[]>>, @@ -237,6 +266,11 @@ describe('DeepExclude', () => { ]; it('should work with empty list patterns', () => { + type res1 = DeepExclude<{ values: (1 | 2 | 3)[] }, { values: [] }>; + type test1 = Expect< + Equal + >; + type cases = [ Expect, [1, 2, 3]>>, Expect< @@ -250,12 +284,6 @@ describe('DeepExclude', () => { DeepExclude<{ values: [1, 2, 3] }, { values: [] }>, { values: [1, 2, 3] } > - >, - Expect< - Equal< - DeepExclude<{ values: (1 | 2 | 3)[] }, { values: [] }>, - { values: (1 | 2 | 3)[] } - > > ]; }); diff --git a/tests/distribute-unions.test.ts b/tests/distribute-unions.test.ts index aa814faf..1574c83c 100644 --- a/tests/distribute-unions.test.ts +++ b/tests/distribute-unions.test.ts @@ -10,269 +10,275 @@ import { Option } from './types-catalog/utils'; describe('FindAllUnions', () => { it('should correctly find all unions on an object', () => { - type cases = [ - Expect< - Equal< - FindUnions<{ a: 1 | 2; b: 3 | 4; c: 6 | 7 }, { a: 1; b: 3 }>, - [ - { - cases: - | { - value: 1; - subUnions: []; - } - | { - value: 2; - subUnions: []; - }; - path: ['a']; - }, - { - cases: - | { - value: 4; - subUnions: []; - } - | { - value: 3; - subUnions: []; - }; - path: ['b']; - } - ] - > - >, - Expect< - Equal< - FindUnions< - { - a: 1 | 2; - b: 3 | 4; - c: 5 | 6; - d: 7 | 8; // not matched - }, - { a: 1; b: 3; c: 5 } - >, - [ - { - cases: - | { - value: 1; - subUnions: []; - } - | { - value: 2; - subUnions: []; - }; - path: ['a']; - }, - { - cases: - | { - value: 3; - subUnions: []; - } - | { - value: 4; - subUnions: []; - }; - path: ['b']; - }, - { - cases: - | { - value: 5; - subUnions: []; - } - | { - value: 6; - subUnions: []; - }; - path: ['c']; - } - ] - > - >, - Expect< - Equal< - FindUnions< - { - a: 1 | 2; - b: 3 | 4; - c: 5 | 6; - d: { e: 7 | 8; f: 9 | 10 }; - g: 11 | 12; // not matched by the pattern - }, - { - a: 1; - b: 3; - c: 5; - d: { e: 7; f: 9 }; - } - >, - [ - { - cases: - | { - value: 1; - subUnions: []; - } - | { - value: 2; - subUnions: []; - }; - path: ['a']; - }, - { - cases: - | { - value: 3; - subUnions: []; - } - | { - value: 4; - subUnions: []; - }; - path: ['b']; - }, - { - cases: - | { - value: 5; - subUnions: []; - } - | { - value: 6; - subUnions: []; - }; - path: ['c']; - }, - { - cases: - | { - value: 7; - subUnions: []; - } - | { - value: 8; - subUnions: []; - }; - path: ['d', 'e']; - }, - { - cases: - | { - value: 9; - subUnions: []; - } - | { - value: 10; - subUnions: []; - }; - path: ['d', 'f']; - } - ] - > - >, - Expect< - Equal< - FindUnions< - { a: { b: { e: 7 | 8; f: 9 | 10 } } } | { c: 11 | 12 }, - { a: { b: { e: 7; f: 9 } } } - >, - [ - { - cases: - | { - value: { a: { b: { e: 7 | 8; f: 9 | 10 } } }; - subUnions: [ - { - cases: - | { - value: 7; - subUnions: []; - } - | { - value: 8; - subUnions: []; - }; - path: ['a', 'b', 'e']; - }, - { - cases: - | { - value: 9; - subUnions: []; - } - | { - value: 10; - subUnions: []; - }; - path: ['a', 'b', 'f']; - } - ]; - } - | { value: { c: 11 | 12 }; subUnions: [] }; - path: []; - } - ] - > - >, - Expect< - Equal< - FindUnions< - { - e: 'not a union'; - a: { - e: 7 | 8; - f: 9 | 10; - g: 11 | 12; // not matched - }; - b: 2 | 3; - }, - { e: 'not a union'; a: { e: 7; f: 9 }; b: 2 } - >, - [ - { - cases: - | { - value: 7; - subUnions: []; - } - | { - value: 8; - subUnions: []; - }; - path: ['a', 'e']; - }, - { - cases: - | { - value: 9; - subUnions: []; - } - | { - value: 10; - subUnions: []; - }; - path: ['a', 'f']; - }, - { - cases: - | { - value: 2; - subUnions: []; - } - | { - value: 3; - subUnions: []; - }; - path: ['b']; - } - ] - > + type res1 = FindUnions<{ a: 1 | 2; b: 3 | 4; c: 6 | 7 }, { a: 1; b: 3 }>; + type test1 = Expect< + Equal< + res1, + [ + { + cases: + | { + value: 1; + subUnions: []; + } + | { + value: 2; + subUnions: []; + }; + path: ['a']; + }, + { + cases: + | { + value: 4; + subUnions: []; + } + | { + value: 3; + subUnions: []; + }; + path: ['b']; + } + ] > - ]; + >; + type res2 = FindUnions< + { + a: 1 | 2; + b: 3 | 4; + c: 5 | 6; + d: 7 | 8; // not matched + }, + { a: 1; b: 3; c: 5 } + >; + type test2 = Expect< + Equal< + res2, + [ + { + cases: + | { + value: 1; + subUnions: []; + } + | { + value: 2; + subUnions: []; + }; + path: ['a']; + }, + { + cases: + | { + value: 3; + subUnions: []; + } + | { + value: 4; + subUnions: []; + }; + path: ['b']; + }, + { + cases: + | { + value: 5; + subUnions: []; + } + | { + value: 6; + subUnions: []; + }; + path: ['c']; + } + ] + > + >; + type res3 = FindUnions< + { + a: 1 | 2; + b: 3 | 4; + c: 5 | 6; + d: { e: 7 | 8; f: 9 | 10 }; + g: 11 | 12; // not matched by the pattern + }, + { + a: 1; + b: 3; + c: 5; + d: { e: 7; f: 9 }; + } + >; + + type test3 = Expect< + Equal< + res3, + [ + { + cases: + | { + value: 1; + subUnions: []; + } + | { + value: 2; + subUnions: []; + }; + path: ['a']; + }, + { + cases: + | { + value: 3; + subUnions: []; + } + | { + value: 4; + subUnions: []; + }; + path: ['b']; + }, + { + cases: + | { + value: 5; + subUnions: []; + } + | { + value: 6; + subUnions: []; + }; + path: ['c']; + }, + { + cases: + | { + value: 7; + subUnions: []; + } + | { + value: 8; + subUnions: []; + }; + path: ['d', 'e']; + }, + { + cases: + | { + value: 9; + subUnions: []; + } + | { + value: 10; + subUnions: []; + }; + path: ['d', 'f']; + } + ] + > + >; + + type res4 = FindUnions< + { a: { b: { e: 7 | 8; f: 9 | 10 } } } | { c: 11 | 12 }, + { a: { b: { e: 7; f: 9 } } } + >; + type test4 = Expect< + Equal< + res4, + [ + { + cases: + | { + value: { a: { b: { e: 7 | 8; f: 9 | 10 } } }; + subUnions: [ + { + cases: + | { + value: 7; + subUnions: []; + } + | { + value: 8; + subUnions: []; + }; + path: ['a', 'b', 'e']; + }, + { + cases: + | { + value: 9; + subUnions: []; + } + | { + value: 10; + subUnions: []; + }; + path: ['a', 'b', 'f']; + } + ]; + } + | { value: { c: 11 | 12 }; subUnions: [] }; + path: []; + } + ] + > + >; + + type res5 = FindUnions< + { + e: 'not a union'; + a: { + e: 7 | 8; + f: 9 | 10; + g: 11 | 12; // not matched + }; + b: 2 | 3; + }, + { e: 'not a union'; a: { e: 7; f: 9 }; b: 2 } + >; + type test5 = Expect< + Equal< + res5, + [ + { + cases: + | { + value: 7; + subUnions: []; + } + | { + value: 8; + subUnions: []; + }; + path: ['a', 'e']; + }, + { + cases: + | { + value: 9; + subUnions: []; + } + | { + value: 10; + subUnions: []; + }; + path: ['a', 'f']; + }, + { + cases: + | { + value: 2; + subUnions: []; + } + | { + value: 3; + subUnions: []; + }; + path: ['b']; + } + ] + > + >; }); it('should correctly find all unions on a tuple', () => { @@ -420,6 +426,95 @@ describe('FindAllUnions', () => { ]; }); + it('when matched against an empty array, the input should be turned into a union of empty array and non-empty array', () => { + type res1 = FindUnions; + type tes1 = Expect< + Equal< + res1, + [ + { + cases: + | { + value: readonly []; + subUnions: []; + } + | { + value: readonly [number, ...(readonly number[])]; + subUnions: []; + }; + path: []; + } + ] + > + >; + + type res2 = FindUnions<[number], []>; + type tes2 = Expect>; + + type res3 = FindUnions<[number], [number, ...number[]]>; + type tes3 = Expect>; + + type res4 = FindUnions<[number], [...number[], number]>; + type tes4 = Expect>; + + type res5 = FindUnions<[number], [...number[], number]>; + type tes5 = Expect>; + + type res6 = FindUnions; + type tes6 = Expect< + Equal< + res6, + [ + { + cases: + | { + value: readonly []; + subUnions: []; + } + | { + value: readonly [number, ...(readonly number[])]; + subUnions: []; + }; + path: []; + } + ] + > + >; + + type res7 = FindUnions; + type tes7 = Expect< + Equal< + res7, + [ + { + cases: + | { + value: readonly []; + subUnions: []; + } + | { + value: readonly [...number[], number]; + subUnions: []; + }; + path: []; + } + ] + > + >; + + type res8 = FindUnions< + readonly [...number[], number], + readonly [...number[], number] + >; + type tes8 = Expect>; + + type res9 = FindUnions< + readonly [number, ...number[]], + readonly [number, ...number[]] + >; + type tes9 = Expect>; + }); + it('should avoid duplicating the unions, even if the pattern matches the same path twice', () => { type cases = [ Expect< @@ -747,9 +842,11 @@ describe('DistributeMatchingUnions', () => { }); it('should work for non unions', () => { + type res1 = DistributeMatchingUnions<[], []>; + type test1 = Expect>; + type cases = [ Expect, {}>>, - Expect, []>>, Expect< Equal< DistributeMatchingUnions, Map>, diff --git a/tests/exhaustive-match.test.ts b/tests/exhaustive-match.test.ts index 5574682e..86d03f00 100644 --- a/tests/exhaustive-match.test.ts +++ b/tests/exhaustive-match.test.ts @@ -432,13 +432,13 @@ describe('exhaustive()', () => { const input = new Set(['']) as Input; match(input) - .with(new Set([P.string]), (x) => x) + .with(P.set(P.string), (x) => x) // @ts-expect-error .exhaustive(); match(input) - .with(new Set([P.string]), (x) => x) - .with(new Set([P.number]), (x) => new Set([])) + .with(P.set(P.string), (x) => x) + .with(P.set(P.number), (x) => new Set([])) .exhaustive(); }); @@ -448,15 +448,15 @@ describe('exhaustive()', () => { expect( match(input) - .with(new Set([P.string]), (x) => x) + .with(P.set(P.string), (x) => x) // @ts-expect-error .exhaustive() ).toEqual(input); expect( match(input) - .with(new Set([P.string]), (x) => 1) - .with(new Set([P.number]), (x) => 2) + .with(P.set(P.string), (x) => 1) + .with(P.set(P.number), (x) => 2) .exhaustive() ).toEqual(1); }); @@ -467,21 +467,21 @@ describe('exhaustive()', () => { expect( match(input) - .with(new Map([['hello' as const, P.number]]), (x) => x) + .with(P.map('hello', P.number), (x) => x) // @ts-expect-error .exhaustive() ).toEqual(input); expect( match(input) - .with(new Map([['hello' as const, 1 as const]]), (x) => x) + .with(P.map('hello', 1), (x) => x) // @ts-expect-error .exhaustive() ).toEqual(input); expect( match(input) - .with(new Map([['hello', 1 as const]]), (x) => x) + .with(P.map('hello', 1), (x) => x) // @ts-expect-error .exhaustive() ).toEqual(input); @@ -665,9 +665,9 @@ describe('exhaustive()', () => { }); it('should not exclude cases if the pattern is a literal type and the value is not', () => { - match({ x: 2 }) + match<{ x: number }>({ x: 2 }) .with({ x: 2 }, ({ x }) => { - type t = Expect>; + type t = Expect>; return ''; }) // @ts-expect-error @@ -871,7 +871,7 @@ describe('exhaustive()', () => { match(input) .with({ t: 'a', x: 'hello' }, (x) => 'ok') .with({ t: 'b' }, (x) => 'ok') - // FIXME this should error ideally: @ts-expect-error + // FIXME should error @ts-expect-error .exhaustive(); const f3 = (input: { t: 'a'; x: any } | { t: 'b' }) => @@ -900,7 +900,7 @@ describe('exhaustive()', () => { { age: 'c' | 'd'; sex: 'b'; - oopsThisIsATypo: string; + oopsThisIsATypo: 'c'; } > >; diff --git a/tests/extract-precise-value.test.ts b/tests/extract-precise-value.test.ts index 761058cb..88464759 100644 --- a/tests/extract-precise-value.test.ts +++ b/tests/extract-precise-value.test.ts @@ -1,20 +1,19 @@ import { ExtractPreciseValue } from '../src/types/ExtractPreciseValue'; -import { Expect, Equal, LeastUpperBound } from '../src/types/helpers'; -import { ToExclude } from '../src/types/Pattern'; -import { Event, Option, State } from './types-catalog/utils'; +import { Expect, Equal } from '../src/types/helpers'; +import { AsyncResult, Event, Option, State } from './types-catalog/utils'; describe('ExtractPreciseValue', () => { it('should correctly extract the matching value from the input and an inverted pattern', () => { + type res1 = ExtractPreciseValue< + { type: 'test' } | ['hello', Option] | 'hello'[], + ['hello', { kind: 'some' }] + >; + + type test1 = Expect< + Equal + >; + type cases = [ - Expect< - Equal< - ExtractPreciseValue< - { type: 'test' } | ['hello', Option] | 'hello'[], - ['hello', { kind: 'some' }] - >, - ['hello', { kind: 'some'; value: string }] - > - >, Expect< Equal< ExtractPreciseValue< @@ -210,14 +209,17 @@ describe('ExtractPreciseValue', () => { }); it('should work with arrays', () => { - type cases = [ - Expect< - Equal< - ExtractPreciseValue, - string[] - > - > - ]; + type res1 = ExtractPreciseValue< + boolean | { type: string } | string[], + string[] + >; + type test1 = Expect>; + + type res2 = ExtractPreciseValue< + ({ a: string } | { b?: number | boolean; c: string })[], + { b: number }[] + >; + type test2 = Expect>; }); describe('Optional properties', () => { @@ -235,15 +237,6 @@ describe('ExtractPreciseValue', () => { { type: 'test'; id?: string } > >, - Expect< - Equal< - ExtractPreciseValue< - Input, - { type: 'test'; id: ToExclude } - >, - { type: 'test'; id: string } - > - >, Expect< Equal< ExtractPreciseValue, @@ -386,4 +379,121 @@ describe('ExtractPreciseValue', () => { ]; }); }); + + describe('variadic patterns', () => { + it('[a, ...b[]]', () => { + type res1 = ExtractPreciseValue; + type t1 = Expect>; + + type res2 = ExtractPreciseValue; + type t2 = Expect>; + + type res3 = ExtractPreciseValue< + [string, ...boolean[]], + ['a', ...unknown[]] + >; + type t3 = Expect>; + + type res4 = ExtractPreciseValue< + (string | boolean)[], + ['a', ...unknown[]] + >; + type t4 = Expect>; + }); + + it('[a, b, ...c[]]', () => { + type res1 = ExtractPreciseValue< + unknown[], + [unknown, unknown, ...unknown[]] + >; + type t1 = Expect>; + + type res2 = ExtractPreciseValue< + unknown[], + [number, boolean, ...string[]] + >; + type t2 = Expect>; + + type res3 = ExtractPreciseValue< + [string, number, ...boolean[]], + ['a', 2, ...unknown[]] + >; + type t3 = Expect>; + }); + + it('[...a[], b]', () => { + type res1 = ExtractPreciseValue; + type t1 = Expect>; + + type res2 = ExtractPreciseValue; + type t2 = Expect>; + + type res3 = ExtractPreciseValue< + [...boolean[], string], + [...unknown[], 'a'] + >; + type t3 = Expect>; + }); + it('[...a[], b, c]', () => { + type res1 = ExtractPreciseValue< + unknown[], + [...unknown[], unknown, unknown] + >; + type t1 = Expect>; + + type res2 = ExtractPreciseValue< + unknown[], + [...string[], number, boolean] + >; + type t2 = Expect>; + + type res3 = ExtractPreciseValue< + [...boolean[], string, boolean], + [...unknown[], 'a', true] + >; + type t3 = Expect>; + }); + it('[a, ...b[], c]', () => { + type res1 = ExtractPreciseValue< + unknown[], + [unknown, ...unknown[], unknown] + >; + type t1 = Expect>; + + type res2 = ExtractPreciseValue< + unknown[], + [number, ...string[], boolean] + >; + type t2 = Expect>; + + type res3 = ExtractPreciseValue< + [string, ...boolean[], number], + ['a', ...unknown[], 2] + >; + type t3 = Expect>; + }); + }); +}); + +describe('generics', () => { + it("shouldn't get stuck on generics in the input structure that aren't matched by the pattern", () => { + const fn = () => { + type res1 = ExtractPreciseValue< + // ^? + AsyncResult, + { status: 'loading' } + >; + + type test1 = Expect< + Equal< + res1, + { + status: 'loading'; + data?: TResult | undefined; + error?: TError | undefined; + } + > + >; + }; + }); }); diff --git a/tests/find-selected.test.ts b/tests/find-selected.test.ts index c14087f8..41d9ba89 100644 --- a/tests/find-selected.test.ts +++ b/tests/find-selected.test.ts @@ -19,22 +19,19 @@ type AnonymousSelectP = SelectP; describe('FindSelected', () => { describe('should correctly return kwargs', () => { it('Tuples', () => { + type res1 = FindSelected< + { a: { b: { c: [3] } } }, + { + a: { + b: { + c: [SelectP<'c'>]; + }; + }; + } + >; + type test1 = Expect>; + type cases = [ - Expect< - Equal< - FindSelected< - { a: { b: { c: [3] } } }, - { - a: { - b: { - c: [SelectP<'c'>]; - }; - }; - } - >, - { c: 3 } - > - >, Expect< Equal< FindSelected<[State, Event], [SelectP<'state'>, SelectP<'event'>]>, @@ -77,6 +74,170 @@ describe('FindSelected', () => { ]; }); + describe('variadic tuples', () => { + it('[a, ...b[]]', () => { + type res1 = FindSelected< + [State, ...Event[]], + [SelectP<'state'>, ...ArrayP>[]] + >; + type test1 = Expect>; + + type res2 = FindSelected< + [1, ...number[]], + [AnonymousSelectP, ...ArrayP[]] + >; + type test2 = Expect>; + + type res3 = FindSelected< + [1, ...number[]], + [unknown, ...ArrayP[]] + >; + type test3 = Expect>; + }); + + it('[a, b, ...c[]]', () => { + type res1 = FindSelected< + [State, State, ...Event[]], + [ + SelectP<'state'>, + SelectP<'state2'>, + ...ArrayP>[] + ] + >; + type test1 = Expect< + Equal + >; + + type res2 = FindSelected< + [1, 2, ...number[]], + [AnonymousSelectP, unknown, ...ArrayP[]] + >; + type test2 = Expect>; + + type res3 = FindSelected< + [1, 2, ...number[]], + [unknown, AnonymousSelectP, ...ArrayP[]] + >; + type test3 = Expect>; + + type res4 = FindSelected< + [1, 2, ...number[]], + [unknown, unknown, ...ArrayP[]] + >; + type test4 = Expect>; + }); + it('[...a[], b]', () => { + type res1 = FindSelected< + [...Event[], State], + [...ArrayP>[], SelectP<'state'>] + >; + type test1 = Expect>; + + type res2 = FindSelected< + [...number[], 1], + [...ArrayP[], AnonymousSelectP] + >; + type test2 = Expect>; + + type res3 = FindSelected< + [...number[], 1], + [...ArrayP[], unknown] + >; + type test3 = Expect>; + }); + it('[...a[], b, c]', () => { + type res1 = FindSelected< + [...Event[], State, State], + [ + ...ArrayP>[], + SelectP<'state'>, + SelectP<'state2'> + ] + >; + type test1 = Expect< + Equal + >; + + type res2 = FindSelected< + [...number[], 1, 2], + [...ArrayP[], AnonymousSelectP, unknown] + >; + type test2 = Expect>; + + type res3 = FindSelected< + [...number[], 1, 2], + [...ArrayP[], unknown, AnonymousSelectP] + >; + type test3 = Expect>; + + type res4 = FindSelected< + [...number[], 1, 2], + [...ArrayP[], unknown, unknown] + >; + type test4 = Expect>; + }); + + it('[a, ...b[], c]', () => { + type res1 = FindSelected< + [State, ...Event[], State], + [ + SelectP<'state'>, + ...ArrayP>[], + SelectP<'state2'> + ] + >; + type test1 = Expect< + Equal + >; + + type res2 = FindSelected< + [1, ...number[], 2], + [AnonymousSelectP, ...ArrayP[], unknown] + >; + type test2 = Expect>; + + type res3 = FindSelected< + [1, ...number[], 2], + [unknown, ...ArrayP[], AnonymousSelectP] + >; + type test3 = Expect>; + + type res4 = FindSelected< + [1, ...number[], 2], + [unknown, ...ArrayP[], unknown] + >; + type test4 = Expect>; + }); + + it('[a, b, select(c), ...d[], e]', () => { + type res1 = FindSelected< + [State, State, number, ...Event[], 1], + [1, 2, AnonymousSelectP, ...ArrayP[], 4] + >; + type test1 = Expect>; + + type res2 = FindSelected< + [State, State, Event, ...State[], 1], + [1, 2, AnonymousSelectP, ...ArrayP[], 4] + >; + type test2 = Expect>; + }); + + it('[a, ...b[], select(c), d, e]', () => { + type res1 = FindSelected< + [State, State, State, number, State, State], + [1, ...ArrayP[], AnonymousSelectP, 4, 2] + >; + type test1 = Expect>; + + type res2 = FindSelected< + [State, State, State, State, number, State], + [1, ...ArrayP[], AnonymousSelectP, 4, 2] + >; + type test2 = Expect>; + }); + }); + it('list selections should be wrapped in arrays', () => { type cases = [ Expect< @@ -138,29 +299,26 @@ describe('FindSelected', () => { }); it('Mixed', () => { - type cases = [ - Expect< - Equal< - FindSelected< - { a: { b: { c: [3, 4] } } }, - { a: { b: { c: [SelectP<'c'>, unknown] } } } - >, - { c: 3 } - > - >, - Expect< - Equal< - FindSelected< - { a: [{ c: 3 }, { e: 7 }]; b: { d: string }[] }, - { - a: [{ c: SelectP<'c'> }, { e: 7 }]; - b: Matcher }, 'array'>; - } - >, - { c: 3; d: string[] } - > - > - ]; + type res1 = FindSelected< + { a: { b: { c: [3, 4] } } }, + { a: { b: { c: [SelectP<'c'>, unknown] } } } + >; + + type res12 = FindSelected< + [{ c: 3 }, { e: 7 }], + [{ c: SelectP<'c'> }, { e: 7 }] + >; + + type x = Extract<[1, 2], readonly any[]>; + type test1 = Expect>; + type res2 = FindSelected< + { a: [{ c: 3 }, { e: 7 }]; b: { d: string }[] }, + { + a: [{ c: SelectP<'c'> }, { e: 7 }]; + b: Matcher }, 'array'>; + } + >; + type test2 = Expect>; }); }); diff --git a/tests/generics.test.ts b/tests/generics.test.ts index f2c72ab5..ce4766af 100644 --- a/tests/generics.test.ts +++ b/tests/generics.test.ts @@ -1,6 +1,13 @@ import { match, P } from '../src'; import { Equal, Expect } from '../src/types/helpers'; -import { none, Option, some } from './types-catalog/utils'; +import { + AsyncResult, + AsyncResultError, + AsyncResultSuccess, + none, + Option, + some, +} from './types-catalog/utils'; describe('generics', () => { type State = @@ -98,4 +105,45 @@ describe('generics', () => { .otherwise(() => 'nope'); }; }); + + it("shouldn't get stucked on type parameters if they aren't included in the pattern", () => { + const fn = (result: AsyncResult) => { + return match(result) + .with({ status: 'success' }, (x) => { + type test = Expect< + Equal> + >; + }) + .with({ status: 'error' }, (x) => { + type test = Expect< + Equal> + >; + }) + .with({ status: 'loading' }, (x) => { + type test = Expect< + Equal< + typeof x, + { + status: 'loading'; + error?: TError | undefined; + data?: TResult | undefined; + } + > + >; + }) + .with({ status: 'idle' }, (x) => { + type test = Expect< + Equal< + typeof x, + { + status: 'idle'; + error?: TError | undefined; + data?: TResult | undefined; + } + > + >; + }) + .exhaustive(); + }; + }); }); diff --git a/tests/helpers.test.ts b/tests/helpers.test.ts index a8e2db36..891fad5b 100644 --- a/tests/helpers.test.ts +++ b/tests/helpers.test.ts @@ -8,6 +8,7 @@ import { Take, IntersectObjects, UpdateAt, + IsReadonlyArray, } from '../src/types/helpers'; describe('helpers', () => { @@ -163,4 +164,28 @@ describe('helpers', () => { >; }); }); + + describe('IsReadonlyArray', () => { + type t1 = IsReadonlyArray; + type test1 = Expect>; + type t2 = IsReadonlyArray; + type test2 = Expect>; + type t3 = IsReadonlyArray; + type test3 = Expect>; + type t4 = IsReadonlyArray; + type test4 = Expect>; + type t5 = IsReadonlyArray; + type test5 = Expect>; + + type t6 = IsReadonlyArray<[]>; + type test6 = Expect>; + type t7 = IsReadonlyArray; + type test7 = Expect>; + type t8 = IsReadonlyArray<[number]>; + type test8 = Expect>; + type t9 = IsReadonlyArray<[number, ...any[]]>; + type test9 = Expect>; + type t10 = IsReadonlyArray<[...any[], number]>; + type test10 = Expect>; + }); }); diff --git a/tests/intersection-and-union.test.ts b/tests/intersection-and-union.test.ts index 230916bb..f91699bd 100644 --- a/tests/intersection-and-union.test.ts +++ b/tests/intersection-and-union.test.ts @@ -159,7 +159,6 @@ describe('and, and or patterns', () => { >; return 'branch 2'; }) - // FIXME: This should work .exhaustive(); }); @@ -224,8 +223,8 @@ describe('and, and or patterns', () => { const f = (n: Parent) => match(n) .with( - P.intersection(P.instanceOf(Child1), { - a: P.optional(P.instanceOf(Child2)), + P.instanceOf(Child1).and({ + a: P.instanceOf(Child2).optional(), b: P.instanceOf(Child2), }), (x) => { @@ -236,12 +235,10 @@ describe('and, and or patterns', () => { } ) .with( - P.intersection( - { a: P.instanceOf(Child1) }, - P.union( - { a: { a: P.instanceOf(Child1), b: P.instanceOf(Child1) } }, - { b: { a: P.instanceOf(Child2), b: P.instanceOf(Child2) } } - ) + P.shape({ a: P.instanceOf(Child1) }).and( + P.shape({ + a: { a: P.instanceOf(Child1), b: P.instanceOf(Child1) }, + }).or({ b: { a: P.instanceOf(Child2), b: P.instanceOf(Child2) } }) ), (x) => { type t = Expect< @@ -606,8 +603,7 @@ describe('and, and or patterns', () => { const errorF = (input: Input) => match(input) - // @ts-expect-error FIXME this should work - .with({ value: P.array({ type: P.union('a', 'b') }) }, (x) => {}) + .with({ value: P.array({ type: P.union('a', 'b', 'c') }) }, (x) => {}) .exhaustive(); const f = (input: Input) => { @@ -619,10 +615,16 @@ describe('and, and or patterns', () => { Equal< typeof x, | { - value: { type: 'a'; n: number }[]; + value: { + type: 'a'; + n: number; + }[]; } | { - value: { type: 'b'; s: string }[]; + value: { + type: 'b'; + s: string; + }[]; } > >; @@ -723,7 +725,7 @@ describe('and, and or patterns', () => { .otherwise(() => 'ko'); }); - it('Should work with P.typed()', () => { + it('Inference should work at the top level', () => { class A { constructor(public foo: 'bar' | 'baz') {} } @@ -735,7 +737,7 @@ describe('and, and or patterns', () => { const f = (input: A | B) => match(input) .with( - P.typed().intersection(P.instanceOf(A), { foo: 'bar' }), + P.intersection(P.instanceOf(A), { foo: 'bar' }), // prop: A & { foo: 'bar' } (prop) => { type t = Expect>; @@ -743,7 +745,7 @@ describe('and, and or patterns', () => { } ) .with( - P.typed().intersection(P.instanceOf(A), { foo: 'baz' }), + P.intersection(P.instanceOf(A), { foo: 'baz' }), // prop: A & { foo: 'baz' } (prop) => { type t = Expect>; diff --git a/tests/invert-pattern.test.ts b/tests/invert-pattern.test.ts index 7022a13b..2ba60f9e 100644 --- a/tests/invert-pattern.test.ts +++ b/tests/invert-pattern.test.ts @@ -1,6 +1,201 @@ import { Equal, Expect } from '../src/types/helpers'; -import { InvertPatternForExclude } from '../src/types/InvertPattern'; -import { Matcher } from '../src/types/Pattern'; +import { + InvertPattern, + InvertPatternForExclude, +} from '../src/types/InvertPattern'; +import { ArrayP, GuardP, Matcher, Pattern } from '../src/types/Pattern'; + +describe('InvertPattern', () => { + describe('variadic tuples', () => { + it('[a, ...b[]]', () => { + type pattern1 = [ + 'Hello', + ...Matcher, 'array'>[] + ]; + type inverted1 = InvertPattern; + // ^? + type test1 = Expect>; + + type pattern2 = [ + GuardP, + ...Matcher[] + ]; + type inverted2 = InvertPattern; + // ^? + type test2 = Expect>; + + type pattern3 = [ + GuardP, + ...Matcher, 'array'>[] + ]; + type inverted3 = InvertPattern; + // ^? + type test3 = Expect>; + + type pattern6 = { + key: readonly [ + GuardP, + ...ArrayP>[] + ]; + }; + type input6 = unknown; + type inverted6 = InvertPattern; + // ^? + type test6 = Expect>; + }); + + it('[a, b, ...c[]]', () => { + type pattern1 = [ + 'Hello', + 7, + ...Matcher, 'array'>[] + ]; + type inverted1 = InvertPattern; + // ^? + type test1 = Expect>; + + type pattern2 = [ + GuardP, + GuardP, + ...Matcher[] + ]; + type inverted2 = InvertPattern; + // ^? + type test2 = Expect>; + + type pattern3 = [ + GuardP, + GuardP, + ...Matcher, 'array'>[] + ]; + type inverted3 = InvertPattern; + // ^? + type test3 = Expect>; + }); + it('[...a[], b]', () => { + type pattern1 = [ + ...Matcher, 'array'>[], + 'Hello' + ]; + type inverted1 = InvertPattern; + // ^? + type test1 = Expect>; + + type pattern2 = [ + ...Matcher[], + GuardP + ]; + type inverted2 = InvertPattern; + // ^? + type test2 = Expect>; + + type pattern3 = [ + ...Matcher, 'array'>[], + GuardP + ]; + type inverted3 = InvertPattern; + // ^? + type test3 = Expect>; + }); + it('[...a[], b, c]', () => { + type pattern1 = [ + ...Matcher, 'array'>[], + 'Hello', + 7 + ]; + type inverted1 = InvertPattern; + // ^? + type test1 = Expect>; + + type pattern2 = [ + ...Matcher[], + GuardP, + GuardP + ]; + type inverted2 = InvertPattern; + // ^? + type test2 = Expect>; + + type pattern3 = [ + ...Matcher, 'array'>[], + GuardP, + GuardP + ]; + type inverted3 = InvertPattern; + // ^? + type test3 = Expect>; + }); + it('[a, ...b[], c]', () => { + type pattern1 = [ + 7, + ...Matcher, 'array'>[], + 'Hello' + ]; + type inverted1 = InvertPattern; + // ^? + type test1 = Expect>; + + type pattern2 = [ + GuardP, + ...Matcher[], + GuardP + ]; + type inverted2 = InvertPattern; + // ^? + type test2 = Expect>; + + type pattern3 = [ + GuardP, + ...Matcher, 'array'>[], + GuardP + ]; + type inverted3 = InvertPattern; + // ^? + type test3 = Expect>; + }); + + it('[a, b, ...c[], d, e]', () => { + type pattern1 = [ + 7, + 8, + ...Matcher, 'array'>[], + 'Hello', + 'Bonjour' + ]; + type inverted1 = InvertPattern; + // ^? + type test1 = Expect< + Equal + >; + + type pattern2 = [ + GuardP, + GuardP, + ...Matcher[], + GuardP, + GuardP + ]; + type inverted2 = InvertPattern; + // ^? + type test2 = Expect< + Equal + >; + + type pattern3 = [ + GuardP, + GuardP, + ...Matcher, 'array'>[], + GuardP, + GuardP + ]; + type inverted3 = InvertPattern; + // ^? + type test3 = Expect< + Equal + >; + }); + }); +}); describe('InvertPatternForExclude', () => { it('should correctly invert type guards', () => { @@ -31,45 +226,28 @@ describe('InvertPatternForExclude', () => { }); it('should work with objects', () => { - type t = InvertPatternForExclude< + type res1 = InvertPatternForExclude< { a: Matcher }, { a: string; b: number } | [1, 2] >; - - type cases = [ - Expect< - Equal< - InvertPatternForExclude< - { a: Matcher }, - { a: string; b: number } | [1, 2] - >, - Readonly<{ a: string }> - > - > - ]; + type test1 = Expect>>; }); describe('Tuples', () => { it('should work with tuples', () => { - type cases = [ - Expect< - Equal< - InvertPatternForExclude<[1, 2], { a: string; b: number } | [1, 2]>, - readonly [1, 2] - > - > - ]; + type res1 = InvertPatternForExclude< + [1, 2], + { a: string; b: number } | [1, 2] + >; + type test1 = Expect>; }); - it('should return readonly tuples because both mutable and readonly are assignable to them', () => { - type cases = [ - Expect< - Equal< - InvertPatternForExclude<[[[1, 2]]], { a: string } | [[[1, 2]]]>, - readonly [readonly [readonly [1, 2]]] - > - > - ]; + it('should return readonly tuples if the input tuple is readonly, not otherwise', () => { + type res1 = InvertPatternForExclude< + [[[1, 2]]], + { a: string } | readonly [[readonly [1, 2]]] + >; + type test1 = Expect>; }); }); @@ -120,13 +298,104 @@ describe('InvertPatternForExclude', () => { }); }); - describe('issue #44', () => { - it('if the pattern contains unknown keys, inverted this pattern should keep them', () => { - type input = { sex: 'a' | 'b'; age: 'c' | 'd' }; - type pattern = Readonly<{ sex: 'a'; unknownKey: 'c' }>; - type inverted = InvertPatternForExclude; + describe('variadic tuples', () => { + it('[a, ...b[]]', () => { + type pattern1 = ['Hello', ...Matcher, 'array'>[]]; + type input1 = { a: string; b: number } | [string, ...number[]]; + type inverted1 = InvertPatternForExclude; + type test1 = Expect>; - type cases = [Expect>]; + type pattern2 = ['Hello', ...Matcher, 'array'>[]]; + type input2 = [string, ...number[]]; + type inverted2 = InvertPatternForExclude; + type test2 = Expect>; + + type pattern3 = [...Matcher, 'array'>[]]; + type input3 = [...number[]]; + type inverted3 = InvertPatternForExclude; + type test3 = Expect>; + + type pattern4 = readonly [ + GuardP, + ...ArrayP[] + ]; + type input4 = [string | number, ...(string | number)[]]; + type inverted4 = InvertPatternForExclude; + // ^? + type test4 = Expect>; + + type pattern5 = ArrayP; + type input5 = (string | number)[]; + type inverted5 = InvertPatternForExclude; + type test5 = Expect>; + }); + + it('[a, b, ...c[]]', () => { + type pattern1 = [ + 'Hello', + 10, + ...Matcher, 'array'>[] + ]; + type input1 = { a: string; b: number } | [string, number, ...number[]]; + type inverted1 = InvertPatternForExclude; + type test1 = Expect>; + }); + it('[...a[], b]', () => { + type pattern1 = [ + ...Matcher, 'array'>[], + 'Hello' + ]; + type input1 = { a: string; b: number } | [...number[], string]; + type inverted1 = InvertPatternForExclude; + type test1 = Expect>; + }); + it('[...a[], b, c]', () => { + type pattern1 = [ + ...Matcher, 'array'>[], + 'Hello', + true + ]; + type input1 = { a: string; b: number } | [...number[], string, boolean]; + type inverted1 = InvertPatternForExclude; + type test1 = Expect>; }); + it('[a, ...b[], c]', () => { + type pattern1 = [ + 'Hello', + ...Matcher, 'array'>[], + true + ]; + type input1 = { a: string; b: number } | [string, ...number[], boolean]; + type inverted1 = InvertPatternForExclude; + type test1 = Expect>; + }); + }); +}); + +describe('issue #44', () => { + it('if the pattern contains unknown keys, inverted this pattern should keep them', () => { + type input = { sex: 'a' | 'b'; age: 'c' | 'd' }; + type pattern = Readonly<{ sex: 'a'; unknownKey: 'c' }>; + type inverted = InvertPatternForExclude; + + type cases = [Expect>]; + }); +}); + +describe('it should return never if the input pattern is Pattern', () => { + it('InvertPattern', () => { + type input = { sex: 'a' | 'b'; age: 'c' | 'd' }; + type pattern = Pattern; + type inverted = InvertPattern; + // ^? + type test1 = Expect>; + }); + + it('InvertPatternForExclude', () => { + type input = { sex: 'a' | 'b'; age: 'c' | 'd' }; + type pattern = Pattern; + type inverted = InvertPatternForExclude; + // ^? + type test1 = Expect>; }); }); diff --git a/tests/large-exhaustive.test.ts b/tests/large-exhaustive.test.ts index 1e8021e5..fdb45e09 100644 --- a/tests/large-exhaustive.test.ts +++ b/tests/large-exhaustive.test.ts @@ -1,17 +1,17 @@ import { match, P } from '../src'; -import { Equal, Expect } from '../src/types/helpers'; +import { Compute, Equal, Expect, Not } from '../src/types/helpers'; describe('large exhaustive', () => { // prettier-ignore - type LargeObject = { - a1: number; b1: number; c1: number; d1: number; e1: number; f1: number; g1: number; h1: number; i1: number; j1: number; k1: number; l1: number; m1: number; n1: number; o1: number; p1: number; q1: number; r1: number; s1: number; t1: number; u1: number; v1: number; w1: number; x1: number; y1: number; z1: number; - a2: number; b2: number; c2: number; d2: number; e2: number; f2: number; g2: number; h2: number; i2: number; j2: number; k2: number; l2: number; m2: number; n2: number; o2: number; p2: number; q2: number; r2: number; s2: number; t2: number; u2: number; v2: number; w2: number; x2: number; y2: number; z2: number; - a3: number; b3: number; c3: number; d3: number; e3: number; f3: number; g3: number; h3: number; i3: number; j3: number; k3: number; l3: number; m3: number; n3: number; o3: number; p3: number; q3: number; r3: number; s3: number; t3: number; u3: number; v3: number; w3: number; x3: number; y3: number; z3: number; -}; + type LargeObject = Compute<{ + a1: T; b1: T; c1: T; d1: T; e1: T; f1: T; g1: T; h1: T; i1: T; j1: T; k1: T; l1: T; m1: T; n1: T; o1: T; p1: T; q1: T; r1: T; s1: T; t1: T; u1: T; v1: T; w1: T; x1: T; y1: T; z1: T; + a2: T; b2: T; c2: T; d2: T; e2: T; f2: T; g2: T; h2: T; i2: T; j2: T; k2: T; l2: T; m2: T; n2: T; o2: T; p2: T; q2: T; r2: T; s2: T; t2: T; u2: T; v2: T; w2: T; x2: T; y2: T; z2: T; + a3: T; b3: T; c3: T; d3: T; e3: T; f3: T; g3: T; h3: T; i3: T; j3: T; k3: T; l3: T; m3: T; n3: T; o3: T; p3: T; q3: T; r3: T; s3: T; t3: T; u3: T; v3: T; w3: T; x3: T; y3: T; z3: T; +}>; it('large objects', () => { expect( - match(null) + match | null>(null) .with( // prettier-ignore { @@ -38,7 +38,14 @@ describe('large exhaustive', () => { it('large tuple', () => { expect( match< - [LargeObject, LargeObject, LargeObject, LargeObject, LargeObject] | null + | [ + LargeObject, + LargeObject, + LargeObject, + LargeObject, + LargeObject + ] + | null >(null) .with( // prettier-ignore @@ -70,18 +77,9 @@ describe('large exhaustive', () => { } ], (x) => { - type t = Expect< - Equal< - typeof x, - [ - LargeObject, - LargeObject, - LargeObject, - LargeObject, - LargeObject - ] - > - >; + type test1 = Expect>>; + type test2 = Expect>>; + type test3 = Expect>>; return 'match'; } ) diff --git a/tests/lists.test.ts b/tests/lists.test.ts index 635bd06f..c5a26b89 100644 --- a/tests/lists.test.ts +++ b/tests/lists.test.ts @@ -9,7 +9,7 @@ describe('List ([a])', () => { title: 'hellooo', }; const res = match>([httpResult]) - .with([] as const, (x) => { + .with([], (x) => { type t = Expect>; return { kind: 'some', value: [{ id: 0, title: 'LOlol' }] }; }) @@ -21,7 +21,7 @@ describe('List ([a])', () => { }; }) .with(20, (x) => { - type t = Expect>; + type t = Expect>; return { kind: 'none' }; }) .otherwise(() => ({ kind: 'none' })); @@ -58,4 +58,19 @@ describe('List ([a])', () => { ) .otherwise(() => 'something else'); }); + + it('type narrowing should work on nested arrays', () => { + const fn = (input: { queries?: { q?: string[]; a: number }[] }) => + match(input).with( + { + queries: P.array({ q: P.array(P.string) }), + }, + (x) => { + type t = Expect< + Equal + >; + return x.queries[0].q[0]; + } + ); + }); }); diff --git a/tests/maps.test.ts b/tests/maps.test.ts index af333693..8270555b 100644 --- a/tests/maps.test.ts +++ b/tests/maps.test.ts @@ -4,32 +4,35 @@ import { match, P } from '../src'; describe('Map', () => { it('should match Map patterns', () => { const usersMap = new Map([ - ['gab', { name: 'gabriel' }], - ['angégé', { name: 'angéline' }], + ['a', { name: 'alice' }], + ['b', { name: 'bob' }], ]); const userPattern = { name: P.string }; const res = match>(usersMap) - .with( - new Map([ - ['angégé' as const, userPattern], - ['gab' as const, userPattern], - ]), - (map) => ({ - name: map.get('angégé')!.name + ' ' + map.get('gab')!.name, - }) - ) - .with( - new Map([['angégé' as const, userPattern]]), - (map) => map.get('angégé')! - ) - .with(new Map([['gab' as const, userPattern]]), (map) => map.get('gab')!) + .with(P.map(P.union('b', 'a'), userPattern), (map) => ({ + name: map.get('b')!.name + ' ' + map.get('a')!.name, + })) + .with(P.map('b', userPattern), (map) => map.get('b')!) .with(P._, () => ({ name: 'unknown' })) .run(); type t = Expect>; - expect(res).toEqual({ name: 'angéline gabriel' }); + expect(res).toEqual({ name: 'bob alice' }); + }); + + it("should match any map if P.map isn't given any arguments", () => { + const usersMap = new Map([ + ['a', { name: 'alice' }], + ['b', { name: 'bob' }], + ]); + + const res = match>(usersMap) + .with(P.map(), () => true) + .exhaustive(); + type t = Expect>; + expect(res).toEqual(true); }); }); diff --git a/tests/matcher-protocol.test.ts b/tests/matcher-protocol.test.ts new file mode 100644 index 00000000..41940721 --- /dev/null +++ b/tests/matcher-protocol.test.ts @@ -0,0 +1,123 @@ +import { isMatching, match, P } from '../src'; +import { Equal, Expect } from '../src/types/helpers'; + +describe('matcher protocol', () => { + type SomeValue = T extends Some ? V : never; + + interface SomeNarrowFn extends P.unstable_Fn { + output: Some>; + } + + class Some { + constructor(public value: T) {} + + static [P.matcher](): P.unstable_Matcher { + return { + match: (input) => ({ + matched: input instanceof Some, + }), + }; + } + + [P.matcher](): P.unstable_Matcher< + Some ? P.infer : T> + > { + return { + match: (input) => { + return { + matched: + input instanceof Some && isMatching(this.value, input.value), + }; + }, + }; + } + } + + class None { + coucou: number; + constructor() { + this.coucou = 1; + } + static [P.matcher](): P.unstable_Matcher { + return { + match: (input) => { + return { matched: input instanceof None }; + }, + }; + } + } + type Option = Some | None; + + it('should support taking a sub pattern', () => { + const res = match<{ option: Option }>({ + option: new Some(12), + }) + .with({ option: new Some(7) }, (value) => { + type t = Expect }>>; + return value.option.value; + }) + .with({ option: new Some(12) }, (value) => { + type t = Expect }>>; + return value.option.value; + }) + .with({ option: None }, () => '') + .with({ option: Some }, () => '') + .exhaustive(); + + expect(res).toBe(12); + + match>(new Some(12)).with( + new Some(P.number), + (some) => { + type t = Expect>>; + } + ); + }); + + it('should support nesting', () => { + const res = match<{ option: Option }>({ + option: new Some(12), + }) + .with({ option: Some }, (x) => { + type t = Expect }>>; + return `Some ${x.option.value}`; + }) + .with({ option: None }, (x) => { + type t = Expect>; + return 'None'; + }) + .exhaustive(); + + expect(res).toBe(`Some 12`); + }); + + it('it should work without nesting too', () => { + expect( + match>(new Some(12)) + .with(new Some(10), (some) => { + type t = Expect>>; + return `10`; + }) + .with(new Some(12), (some) => `12`) + .with(new Some(P.any), (some) => `any`) + .with(None, () => 0) + .exhaustive() + ).toBe('12'); + + match>(new Some(12)).with( + new Some(P.number), + (some) => { + type t = Expect>>; + } + ); + + match>(new Some(12)) + .with(Some, (some) => { + type t = Expect>>; + }) + .with(None, (none) => { + type t = Expect>; + }) + .exhaustive(); + }); +}); diff --git a/tests/multiple-patterns.test.ts b/tests/multiple-patterns.test.ts index b5f6a54c..ca20e8f8 100644 --- a/tests/multiple-patterns.test.ts +++ b/tests/multiple-patterns.test.ts @@ -147,15 +147,15 @@ describe('Multiple patterns', () => { .with( { a: P.string }, [true, 2], - new Map([['key', P._]]), - new Set([P.number]), + P.map('key', P._), + P.set(P.number), (x) => { type t = Expect< Equal< typeof x, | { a: string; b: number } - | [true, number] - | Map + | [true, 2] + | Map<'key', { x: number }> | Set > >; @@ -163,15 +163,15 @@ describe('Multiple patterns', () => { return 'Object'; } ) - .with([false, 2] as const, (x) => { + .with([false, 2], (x) => { type t = Expect>; return '[false, 2]'; }) - .with([false, P.number] as const, (x) => { + .with([false, P.number], (x) => { type t = Expect>; return '[false, number]'; }) - .with([true, P.number] as const, (x) => { + .with([true, P.number], (x) => { type t = Expect>; return '[true, number]'; }) @@ -184,8 +184,8 @@ describe('Multiple patterns', () => { .with( { a: P.string }, [true, 2], - new Map([['key', P._]]), - new Set([P.number]), + P.map(P.string, P._), + P.set(P.number), (x) => 'Object' ) .with([false, 2], (x) => '[false, 2]') @@ -223,7 +223,7 @@ describe('Multiple patterns', () => { }); it('issue #74: inference must work on every pattern in the list', () => { - match({ a: [1, 2, 3, 4] }) + match<{ a: number[] }>({ a: [1, 2, 3, 4] }) .with( { a: P.when((arr) => { diff --git a/tests/nesting.test.ts b/tests/nesting.test.ts index 1bd0dfb7..c0f88039 100644 --- a/tests/nesting.test.ts +++ b/tests/nesting.test.ts @@ -22,7 +22,25 @@ describe('Nesting', () => { .with( { type: 'post', content: { video: { id: 2, content: { src: '' } } } }, (x) => { - type t = Expect>; + type t = Expect< + Equal< + typeof x, + { + id: number; + type: 'post'; + content: { + body: string; + video: { + type: 'video'; + id: 2; + content: { + src: ''; + }; + }; + }; + } + > + >; return 1; } ) @@ -105,7 +123,7 @@ describe('Nesting', () => { describe('array', () => { it('it should work on 2 levels', () => { expect( - match([{ two: '2', foo: 2, bar: true }] as const) + match([{ two: '2', foo: 2, bar: true }]) .with([{ foo: P.any, bar: P.select('bar') }], ({ bar }) => bar) .exhaustive() ).toEqual(true); @@ -113,7 +131,7 @@ describe('Nesting', () => { it('it should work on 3 levels', () => { expect( - match([[{ two: '2', foo: 2, bar: true }]] as const) + match([[{ two: '2', foo: 2, bar: true }]]) .with([[{ foo: P.any, bar: P.select('bar') }]], ({ bar }) => bar) .exhaustive() ).toEqual(true); @@ -121,7 +139,7 @@ describe('Nesting', () => { it('it should work on 4 levels', () => { expect( - match([[[{ two: '2', foo: 2, bar: true }]]] as const) + match([[[{ two: '2', foo: 2, bar: true }]]]) .with([[[{ foo: P.any, bar: P.select('bar') }]]], ({ bar }) => bar) .exhaustive() ).toEqual(true); @@ -129,7 +147,7 @@ describe('Nesting', () => { it('it should work on 5 levels', () => { expect( - match([[[[{ two: '2', foo: 2, bar: true }]]]] as const) + match([[[[{ two: '2', foo: 2, bar: true }]]]]) .with([[[[{ foo: P.any, bar: P.any }]]]], ([[[[{ bar }]]]]) => bar) .exhaustive() ).toEqual(true); diff --git a/tests/numbers.test.ts b/tests/numbers.test.ts index 2524093c..fc10f43e 100644 --- a/tests/numbers.test.ts +++ b/tests/numbers.test.ts @@ -3,7 +3,7 @@ import { match, P } from '../src'; describe('Numbers', () => { it('Should match exact numbers', () => { - const res = match(1) + const res = match(1) .with(1, (v) => { type t = Expect>; return v * 2; @@ -55,4 +55,155 @@ describe('Numbers', () => { .with(P.number, () => 'number') .exhaustive(); }); + + describe('chainable', () => { + it(`P.number.between(1, 10)`, () => { + const f = (input: string | number) => + match(input) + .with(P.number.between(0, 10), (value) => { + type t = Expect>; + return 'between 0 and 10'; + }) + .otherwise((value) => { + type t = Expect>; + return 'something else'; + }); + + expect(f(5)).toBe('between 0 and 10'); + expect(f(0)).toBe('between 0 and 10'); + expect(f(10)).toBe('between 0 and 10'); + expect(f('gabriel')).toBe('something else'); + }); + + it(`P.number.lt(..)`, () => { + const f = (input: string | number | bigint) => + match(input) + .with(P.number.lt(10), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5)).toBe('yes'); + expect(f(12)).toBe('no'); + expect(f(10n)).toBe('no'); + }); + it(`P.number.gt(..)`, () => { + const f = (input: string | number | bigint) => + match(input) + .with(P.number.gt(10), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5)).toBe('no'); + expect(f(10)).toBe('no'); + expect(f(12)).toBe('yes'); + }); + it(`P.number.gte(..)`, () => { + const f = (input: string | number | bigint) => + match(input) + .with(P.number.gte(10), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5)).toBe('no'); + expect(f(10)).toBe('yes'); + expect(f(12)).toBe('yes'); + }); + it(`P.number.lte(..)`, () => { + const f = (input: string | number | bigint) => + match(input) + .with(P.number.lte(10), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5)).toBe('yes'); + expect(f(10)).toBe('yes'); + expect(f(12)).toBe('no'); + }); + it(`P.number.int(..)`, () => { + const f = (input: string | number | bigint) => + match(input) + .with(P.number.int(), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5)).toBe('yes'); + expect(f(10.123)).toBe('no'); + expect(f(-Infinity)).toBe('no'); + }); + it(`P.number.finite()`, () => { + const f = (input: string | number | bigint) => + match(input) + .with(P.number.finite(), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5)).toBe('yes'); + expect(f(10.123)).toBe('yes'); + expect(f(-Infinity)).toBe('no'); + }); + it(`P.number.positive()`, () => { + const f = (input: string | number | bigint) => + match(input) + .with(P.number.positive(), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5)).toBe('yes'); + expect(f(10.123)).toBe('yes'); + expect(f(-10.123)).toBe('no'); + expect(f(-Infinity)).toBe('no'); + }); + it(`P.number.negative()`, () => { + const f = (input: string | number | bigint) => + match(input) + .with(P.number.negative(), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f(5)).toBe('no'); + expect(f(10.123)).toBe('no'); + expect(f(-10.123)).toBe('yes'); + expect(f(-Infinity)).toBe('yes'); + }); + }); }); diff --git a/tests/optional.test.ts b/tests/optional.test.ts index 669d6071..07c42951 100644 --- a/tests/optional.test.ts +++ b/tests/optional.test.ts @@ -28,7 +28,7 @@ describe('optional', () => { match(input) .with({ a: P.optional({ name: 'Hello' }) }, (x) => { type t = Expect< - Equal + Equal >; return true; }) @@ -59,7 +59,7 @@ describe('optional', () => { } ); - match(input).with({ type: 'a', a: P.optional(P.select()) }, (x) => { + match(input).with({ type: 'a', a: P.select().optional() }, (x) => { type t = Expect< Equal >; diff --git a/tests/otherwise.test.ts b/tests/otherwise.test.ts index 32b1dea5..cff624a4 100644 --- a/tests/otherwise.test.ts +++ b/tests/otherwise.test.ts @@ -2,7 +2,7 @@ import { match } from '../src'; describe('otherwise', () => { it('should pass matched value to otherwise', () => { - const result = match(42) + const result = match(42) .with(51, (d) => d) .otherwise((d) => d); expect(result).toBe(42); diff --git a/tests/pattern.test.ts b/tests/pattern.test.ts index 93f0685b..40685f0e 100644 --- a/tests/pattern.test.ts +++ b/tests/pattern.test.ts @@ -15,27 +15,24 @@ describe('Pattern', () => { }); it('Should return a single object pattern when the input is a union of objects', () => { - type cases = [ - Expect< - Equal< - P.Pattern<{ kind: 'some'; value: number } | { kind: 'none' }>, - | Matcher< - { kind: 'some'; value: number } | { kind: 'none' }, - unknown, - any, - any, - unknown - > - | { - readonly kind?: P.Pattern<'some'>; - readonly value?: P.Pattern; - } - | { - readonly kind?: P.Pattern<'none'>; - } - > + type res1 = P.Pattern<{ kind: 'some'; value: number } | { kind: 'none' }>; + + type test1 = Expect< + Equal< + res1, + | Matcher< + { kind: 'some'; value: number } | { kind: 'none' }, + unknown, + any, + any, + unknown + > + | { + readonly kind?: P.Pattern<'some' | 'none'>; + readonly value?: P.Pattern; + } > - ]; + >; }); it('Should return a single object pattern when the input is a union of objects and other types', () => { @@ -54,12 +51,9 @@ describe('Pattern', () => { unknown > | { - readonly kind?: P.Pattern<'some'>; + readonly kind?: P.Pattern<'some' | 'none'>; readonly value?: P.Pattern; } - | { - readonly kind?: P.Pattern<'none'>; - } | string > >; @@ -76,8 +70,6 @@ describe('Pattern', () => { > | { readonly a?: P.Pattern<{ name: string; age: number }>; - } - | { readonly b?: P.Pattern<''>; } > @@ -99,9 +91,12 @@ describe('Pattern', () => { | undefined > >; + + type res4 = P.Pattern<{ name: string; age: number } | [type: 'Hello']>; + type t4 = Expect< Equal< - P.Pattern<{ name: string; age: number } | [type: 'Hello']>, + res4, | Matcher< { name: string; age: number } | [type: 'Hello'], unknown, diff --git a/tests/readonly.test.ts b/tests/readonly.test.ts index 8ddd59bc..bdf34a4f 100644 --- a/tests/readonly.test.ts +++ b/tests/readonly.test.ts @@ -1,5 +1,16 @@ import { match } from '../src'; -import { Equal, Expect } from '../src/types/helpers'; +import { DeepExclude } from '../src/types/DeepExclude'; +import { + InvertPattern, + InvertPatternForExclude, +} from '../src/types/InvertPattern'; +import { MatchedValue } from '../src/types/Pattern'; +import { + Equal, + Expect, + ExtractWithDefault, + IsReadonlyArray, +} from '../src/types/helpers'; describe('readonly', () => { describe('exhaustive', () => { @@ -7,19 +18,19 @@ describe('readonly', () => { const f = (input: readonly ['a' | 'b', 'c' | 'd']) => match(input) .with(['a', 'c'], (x) => { - type t = Expect>; + type t = Expect>; return 'ok'; }) .with(['a', 'd'], (x) => { - type t = Expect>; + type t = Expect>; return 'ok'; }) .with(['b', 'c'], (x) => { - type t = Expect>; + type t = Expect>; return 'ok'; }) .with(['b', 'd'], (x) => { - type t = Expect>; + type t = Expect>; return 'ok'; }) .exhaustive(); @@ -49,9 +60,7 @@ describe('readonly', () => { ) => match(input) .with({ t: 'a', x: [2, 'hello', 2] }, (x) => { - type t = Expect< - Equal - >; + type t = Expect>; return 'ok'; }) .with({ t: 'a', x: [2, 'hello', 2] as const }, (x) => { diff --git a/tests/real-world.test.ts b/tests/real-world.test.ts index 0cdc382b..2fa1bc99 100644 --- a/tests/real-world.test.ts +++ b/tests/real-world.test.ts @@ -75,7 +75,6 @@ describe('real world example of a complex input type', () => { { viz: P.union('timeseries', 'query_table'), requests: P.array({ - // @ts-expect-error: FIXME, P.union only sees 'timeseries' response_format: P.union('timeseries', 'scalar'), }), }, diff --git a/tests/records.test.ts b/tests/records.test.ts index a61a3f68..9227db91 100644 --- a/tests/records.test.ts +++ b/tests/records.test.ts @@ -17,17 +17,22 @@ describe('Records ({})', () => { expect( match(vector) .with({ x: 1, y: 1, z: 1 }, (x) => { - type t = Expect< - Equal - >; + type t = Expect>; return 'vector3'; }) .with({ x: 2, y: 1 }, (x) => { - type t = Expect>; + type t = Expect< + Equal + >; return 'vector2'; }) .with({ x: 1 }, (x) => { - type t = Expect>; + type t = Expect< + Equal< + typeof x, + { x: 1 } | { x: 1; y: number } | { x: 1; y: number; z: number } + > + >; return 'vector1'; }) .otherwise(() => 'no match') diff --git a/tests/return-type.test.ts b/tests/return-type.test.ts new file mode 100644 index 00000000..9b386ccf --- /dev/null +++ b/tests/return-type.test.ts @@ -0,0 +1,50 @@ +import { P, match } from '../src'; + +describe('returnType', () => { + it('should only be allowed directly after match(...)', () => { + const f = (input: unknown) => + match(input) + .returnType() // allowed + .with(undefined, () => 'undefined') + .with(P.string, () => 'string') + .otherwise(() => 'unknown'); + + const f2 = (input: unknown) => + match(input) + .with(undefined, () => 'undefined') + // @ts-expect-error: not allowed + .returnType() + .with(P.string, () => 'string') + .otherwise(() => 'unknown'); + + const f3 = (input: unknown) => + match(input) + .with(undefined, () => 'undefined') + .with(P.string, () => 'string') + // @ts-expect-error: not allowed + .returnType() + .otherwise(() => 'unknown'); + }); + + it('should restrict the return type to a specific type', () => { + const f = (input: string | undefined): string => + match(input) + .returnType() + // @ts-expect-error + .with(undefined, () => undefined) + .with(P.string, () => 'string') + // @ts-expect-error + .otherwise(() => true); + }); + + it('type errors should be well placed', () => { + match(null) + .returnType<{ type: 'ok'; value: 'a' | 'b' }>() + .with(null, () => ({ + type: 'ok', + // @ts-expect-error + value: 'oops', + })) + .exhaustive(); + }); +}); diff --git a/tests/select.test.ts b/tests/select.test.ts index 054394d2..2fe066cd 100644 --- a/tests/select.test.ts +++ b/tests/select.test.ts @@ -22,7 +22,7 @@ describe('select', () => { expect( match(['you', 'hello']) .with([P.select('first')], ({ first }, xs) => { - type t = Expect>; + type t = Expect>; type t2 = Expect>; return [first]; }) @@ -213,10 +213,7 @@ describe('select', () => { return 'empty'; }) .with( - P.typed().array([ - { name: P.any }, - { post: P.array({ title: P.select() }) }, - ]), + P.array([{ name: P.any }, { post: P.array({ title: P.select() }) }]), (titles) => { type t1 = Expect>; return titles @@ -436,7 +433,7 @@ describe('select', () => { }); it('Issue #95: P.select() on empty arrays should return an empty array', () => { - const res = match({ a: [], b: ['text'] }) + const res = match<{ a: string[]; b: string[] }>({ a: [], b: ['text'] }) .with( { a: P.array(P.select('a')), b: P.array(P.select('b')) }, ({ a, b }) => { diff --git a/tests/sets.test.ts b/tests/sets.test.ts index 4bc66fb1..d4fce31a 100644 --- a/tests/sets.test.ts +++ b/tests/sets.test.ts @@ -5,32 +5,40 @@ describe('Set', () => { it('should match Set patterns', () => { const containsGabAndYo = (set: Set) => match, [boolean, boolean]>(set) - .with(new Set(['gab', 'yo']), (x) => { - type t = Expect>>; - return [true, true]; - }) - .with(new Set(['gab']), (x) => { - type t = Expect>>; + .with(P.set('gab'), (x) => { + type t = Expect>>; return [true, false]; }) - .with(new Set(['yo']), (x) => { - type t = Expect>>; + .with(P.set('yo'), (x) => { + type t = Expect>>; return [false, true]; }) + .with(P.set(P.union('gab', 'yo')), (x) => { + type t = Expect>>; + return [true, true]; + }) .with(P._, (x) => { type t = Expect>>; return [false, false]; }) .run(); - expect(containsGabAndYo(new Set(['gab', 'yo', 'hello']))).toEqual([ - true, - true, - ]); - expect(containsGabAndYo(new Set(['gab', 'hello']))).toEqual([true, false]); - expect(containsGabAndYo(new Set(['yo', 'hello']))).toEqual([false, true]); + expect(containsGabAndYo(new Set(['gab', 'yo']))).toEqual([true, true]); + expect(containsGabAndYo(new Set(['gab']))).toEqual([true, false]); + expect(containsGabAndYo(new Set(['yo']))).toEqual([false, true]); expect(containsGabAndYo(new Set(['hello']))).toEqual([false, false]); - expect(containsGabAndYo(new Set([]))).toEqual([false, false]); expect(containsGabAndYo(new Set([2]))).toEqual([false, false]); }); + + it("should match any set if P.set isn't given any arguments", () => { + const someSet = new Set([1, 2, 3]); + + const res = match(someSet) + .with(P.set(), () => true) + .exhaustive(); + + type t = Expect>; + + expect(res).toEqual(true); + }); }); diff --git a/tests/strings.test.ts b/tests/strings.test.ts new file mode 100644 index 00000000..c59cc677 --- /dev/null +++ b/tests/strings.test.ts @@ -0,0 +1,159 @@ +import { P, match } from '../src'; +import { Equal, Expect } from '../src/types/helpers'; + +describe('Strings', () => { + it(`P.string.includes('str')`, () => { + const f = (input: string | number) => + match(input) + .with(P.string.includes('!!'), (value) => { + type t = Expect>; + return 'includes !!'; + }) + .otherwise((value) => { + type t = Expect>; + return 'something else'; + }); + + expect(f('hello!!')).toBe('includes !!'); + expect(f('nope')).toBe('something else'); + }); + + describe('startsWith', () => { + it(`P.string.startsWith('str')`, () => { + const f = (input: string | number) => + match(input) + .with(P.string.startsWith('hello '), (value) => { + type t = Expect>; + return 'starts with hello'; + }) + .otherwise((value) => { + type t = Expect>; + return 'something else'; + }); + + expect(f('hello gabriel')).toBe('starts with hello'); + expect(f('gabriel')).toBe('something else'); + }); + + type FileFrom2022 = `2022-${number}-${number}`; + type FileFrom2023 = `2023-${number}-${number}`; + + it('should narrow template literal types', () => { + const get = (x: FileFrom2022 | FileFrom2023): string => + match(x) + .with(P.string.startsWith('2022-'), (x) => { + type t = Expect>; + return 'file from 2022'; + }) + .with(P.string.startsWith('2023-'), (x) => { + type t = Expect>; + return 'file from 2023'; + }) + .exhaustive(); + + expect(get('2022-04-01')).toEqual('file from 2022'); + expect(get('2023-04-01')).toEqual('file from 2023'); + }); + + it('should work as a nested pattern', () => { + type Input = { value: FileFrom2022 | FileFrom2023 }; + + const input: Input = { value: '2023-04-01' }; + + const output = match(input) + .with({ value: P.string.startsWith('2022-') }, (a) => { + type t = Expect>; + return 'nested file from 2022'; + }) + .with({ value: P.string.startsWith('2023-') }, (b) => { + type t = Expect>; + return 'nested file from 2023'; + }) + .exhaustive(); + + expect(output).toEqual('nested file from 2023'); + }); + }); + + it(`P.string.endsWith('str')`, () => { + const f = (input: string | number) => + match(input) + .with(P.string.endsWith('!!'), (value) => { + type t = Expect>; + return 'ends with !!'; + }) + .otherwise((value) => { + type t = Expect>; + return 'something else'; + }); + + expect(f('hello!!')).toBe('ends with !!'); + expect(f('nope')).toBe('something else'); + }); + + it(`P.string.minLength(..)`, () => { + const f = (input: string | number) => + match(input) + .with(P.string.minLength(2), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f('aa')).toBe('yes'); + expect(f('aaa')).toBe('yes'); + expect(f('a')).toBe('no'); + }); + + it(`P.string.maxLength(..)`, () => { + const f = (input: string | number) => + match(input) + .with(P.string.maxLength(10), (value) => { + type t = Expect>; + return 'yes'; + }) + .otherwise((value) => { + type t = Expect>; + return 'no'; + }); + + expect(f('aaa')).toBe('yes'); + expect(f('aaaaaaaaaa')).toBe('yes'); + expect(f('aaaaaaaaaaa')).toBe('no'); + }); + + it(`P.string.regex('^[a-z]+$')`, () => { + const f = (input: string | number) => + match(input) + .with(P.string.regex('^[a-z]+$'), (value) => { + type t = Expect>; + return 'single word'; + }) + .otherwise((value) => { + type t = Expect>; + return 'something else'; + }); + + expect(f('hello')).toBe('single word'); + expect(f('a b c')).toBe('something else'); + }); + + it(`P.string.regex(/[a-z]+/)`, () => { + const f = (input: string | number) => + match(input) + .with(P.string.regex(/^https?:\/\//), (value) => { + type t = Expect>; + return 'url'; + }) + .otherwise((value) => { + type t = Expect>; + return 'something else'; + }); + + expect(f('https://type-level-typescript.com')).toBe('url'); + expect(f('a b c')).toBe('something else'); + }); +}); diff --git a/tests/tuples.test.ts b/tests/tuples.test.ts index 28266984..aeab8c83 100644 --- a/tests/tuples.test.ts +++ b/tests/tuples.test.ts @@ -79,15 +79,15 @@ describe('tuple ([a, b])', () => { expect( match<[string, number], string>(tuple) .with(['hello', 20], (x) => { - type t = Expect>; + type t = Expect>; return `perfect match`; }) .with(['hello', P._], (x) => { - type t = Expect>; + type t = Expect>; return `string match`; }) .with([P._, 20], (x) => { - type t = Expect>; + type t = Expect>; return `number match`; }) .with([P.string, P.number], (x) => { diff --git a/tests/type-error.test.ts b/tests/type-error.test.ts index d080e04f..9fb84519 100644 --- a/tests/type-error.test.ts +++ b/tests/type-error.test.ts @@ -115,4 +115,48 @@ describe('type errors', () => { // @ts-expect-error .exhaustive(); }); + + it("if a pattern is any, the outer expression shouldn't throw a type error", () => { + const anyVar = null as any; + + match({ a: 'a' }) + .with({ a: anyVar }, (x) => { + type t = Expect>; + return 'Ok'; + }) + .otherwise(() => 'ko'); + }); + + it('type errors should be well placed', () => { + match<{ + a: 1; + b: 'hello' | 'bonjour'; + c: { d: [number, number, boolean] }; + e: unknown; + } | null>(null) + .with( + { + // @ts-expect-error + b: 'oops', + }, + () => 'result' + ) + .with( + { + c: { + d: [ + 1, 2, + // @ts-expect-error: number instead of boolean + 3, + ], + }, + }, + () => 'x' + ) + .with({ e: 1 }, () => 'bas') + .with({ b: 'hello' }, ({ a }) => 'result') + .with({ b: 'bonjour' }, ({ a }) => 'result') + .with(null, () => 'result') + .exhaustive(); + }); }); diff --git a/tests/type-is-matching.test.ts b/tests/type-is-matching.test.ts index 3d32361f..a85835c6 100644 --- a/tests/type-is-matching.test.ts +++ b/tests/type-is-matching.test.ts @@ -22,8 +22,48 @@ describe('IsMatching', () => { ]; }); + describe('Primitives', () => { + it('if there is an overlap in either direction, it should match', () => { + type res1 = IsMatching<3, number>; + type test1 = Expect>; + + type res2 = IsMatching; + type test2 = Expect>; + + type res3 = IsMatching<'hello', string>; + type test3 = Expect>; + + type res4 = IsMatching; + type test4 = Expect>; + }); + + it('if there is NO overlap, it should not match', () => { + type res1 = IsMatching<3, string>; + type test1 = Expect>; + + type res3 = IsMatching<'hello', number>; + type test3 = Expect>; + }); + + it('should support unions of primitives', () => { + type res1 = IsMatching; + type test1 = Expect>; + + type res2 = IsMatching; + type test2 = Expect>; + + type res3 = IsMatching; + type test3 = Expect>; + + // if there is an overlap, it matches + type res4 = IsMatching; + type test4 = Expect>; + }); + }); + it('Object', () => { type cases = [ + Expect, true>>, Expect< Equal< IsMatching<{ type: 'a'; color: 'yellow' | 'green' }, { type: 'a' }>, @@ -170,6 +210,12 @@ describe('IsMatching', () => { type State = {}; type Msg = [type: 'Login'] | [type: 'UrlChange', url: string]; + type res1 = IsMatching<[State, Msg], [unknown, ['Login', unknown]]>; + type test1 = Expect>; + + type res2 = IsMatching<['a'], []>; + type test2 = Expect>; + type cases = [ Expect, true>>, Expect, true>>, @@ -177,7 +223,6 @@ describe('IsMatching', () => { Expect, false>>, Expect, false>>, Expect, true>>, - Expect, false>>, Expect, false>>, Expect, false>>, Expect< @@ -195,9 +240,6 @@ describe('IsMatching', () => { true > >, - Expect< - Equal, false> - >, Expect, true>> ]; }); @@ -212,6 +254,38 @@ describe('IsMatching', () => { ]; }); + it('Variadics', () => { + type res1 = IsMatching<('a' | 'b')[], [unknown, ...unknown[]]>; + type test1 = Expect>; + + type res2 = IsMatching<[number], [unknown, ...unknown[]]>; + type test2 = Expect>; + + type res3 = IsMatching<[number, number], [unknown, ...unknown[]]>; + type test3 = Expect>; + + type res4 = IsMatching<[], [unknown, ...unknown[]]>; + type test4 = Expect>; + + type res5 = IsMatching<[], [...unknown[], unknown]>; + type test5 = Expect>; + + type res6 = IsMatching<[1, 2], [...unknown[], unknown]>; + type test6 = Expect>; + + type res7 = IsMatching<[1, 2], [1, ...unknown[], 2]>; + type test7 = Expect>; + + type res8 = IsMatching<[1, 3, 2], [1, ...unknown[], 2]>; + type test8 = Expect>; + + type res9 = IsMatching<[1, 3, 2], [1, ...string[], 2]>; + type test9 = Expect>; + + type res10 = IsMatching<[1, 3, 2], [1, ...number[], 2]>; + type test10 = Expect>; + }); + it('Sets', () => { type cases = [ Expect, Set<'a'>>, true>>, diff --git a/tests/types-catalog/utils.ts b/tests/types-catalog/utils.ts index d3b43c23..3974dd40 100644 --- a/tests/types-catalog/utils.ts +++ b/tests/types-catalog/utils.ts @@ -50,3 +50,32 @@ export type BigUnion = | 'x' | 'y' | 'z'; + +type AsyncResultStatus = 'idle' | 'loading' | 'error' | 'success'; + +export interface BaseAsyncResult { + status: AsyncResultStatus; + data?: TData; + error?: TError; +} + +export interface AsyncResultIdleOrLoading + extends BaseAsyncResult { + status: 'idle' | 'loading'; +} + +export interface AsyncResultSuccess + extends BaseAsyncResult { + status: 'success'; + data: TData; +} + +export interface AsyncResultError + extends BaseAsyncResult { + status: 'error'; + error: TError; +} +export type AsyncResult = + | AsyncResultIdleOrLoading + | AsyncResultSuccess + | AsyncResultError; diff --git a/tests/types.test.ts b/tests/types.test.ts index d03f1660..06a7fc70 100644 --- a/tests/types.test.ts +++ b/tests/types.test.ts @@ -12,7 +12,7 @@ describe('types', () => { pattern = [{ status: 'success', data: '' }, P._]; pattern = [{ status: 'success', data: P.string }, P._]; pattern = [{ status: 'success', data: P._ }, P._]; - pattern = [{ status: 'error', error: new Error() }, P._]; + pattern = [{ status: 'error', error: P.instanceOf(Error) }, P._]; pattern = [{ status: 'idle' }, P._]; pattern = [P._, { type: 'fetch' }]; pattern = [P._, { type: P._ }]; @@ -124,7 +124,7 @@ describe('types', () => { ); match({ type: 'hello' }).with( - P.typed().when((x) => { + P.when((x) => { type t = Expect>; return true; }), @@ -190,17 +190,14 @@ describe('types', () => { typeof x, { type: string; - hello: - | { - yo: number; - } - | undefined; + hello?: { yo: number } | undefined; } > >; return 'ok'; } ); + match({ type: 'hello' }).with({ type: P.not(P.string) }, (x) => { type t = Expect>; return 'ok'; @@ -338,8 +335,13 @@ describe('type narrowing inheritence', () => { const f = (input: Input) => match(input) .with({ type: 'a' }, () => 'a handled') - // @ts-expect-error duplicates shouldn't be permitted - .with({ type: 'a' }, () => 'duplicated') + .with( + { + // @ts-expect-error duplicates shouldn't be permitted + type: 'a', + }, + () => 'duplicated' + ) .with({ type: 'b' }, () => 'b handled') .exhaustive(); }); @@ -361,7 +363,7 @@ describe('type narrowing inheritence', () => { const size = 10; let canShowInlineLegend = true as boolean; - match(true) + match(true) .with(size >= 100 && width > height * 2.25, () => 'table') .with(size >= 100 && height > width * 1.5, () => 'table') .with(canShowInlineLegend, () => 'inline') diff --git a/tests/unions.test.ts b/tests/unions.test.ts index 42202cea..bb2ffdd9 100644 --- a/tests/unions.test.ts +++ b/tests/unions.test.ts @@ -39,7 +39,18 @@ describe('Unions (a | b)', () => { content: { body: 'yo' }, }) .with({ type: 'post', id: 7 }, (x) => { - type t = Expect>; + type t = Expect< + Equal< + typeof x, + { + content: { + body: string; + }; + type: 'post'; + id: 7; + } + > + >; return 1; }) .with({ type: 'post', content: P._ }, (x) => { @@ -92,7 +103,21 @@ describe('Unions (a | b)', () => { return ``; }) .with({ type: 'ok', data: { type: 'story', likes: 10 } }, (res) => { - type t = Expect>>; + type t = Expect< + Equal< + typeof res, + { + type: 'ok'; + data: { + author: string; + src: string; + views: number; + type: 'story'; + likes: 10; + }; + } + > + >; return `

`; }) .with({ type: 'error' }, (res) => { diff --git a/tests/variadic-tuples.test.ts b/tests/variadic-tuples.test.ts new file mode 100644 index 00000000..0ffacd3d --- /dev/null +++ b/tests/variadic-tuples.test.ts @@ -0,0 +1,625 @@ +import { match, P } from '../src'; +import { Equal, Expect } from '../src/types/helpers'; + +describe('variadic tuples ([a, ...b[]])', () => { + describe('runtime', () => { + describe('match', () => { + it('[any ...any] pattern should match any non-empty array', () => { + const f = (xs: unknown[]) => + match(xs) + .with([P.any, ...P.array()], () => 'non empty') + .otherwise(() => 'empty'); + + expect(f([])).toBe('empty'); + expect(f([1])).toBe('non empty'); + expect(f([1, 2])).toBe('non empty'); + expect(f([1, 2, 3])).toBe('non empty'); + expect(f(['1', '2', '3', '4'])).toBe('non empty'); + }); + + it('[...any, any] pattern should match any non-empty array', () => { + const f = (xs: unknown[]) => + match(xs) + .with([...P.array(), P.any], () => 'non empty') + .otherwise(() => 'empty'); + + expect(f([])).toBe('empty'); + expect(f([1])).toBe('non empty'); + expect(f([1, 2])).toBe('non empty'); + expect(f([1, 2, 3])).toBe('non empty'); + expect(f(['1', '2', '3', '4'])).toBe('non empty'); + }); + + it('[any, ...any, any] patterns should match arrays with at least 2 elements', () => { + const f = (xs: unknown[]) => + match(xs) + .with([P.any, ...P.array(), P.any], () => '>= 2') + .otherwise(() => '< 2'); + + expect(f([1])).toBe('< 2'); + expect(f([1, 2])).toBe('>= 2'); + expect(f([1, 2, 3])).toBe('>= 2'); + expect(f(['1', '2', '3', '4'])).toBe('>= 2'); + }); + + it('[number, ...string[]]', () => { + const f = (xs: unknown[]) => + match(xs) + .with([P.number, ...P.array(P.string)], () => 'match') + .otherwise(() => "doesn't match"); + + expect(f([1])).toBe('match'); + expect(f([1, 2])).toBe("doesn't match"); + expect(f([1, 2, 3])).toBe("doesn't match"); + expect(f([1, '2'])).toBe('match'); + expect(f([1, '2', '3', '4'])).toBe('match'); + }); + + it('[number, ...any, string]', () => { + const f = (xs: unknown[]) => + match(xs) + .with([P.number, ...P.array(), P.string], () => 'match') + .otherwise(() => "doesn't match"); + + expect(f([1])).toBe("doesn't match"); + expect(f([1, 2])).toBe("doesn't match"); + expect(f([1, '2'])).toBe('match'); + expect(f([1, 2, 3, '4'])).toBe('match'); + expect(f([1, '1', '2', '3', '4'])).toBe('match'); + }); + + it('[1, 2, 3, ...number[]]', () => { + const f = (xs: unknown[]) => + match(xs) + .with([1, 2, 3, ...P.array(P.number)], () => 'match') + .otherwise(() => "doesn't match"); + + expect(f([1, 2, 3])).toBe('match'); + expect(f([1, 2, 3, 4, 5, 6])).toBe('match'); + expect(f([1])).toBe("doesn't match"); + expect(f([1, 2])).toBe("doesn't match"); + expect(f([1, 3, 2])).toBe("doesn't match"); + expect(f([1, 2, 3, 4, '5'])).toBe("doesn't match"); + expect(f([1, 2, 3, '4', 5])).toBe("doesn't match"); + expect(f([1, 2, 3, 4, '5', 6])).toBe("doesn't match"); + }); + + it('[...number[], 1, 2, 3]', () => { + const f = (xs: unknown[]) => + match(xs) + .with([...P.array(P.number), 1, 2, 3], () => 'match') + .otherwise(() => "doesn't match"); + + expect(f([1, 2, 3])).toBe('match'); + expect(f([4, 5, 6, 1, 2, 3])).toBe('match'); + expect(f([1])).toBe("doesn't match"); + expect(f([1, 2])).toBe("doesn't match"); + expect(f([1, 3, 2])).toBe("doesn't match"); + expect(f([1, 2, 3, 4, 5])).toBe("doesn't match"); + expect(f(['4', 5, 1, 2, 3])).toBe("doesn't match"); + expect(f([4, '5', 1, 2, 3])).toBe("doesn't match"); + expect(f([4, '5', 6, 1, 2, 3])).toBe("doesn't match"); + }); + + it('[number, number ...boolean[], string, symbol]', () => { + const f = (xs: unknown[]) => + match(xs) + .with( + [P.number, P.number, ...P.array(P.boolean), P.string, P.symbol], + () => 'match' + ) + .otherwise(() => "doesn't match"); + + expect(f([1, 2, true, 'hello', 'yo'])).toBe("doesn't match"); + // ^ ❌ + expect(f([1, 2, true, 3, Symbol('yo')])).toBe("doesn't match"); + // ^ ❌ + expect(f([1, 2, 'true', 'str', Symbol('yo')])).toBe("doesn't match"); + // ^ ❌ + expect(f([1, '2', true, 'str', Symbol('yo')])).toBe("doesn't match"); + // ^ ❌ + expect(f(['1', 2, true, 'str', Symbol('yo')])).toBe("doesn't match"); + // ^ ❌ + expect(f([1, 2, true, 'str', Symbol('yo')])).toBe('match'); + // ^ ✅ + expect(f([1, 2, true, false, true, 'str', Symbol('yo')])).toBe('match'); + // ^ ✅ + + expect(f([1, 2, true, 'false', true, 'str', Symbol('yo')])).toBe( + // ^ ❌ + "doesn't match" + ); + }); + }); + + describe('select', () => { + it('[1, sel, 2, ...number[]]', () => { + const f = (xs: unknown[]) => + match(xs) + .with( + [1, P.select(P.number), 2, ...P.array(P.number)], + (sel) => sel + ) + .otherwise(() => 'no'); + + expect(f([1, 42, 2, 3])).toEqual(42); + }); + + it('[1, 2, ...sel(number)[]]', () => { + const f = (xs: unknown[]) => + match(xs) + .with([1, 2, ...P.array(P.select(P.number))], (sel) => sel) + .otherwise(() => 'no'); + + expect(f([1, 2, 3, 4])).toEqual([3, 4]); + }); + + it('[...sel(number)[], 1, 2]', () => { + const f = (xs: unknown[]) => + match(xs) + .with([...P.array(P.select(P.number)), 1, 2], (sel) => sel) + .otherwise(() => 'no'); + + expect(f([3, 4, 1, 2])).toEqual([3, 4]); + }); + + it('[sel(a), ...sel(b), sel(c)]', () => { + const f = (xs: unknown[]) => + match(xs) + .with( + [ + P.select('a', P.number), + ...P.array(P.select('b', P.number)), + P.select('c', P.string), + ], + (sel) => sel + ) + .otherwise(() => 'no'); + + expect(f([42, 1, 2, 3, '!'])).toEqual({ a: 42, b: [1, 2, 3], c: '!' }); + }); + }); + }); + + describe('types', () => { + it('unknown input', () => { + const xs: unknown[] = [1, 2, 3, 'a', 'b', 'c']; + + match(xs) + .with([P.any, ...P.array()], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => { + return []; + }); + + match(xs) + .with([...P.array(), 7], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => { + return []; + }); + + match(xs) + .with([42, ...P.array(P.number)], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => { + return []; + }); + + match(xs) + .with([42, ...P.array(P.number), '!' as const], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => { + return []; + }); + + match(xs) + .with([1, 2, ...P.array(P.number)], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => { + return []; + }); + + match(xs) + .with([...P.array(P.string), 'a', 'b'], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => { + return []; + }); + }); + + it('known input', () => { + const xs: (string | number)[] = [1, 2, 3, 'a', 'b', 'c']; + + match(xs) + .with([P.any, ...P.array()], (xs) => { + type t = Expect< + Equal + >; + return []; + }) + .otherwise(() => []); + + match(xs) + .with([...P.array(), 7], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with([42, ...P.array(P.number)], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with([42, ...P.array(P.number), 7], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with( + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...P.array(P.number), 7], + (xs) => { + type t = Expect< + Equal + >; + return []; + } + ) + .otherwise(() => []); + + match(xs) + .with([...P.array(P.number), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], (xs) => { + type t = Expect< + Equal + >; + return []; + }) + .otherwise(() => []); + + match(xs) + .with( + [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + ...P.array(P.number), + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + ], + (xs) => { + type t = Expect< + Equal< + typeof xs, + [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + ...number[], + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 + ] + > + >; + return []; + } + ) + .otherwise(() => []); + + match(xs) + .with([1, 2, ...P.array(P.number)], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with([...P.array(P.string), 'a', 'b'], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + }); + + it('select', () => { + const xs: (string | number)[] = [1, 2, 3, 'a', 'b', 'c']; + + match(xs) + .with([P.select(), ...P.array()], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with([...P.array(P.select()), 7], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with([42, ...P.array(P.select(P.number))], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with( + [P.select('head', 42), ...P.array(P.select('tail', P.number))], + (xs) => { + type t = Expect>; + return []; + } + ) + .otherwise(() => []); + + match(xs) + .with([1, 2, ...P.array(P.select(P.number))], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs).with( + [ + P.select('a', 1), + P.select('b', 2), + ...P.array(P.select('c', P.number)), + ], + (xs) => { + type t = Expect>; + return []; + } + ); + match(xs) + .with([1, P.select(2), ...P.array(P.number)], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with([...P.array(P.select(P.string)), 'a'], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs).with( + [...P.array(P.select('inits', P.string)), P.select('last', 'a')], + (xs) => { + type t = Expect>; + return []; + } + ); + match(xs) + .with([...P.array(P.string), P.select()], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with([...P.array(P.select(P.string)), 'a', 'b'], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with([...P.array(P.string), P.select(2), 'b'], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with( + [ + ...P.array(P.select('a', P.string)), + P.select('b', 2), + P.select('c', 'b'), + ], + (xs) => { + type t = Expect>; + return []; + } + ) + .otherwise(() => []); + + match(xs) + .with([42, ...P.array(P.select(P.number)), '!'], (xs) => { + type t = Expect>; + return []; + }) + .otherwise(() => []); + + match(xs) + .with( + [ + P.select('a', 42), + ...P.array(P.number.select('b')), + P.select('c', '!'), + ], + (xs) => { + type t = Expect>; + return []; + } + ) + .otherwise(() => []); + }); + }); + + describe('exhaustiveness checking', () => { + it('1 catch-all wildcards', () => { + const xs: (string | number)[] = [1, 2, 3, 'a', 'b', 'c']; + + const throws = () => + match([]) + .with([P.any, ...P.array()], (xs) => { + return 'branch 1' as const; + }) + // @ts-expect-error: empty list case missing + .exhaustive(); + + expect(() => throws()).toThrow(); + + const res = match(xs) + .with([P.any, ...P.array()], (xs) => { + return 'branch 1' as const; + }) + .with([], (xs) => { + return 'branch 2' as const; + }) + .exhaustive(); + + type t = Expect>; + + expect(res).toBe('branch 1'); + }); + + it('2 catch-all wildcards', () => { + const xs: (string | number)[] = [1, 2, 3, 'a', 'b', 'c']; + + match(xs) + .with([P.any, P.any, ...P.array()], (xs) => { + return 'branch 1' as const; + }) + // @ts-expect-error: empty list case missing + .exhaustive(); + + match(xs) + .with([P.any, P.any, ...P.array()], (xs) => { + return 'branch 1' as const; + }) + .with([P.any, ...P.array()], (xs) => { + return 'branch 2' as const; + }) + // @ts-expect-error: empty list case missing + .exhaustive(); + + const res = match(xs) + .with([P.any, P.any, ...P.array()], (xs) => { + return 'branch 1' as const; + }) + .with([P.any, ...P.array()], (xs) => { + return 'branch 2' as const; + }) + .with([], (xs) => { + return 'branch 3' as const; + }) + .exhaustive(); + + type t = Expect>; + + expect(res).toBe('branch 1'); + }); + }); + + describe('select', () => { + it('selection should work on the variadic part', () => { + const fn = (input: (number | string)[]) => + match(input) + .with([1, 2, ...P.array(P.number).select()], (rest) => { + type t = Expect>; + return ['branch 1', ...rest]; + }) + .with([1, 2, ...P.array(P.number).select(), 'end'], (rest) => { + type t = Expect>; + return ['branch 2', ...rest]; + }) + .with(P.array(P.number.or(P.string)), (rest) => { + type t = Expect>; + return 'otherwise'; + }) + .exhaustive(); + + expect(fn([1, 2, 3])).toEqual(['branch 1', 3]); + expect(fn([1, 2, 3, 4])).toEqual(['branch 1', 3, 4]); + expect(fn([1, 2, 23, 123, 'end'])).toEqual(['branch 2', 23, 123]); + expect(fn(['1', 2, 3, 4])).toEqual('otherwise'); + }); + + it('variadic and array patterns should be threated differently', () => { + const fn = (input: (number | number[] | string)[]) => + match(input) + .with([1, 2, ...P.array(P.number).select()], (rest) => { + type t = Expect>; + return ['variadic 1', ...rest]; + }) + .with([1, 2, ...P.array(P.number).select(), 'end'], (rest) => { + type t = Expect>; + return ['variadic 2', ...rest]; + }) + .with([1, 2, P.array(P.number).select()], (rest) => { + type t = Expect>; + return ['array 1', ...rest]; + }) + .with([1, 2, P.array(P.number).select(), 'end'], (rest) => { + type t = Expect>; + return ['array 2', ...rest]; + }) + .with(P.array(P.number.or(P.string).or(P.array())), (rest) => { + type t = Expect>; + return 'otherwise'; + }) + .exhaustive(); + + expect(fn([1, 2, 3])).toEqual(['variadic 1', 3]); + expect(fn([1, 2, 3, 4])).toEqual(['variadic 1', 3, 4]); + expect(fn([1, 2, 23, 123, 'end'])).toEqual(['variadic 2', 23, 123]); + expect(fn([1, 2, [3, 4]])).toEqual(['array 1', 3, 4]); + expect(fn([1, 2, [23, 123], 'end'])).toEqual(['array 2', 23, 123]); + expect(fn(['1', 2, 3, 4])).toEqual('otherwise'); + }); + }); +}); diff --git a/tests/when.test.ts b/tests/when.test.ts index 0a5d8b15..5609c4e8 100644 --- a/tests/when.test.ts +++ b/tests/when.test.ts @@ -17,7 +17,7 @@ describe('when', () => { expect( match(value) .with( - P.typed().when((x) => x > 10 && x < 50), + P.when((x) => x > 10 && x < 50), () => true ) .otherwise(() => false) @@ -213,7 +213,7 @@ describe('when', () => { list: P.array({ test: 'a', sublist: ['w'], - maybe: P.optional(P.string), + maybe: P.string.optional(), prop: P.when((x) => { type t = Expect>; return true; @@ -257,7 +257,7 @@ describe('when', () => { (x) => { type t = Expect< Equal< - typeof x['value']['coords'], + (typeof x)['value']['coords'], { y: 'top' | 'bottom'; x: 'right'; @@ -365,4 +365,28 @@ describe('when', () => { .exhaustive() ).toBe(true); }); + + it('issue #153: P.when should preserve undefined.', () => { + type Data = { digit: number }; + + type Input = { + data: Data | undefined; + }; + + const input: Input = { data: undefined }; + + const result = match(input) + .with( + { + data: P.when((data) => { + type t = Expect>; + return data ? data.digit > 5 : 0; + }), + }, + () => 'digit is more than 5' + ) + .otherwise(() => 'digit is less than 5'); + + expect(result).toBe('digit is less than 5'); + }); }); diff --git a/tsconfig.json b/tsconfig.json index dfa99d57..22a6cc5a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { - "module": "commonjs", + "module": "ESNext", "declaration": true, - "target": "es6", + "target": "ESNext", + "moduleResolution": "bundler", "strict": true, "outDir": "dist/" },