diff --git a/.eslintrc.json b/.eslintrc.json index 8acaabf23d..56fb4055e8 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -13,6 +13,7 @@ "no-sparse-arrays": 0, "no-unexpected-multiline": 0, "@typescript-eslint/no-empty-function": 0, + "@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-this-alias": 0, "@typescript-eslint/no-unused-vars": ["error", {"ignoreRestSiblings": true}] } diff --git a/package.json b/package.json index dc570bb8de..32acd7946b 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "test": "yarn test:typecheck && yarn test:lint && yarn test:mocha", "test:mocha": "mkdir -p test/output && mocha --conditions=mocha 'test/**/*-test.*' 'test/plot.js'", "test:lint": "eslint src test", - "test:typecheck": "tsc --noEmit", + "test:typecheck": "tsc --noEmit && tsc --noEmit -p test/tsconfig.json", "prepublishOnly": "rm -rf dist && rollup -c && tsc", "postpublish": "git push && git push --tags", "dev": "vite" @@ -63,6 +63,7 @@ "prettier": "^2.7.1", "rollup": "2", "rollup-plugin-terser": "7", + "tsd": "^0.22.0", "tslib": "^2.4.0", "typescript": "^4.6.4", "typescript-module-alias": "^1.0.2", diff --git a/src/data.ts b/src/data.ts new file mode 100644 index 0000000000..7fbd81013f --- /dev/null +++ b/src/data.ts @@ -0,0 +1,95 @@ +/** + * Values are associated to screen encodings (positions, colors…) via scales. + */ +export type Value = number | string | Date | boolean | null | undefined; + +/** + * A data point with values attached to field names; typically, a row from a + * tabular dataset. + */ +export type Row = Record; + +/** + * A single Datum is often a Value, a Row, or an array of values; if a Row, + * possible field names can be inferred from its keys to define accessors; if an + * array, typical accessors are indices, and length, expressed as strings + */ +export type Datum = Row | Value | Value[]; +export type FieldNames = T extends Row + ? // eslint-disable-next-line @typescript-eslint/ban-types + keyof T | (string & {}) + : T extends Value[] + ? // eslint-disable-next-line @typescript-eslint/ban-types + "length" | "0" | "1" | "2" | (string & {}) + : never; + +/** + * The marks data; typically an array of Datum, but can also be defined as an + * iterable compatible with Array.from. + */ +export type Data = ArrayLike | Iterable | TypedArray; + +/** + * An array or typed array constructor, or any class that implements Array.from + */ +export type ArrayType = ArrayConstructor | TypedArrayConstructor; + +/** + * The data is then arrayified, and a range of indices is computed, serving as + * pointers into the columnar representation of each channel + */ +export type DataArray = T[] | TypedArray; + +/** + * A series is an array of indices, used to group data into classes (e.g., + * groups and facets) + */ +export type index = number; // integer +export type Series = index[] | Uint32Array; +export type Facets = Series[]; + +export type NumericArray = number[] | TypedArray; +export type ValueArray = NumericArray | Value[]; + +/** + * Typed arrays are preserved through arrayify + */ +export type TypedArray = + | Int8Array + | Uint8Array + | Int16Array + | Uint16Array + | Int32Array + | Uint32Array + | Uint8ClampedArray + | Float32Array + | Float64Array; + +export type TypedArrayConstructor = + | Int8ArrayConstructor + | Uint8ArrayConstructor + | Int16ArrayConstructor + | Uint16ArrayConstructor + | Int32ArrayConstructor + | Uint32ArrayConstructor + | Uint8ClampedArrayConstructor + | Float32ArrayConstructor + | Float64ArrayConstructor; + +export type Constructor = T extends Int8Array + ? Int8ArrayConstructor + : T extends Uint8Array + ? Uint8ArrayConstructor + : T extends Int16Array + ? Int16ArrayConstructor + : T extends Int32Array + ? Int32ArrayConstructor + : T extends Uint32Array + ? Uint32ArrayConstructor + : T extends Uint8ClampedArray + ? Uint8ClampedArrayConstructor + : T extends Float32Array + ? Float32ArrayConstructor + : T extends Float64Array + ? Float64ArrayConstructor + : never; diff --git a/src/options.js b/src/options.js deleted file mode 100644 index 306df57e4f..0000000000 --- a/src/options.js +++ /dev/null @@ -1,414 +0,0 @@ -import {parse as isoParse} from "isoformat"; -import {color, descending, quantile} from "d3"; - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray -const TypedArray = Object.getPrototypeOf(Uint8Array); -const objectToString = Object.prototype.toString; - -// This allows transforms to behave equivalently to channels. -export function valueof(data, value, arrayType) { - const type = typeof value; - return type === "string" - ? map(data, field(value), arrayType) - : type === "function" - ? map(data, value, arrayType) - : type === "number" || value instanceof Date || type === "boolean" - ? map(data, constant(value), arrayType) - : value && typeof value.transform === "function" - ? arrayify(value.transform(data), arrayType) - : arrayify(value, arrayType); // preserve undefined type -} - -export const field = (name) => (d) => d[name]; -export const indexOf = (d, i) => i; -export const identity = {transform: (d) => d}; -export const zero = () => 0; -export const one = () => 1; -export const yes = () => true; -export const string = (x) => (x == null ? x : `${x}`); -export const number = (x) => (x == null ? x : +x); -export const boolean = (x) => (x == null ? x : !!x); -export const first = (x) => (x ? x[0] : undefined); -export const second = (x) => (x ? x[1] : undefined); -export const constant = (x) => () => x; - -// Converts a string like “p25” into a function that takes an index I and an -// accessor function f, returning the corresponding percentile value. -export function percentile(reduce) { - const p = +`${reduce}`.slice(1) / 100; - return (I, f) => quantile(I, p, f); -} - -// Some channels may allow a string constant to be specified; to differentiate -// string constants (e.g., "red") from named fields (e.g., "date"), this -// function tests whether the given value is a CSS color string and returns a -// tuple [channel, constant] where one of the two is undefined, and the other is -// the given value. If you wish to reference a named field that is also a valid -// CSS color, use an accessor (d => d.red) instead. -export function maybeColorChannel(value, defaultValue) { - if (value === undefined) value = defaultValue; - return value === null ? [undefined, "none"] : isColor(value) ? [undefined, value] : [value, undefined]; -} - -// Similar to maybeColorChannel, this tests whether the given value is a number -// indicating a constant, and otherwise assumes that it’s a channel value. -export function maybeNumberChannel(value, defaultValue) { - if (value === undefined) value = defaultValue; - return value === null || typeof value === "number" ? [undefined, value] : [value, undefined]; -} - -// Validates the specified optional string against the allowed list of keywords. -export function maybeKeyword(input, name, allowed) { - if (input != null) return keyword(input, name, allowed); -} - -// Validates the specified required string against the allowed list of keywords. -export function keyword(input, name, allowed) { - const i = `${input}`.toLowerCase(); - if (!allowed.includes(i)) throw new Error(`invalid ${name}: ${input}`); - return i; -} - -// Promotes the specified data to an array or typed array as needed. If an array -// type is provided (e.g., Array), then the returned array will strictly be of -// the specified type; otherwise, any array or typed array may be returned. If -// the specified data is null or undefined, returns the value as-is. -export function arrayify(data, type) { - return data == null - ? data - : type === undefined - ? data instanceof Array || data instanceof TypedArray - ? data - : Array.from(data) - : data instanceof type - ? data - : type.from(data); -} - -// An optimization of type.from(values, f): if the given values are already an -// instanceof the desired array type, the faster values.map method is used. -export function map(values, f, type = Array) { - return values instanceof type ? values.map(f) : type.from(values, f); -} - -// An optimization of type.from(values): if the given values are already an -// instanceof the desired array type, the faster values.slice method is used. -export function slice(values, type = Array) { - return values instanceof type ? values.slice() : type.from(values); -} - -export function isTypedArray(values) { - return values instanceof TypedArray; -} - -// Disambiguates an options object (e.g., {y: "x2"}) from a primitive value. -export function isObject(option) { - return option?.toString === objectToString; -} - -// Disambiguates a scale options object (e.g., {color: {type: "linear"}}) from -// some other option (e.g., {color: "red"}). When creating standalone legends, -// this is used to test whether a scale is defined; this should be consistent -// with inferScaleType when there are no channels associated with the scale, and -// if this returns true, then normalizeScale must return non-null. -export function isScaleOptions(option) { - return isObject(option) && (option.type !== undefined || option.domain !== undefined); -} - -// Disambiguates an options object (e.g., {y: "x2"}) from a channel value -// definition expressed as a channel transform (e.g., {transform: …}). -export function isOptions(option) { - return isObject(option) && typeof option.transform !== "function"; -} - -// Disambiguates a sort transform (e.g., {sort: "date"}) from a channel domain -// sort definition (e.g., {sort: {y: "x"}}). -export function isDomainSort(sort) { - return isOptions(sort) && sort.value === undefined && sort.channel === undefined; -} - -// For marks specified either as [0, x] or [x1, x2], such as areas and bars. -export function maybeZero(x, x1, x2, x3 = identity) { - if (x1 === undefined && x2 === undefined) { - // {x} or {} - (x1 = 0), (x2 = x === undefined ? x3 : x); - } else if (x1 === undefined) { - // {x, x2} or {x2} - x1 = x === undefined ? 0 : x; - } else if (x2 === undefined) { - // {x, x1} or {x1} - x2 = x === undefined ? 0 : x; - } - return [x1, x2]; -} - -// For marks that have x and y channels (e.g., cell, dot, line, text). -export function maybeTuple(x, y) { - return x === undefined && y === undefined ? [first, second] : [x, y]; -} - -// A helper for extracting the z channel, if it is variable. Used by transforms -// that require series, such as moving average and normalize. -export function maybeZ({z, fill, stroke} = {}) { - if (z === undefined) [z] = maybeColorChannel(fill); - if (z === undefined) [z] = maybeColorChannel(stroke); - return z; -} - -// Returns a Uint32Array with elements [0, 1, 2, … data.length - 1]. -export function range(data) { - const n = data.length; - const r = new Uint32Array(n); - for (let i = 0; i < n; ++i) r[i] = i; - return r; -} - -// Returns a filtered range of data given the test function. -export function where(data, test) { - return range(data).filter((i) => test(data[i], i, data)); -} - -// Returns an array [values[index[0]], values[index[1]], …]. -export function take(values, index) { - return map(index, (i) => values[i]); -} - -// Based on InternMap (d3.group). -export function keyof(value) { - return value !== null && typeof value === "object" ? value.valueOf() : value; -} - -export function maybeInput(key, options) { - if (options[key] !== undefined) return options[key]; - switch (key) { - case "x1": - case "x2": - key = "x"; - break; - case "y1": - case "y2": - key = "y"; - break; - } - return options[key]; -} - -// Defines a column whose values are lazily populated by calling the returned -// setter. If the given source is labeled, the label is propagated to the -// returned column definition. -export function column(source) { - let value; - return [ - { - transform: () => value, - label: labelof(source) - }, - (v) => (value = v) - ]; -} - -// Like column, but allows the source to be null. -export function maybeColumn(source) { - return source == null ? [source] : column(source); -} - -export function labelof(value, defaultValue) { - return typeof value === "string" ? value : value && value.label !== undefined ? value.label : defaultValue; -} - -// Assuming that both x1 and x2 and lazy columns (per above), this derives a new -// a column that’s the average of the two, and which inherits the column label -// (if any). Both input columns are assumed to be quantitative. If either column -// is temporal, the returned column is also temporal. -export function mid(x1, x2) { - return { - transform(data) { - const X1 = x1.transform(data); - const X2 = x2.transform(data); - return isTemporal(X1) || isTemporal(X2) - ? map(X1, (_, i) => new Date((+X1[i] + +X2[i]) / 2)) - : map(X1, (_, i) => (+X1[i] + +X2[i]) / 2, Float64Array); - }, - label: x1.label - }; -} - -// This distinguishes between per-dimension options and a standalone value. -export function maybeValue(value) { - return value === undefined || isOptions(value) ? value : {value}; -} - -// Coerces the given channel values (if any) to numbers. This is useful when -// values will be interpolated into other code, such as an SVG transform, and -// where we don’t wish to allow unexpected behavior for weird input. -export function numberChannel(source) { - return source == null - ? null - : { - transform: (data) => valueof(data, source, Float64Array), - label: labelof(source) - }; -} - -export function isIterable(value) { - return value && typeof value[Symbol.iterator] === "function"; -} - -export function isTextual(values) { - for (const value of values) { - if (value == null) continue; - return typeof value !== "object" || value instanceof Date; - } -} - -export function isOrdinal(values) { - for (const value of values) { - if (value == null) continue; - const type = typeof value; - return type === "string" || type === "boolean"; - } -} - -export function isTemporal(values) { - for (const value of values) { - if (value == null) continue; - return value instanceof Date; - } -} - -// Are these strings that might represent dates? This is stricter than ISO 8601 -// because we want to ignore false positives on numbers; for example, the string -// "1192" is more likely to represent a number than a date even though it is -// valid ISO 8601 representing 1192-01-01. -export function isTemporalString(values) { - for (const value of values) { - if (value == null) continue; - return typeof value === "string" && isNaN(value) && isoParse(value); - } -} - -// Are these strings that might represent numbers? This is stricter than -// coercion because we want to ignore false positives on e.g. empty strings. -export function isNumericString(values) { - for (const value of values) { - if (value == null || value === "") continue; - return typeof value === "string" && !isNaN(value); - } -} - -export function isNumeric(values) { - for (const value of values) { - if (value == null) continue; - return typeof value === "number"; - } -} - -export function isFirst(values, is) { - for (const value of values) { - if (value == null) continue; - return is(value); - } -} - -// Whereas isFirst only tests the first defined value and returns undefined for -// an empty array, this tests all defined values and only returns true if all of -// them are valid colors. It also returns true for an empty array, and thus -// should generally be used in conjunction with isFirst. -export function isEvery(values, is) { - for (const value of values) { - if (value == null) continue; - if (!is(value)) return false; - } - return true; -} - -// Mostly relies on d3-color, with a few extra color keywords. Currently this -// strictly requires that the value be a string; we might want to apply string -// coercion here, though note that d3-color instances would need to support -// valueOf to work correctly with InternMap. -// https://www.w3.org/TR/SVG11/painting.html#SpecifyingPaint -export function isColor(value) { - if (typeof value !== "string") return false; - value = value.toLowerCase().trim(); - return ( - value === "none" || - value === "currentcolor" || - (value.startsWith("url(") && value.endsWith(")")) || // , e.g. pattern or gradient - (value.startsWith("var(") && value.endsWith(")")) || // CSS variable - color(value) !== null - ); -} - -export function isNoneish(value) { - return value == null || isNone(value); -} - -export function isNone(value) { - return /^\s*none\s*$/i.test(value); -} - -export function isRound(value) { - return /^\s*round\s*$/i.test(value); -} - -export function maybeFrameAnchor(value = "middle") { - return keyword(value, "frameAnchor", [ - "middle", - "top-left", - "top", - "top-right", - "right", - "bottom-right", - "bottom", - "bottom-left", - "left" - ]); -} - -// Like a sort comparator, returns a positive value if the given array of values -// is in ascending order, a negative value if the values are in descending -// order. Assumes monotonicity; only tests the first and last values. -export function order(values) { - if (values == null) return; - const first = values[0]; - const last = values[values.length - 1]; - return descending(first, last); -} - -// Unlike {...defaults, ...options}, this ensures that any undefined (but -// present) properties in options inherit the given default value. -export function inherit(options = {}, ...rest) { - let o = options; - for (const defaults of rest) { - for (const key in defaults) { - if (o[key] === undefined) { - const value = defaults[key]; - if (o === options) o = {...o, [key]: value}; - else o[key] = value; - } - } - } - return o; -} - -// Given an iterable of named things (objects with a name property), returns a -// corresponding object with properties associated with the given name. -export function Named(things) { - console.warn("named iterables are deprecated; please use an object instead"); - const names = new Set(); - return Object.fromEntries( - Array.from(things, (thing) => { - const {name} = thing; - if (name == null) throw new Error("missing name"); - const key = `${name}`; - if (key === "__proto__") throw new Error(`illegal name: ${key}`); - if (names.has(key)) throw new Error(`duplicate name: ${key}`); - names.add(key); - return [name, thing]; - }) - ); -} - -export function maybeNamed(things) { - return isIterable(things) ? Named(things) : things; -} diff --git a/src/options.ts b/src/options.ts new file mode 100644 index 0000000000..dcf4a081e9 --- /dev/null +++ b/src/options.ts @@ -0,0 +1,564 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import type { + ArrayType, + Constructor, + Data, + DataArray, + Datum, + FieldNames, + index, + Row, + Series, + TypedArray, + TypedArrayConstructor, + Value, + ValueArray +} from "./data.js"; +import {parse as isoParse} from "isoformat"; +import {color, descending, quantile} from "d3"; + +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray +const TypedArray = Object.getPrototypeOf(Uint8Array); +const objectToString = Object.prototype.toString; + +export function valueof(d: T, v: Accessor, t?: ArrayType): T; +export function valueof( + d: Data, + v: Accessor | number | Date | boolean, + y: Constructor +): U; +export function valueof(d: Data, v: V, t?: ArrayType): V[]; +export function valueof(d: Data, v: U, t?: ArrayConstructor): T[U][]; +export function valueof( + d: Data, + v: AccessorFunction, + t?: ArrayConstructor +): U[]; +export function valueof(d: Data, v: Accessor, t?: ArrayType): ValueArray; +export function valueof( + d: Data, + v: Accessor | number | null | undefined, + t?: ArrayType +): ValueArray | null | undefined; +export function valueof( + data: Data | null | undefined, + value: Accessor | number | Date | boolean | null | undefined, + arrayType: V = Array as V +): ValueArray | null | undefined { + return typeof value === "string" + ? data && map(data as Data, field(value), arrayType) // JS change: avoid crash on valueof(null, "x") + : typeof value === "function" + ? data && map(data, value, arrayType) // JS change: avoid crash on valueof(null, () => {}) + : typeof value === "number" || value instanceof Date || typeof value === "boolean" + ? data && map(data, constant(value), arrayType) // JS change: avoid crash on valueof(null, () => 1) + : value && isTransform(value) // JS change: isTransform is used to assert that value is a TransformMethod + ? arrayify(value.transform(data), arrayType) + : arrayify(value, arrayType); // preserve undefined type +} + +export type Accessor = + | FieldNames + | AccessorFunction + | ValueArray + | TransformMethod; +export type AccessorValue> = V extends keyof T + ? T[V] + : V extends AccessorFunction + ? Val + : never; +type AccessorFunction = (d: T, i: number) => U; + +export type TransformMethod = { + transform: (data: Data | null | undefined) => ValueArray | Iterable | null | undefined; + label?: string; +}; + +function isTransform(value: ColorAccessor): value is TransformMethod { + return isObject(value) && typeof (value as TransformMethod).transform == "function"; +} + +// eslint-disable-next-line @typescript-eslint/ban-types +export type ColorAccessor = Accessor | (string & {}); + +// This function serves as default when no accessor is specified +// It assumes that the Data is already an Iterable of Values. +export const identity = {transform: (data: any): ValueArray => data}; +export const field = (name: string) => (d: any) => d && (d as Row)[name]; // JS change: avoids crash on field(name)(null) +export const indexOf = (d: Datum, i: index) => i; +export const zero = () => 0; +export const one = () => 1; +export const yes = () => true; +export const string = (x: any) => (x == null ? x : `${x}`); +export const number = (x: any) => (x == null ? x : +x); +export const boolean = (x: any) => (x == null ? x : !!x); + +export const first = (x: Value[] | [Value, any] | null | undefined) => (x ? x[0] : undefined); +export const second = (x: Value[] | null | undefined) => (x ? x[1] : undefined); +export const constant = + (x: T) => + () => + x; + +// Converts a string like “p25” into a function that takes an index I and an +// accessor function f, returning the corresponding percentile value. +export function percentile(reduce: pXX): (I: Series, f: (i: index) => any) => number | undefined { + const p = +`${reduce}`.slice(1) / 100; + return (I: Series, f: (i: index) => any) => quantile(I, p, f); +} + +// eslint-disable-next-line @typescript-eslint/ban-types +export type pXX = `p${Digit}${Digit}` & {}; +type Digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"; + +// Some channels may allow a string constant to be specified; to differentiate +// string constants (e.g., "red") from named fields (e.g., "date"), this +// function tests whether the given value is a CSS color string and returns a +// tuple [channel, constant] where one of the two is undefined, and the other is +// the given value. If you wish to reference a named field that is also a valid +// CSS color, use an accessor (d => d.red) instead. +export function maybeColorChannel( + value: ColorAccessor | null | undefined, + defaultValue?: string +): [Accessor | undefined, undefined] | [undefined, string | null | undefined] { + if (value === undefined) value = defaultValue; + return value === null ? [undefined, "none"] : isColor(value) ? [undefined, value] : [value, undefined]; +} + +// Similar to maybeColorChannel, this tests whether the given value is a number +// indicating a constant, and otherwise assumes that it’s a channel value. +export function maybeNumberChannel( + value: Accessor | null | number | undefined, + defaultValue?: number +): [Accessor | null | undefined, undefined] | [undefined, number | null | undefined] { + if (value === undefined) value = defaultValue; + return value === null || typeof value === "number" ? [undefined, value] : [value, undefined]; +} + +// Validates the specified optional string against the allowed list of keywords. +export function maybeKeyword(input: null | undefined, name: string, allowed: string[]): undefined; +export function maybeKeyword(input: string, name: string, allowed: string[]): string | undefined; +export function maybeKeyword(input: string | null | undefined, name: string, allowed: string[]): string | undefined { + if (input != null) return keyword(input, name, allowed); +} + +// Validates the specified required string against the allowed list of keywords. +export function keyword(input: string | null | undefined, name: string, allowed: string[]): string { + const i = `${input}`.toLowerCase(); + if (!allowed.includes(i)) throw new Error(`invalid ${name}: ${input}`); + return i; +} + +// Promotes the specified data to an array or typed array as needed. If an array +// type is provided (e.g., Array), then the returned array will strictly be of +// the specified type; otherwise, any array or typed array may be returned. If +// the specified data is null or undefined, returns the value as-is. +export function arrayify(d: T, t?: ArrayType): T; +export function arrayify(d: T, t?: undefined): T; +export function arrayify(d: T[], t?: undefined): T[]; +export function arrayify(d: Iterable, t?: ArrayConstructor): DataArray; +export function arrayify(d: TypedArray | Iterable, t: Constructor): T; +export function arrayify( + d: Iterable | null | undefined, + t?: ArrayType +): DataArray | null | undefined; +export function arrayify(d: T[], t?: ArrayConstructor): T[]; +export function arrayify(d: T[], t: Constructor): U; +export function arrayify(d: Data, t?: ArrayType): DataArray; +export function arrayify( + data: Data | null | undefined, + type?: ArrayType +): DataArray | null | undefined { + return data == null + ? data + : type === undefined + ? data instanceof Array || data instanceof TypedArray + ? (data as any[]) + : Array.from(data as any[]) + : data instanceof type + ? data + : (type as ArrayConstructor).from(data as any[]); +} + +export type Mapper = (d: T, i: number) => U; +export type TypedMapper = (d: T, i: number) => number; + +export function map(v: Data, f: TypedMapper, t: Constructor): U; +export function map(v: any, f: any, t: Constructor): T; +export function map(v: Data, f: Mapper, t?: ArrayConstructor): U[]; +export function map( + v: Data, + f: Mapper, + t?: ArrayConstructor | TypedArrayConstructor +): U[] | TypedArray; +export function map( + values: Data, + f: Mapper, + type: V = Array as V +): TypedArray | U[] { + // An optimization of type.from(values, f): if the given values are already an + // instanceof the desired array type, the faster values.map method is used. + // Typescript doesn't handle the mixing of different typed array constructors, + // since not every mapping function is compatible, so we cast f to never to + // allow it. + return values instanceof type ? values.map(f as never) : (type as ArrayConstructor).from(values, f); +} + +// An optimization of type.from(values): if the given values are already an +// instanceof the desired array type, the faster values.slice method is used. +export function slice(values: ValueArray, type: ArrayType = Array): any[] | TypedArray { + return values instanceof type ? values.slice() : (type as ArrayConstructor).from(values); +} + +export function isTypedArray(values: ValueArray): values is TypedArray { + return values instanceof TypedArray; +} + +// Disambiguates an options object (e.g., {y: "x2"}) from a primitive value. +export function isObject(o: null | undefined): false; +export function isObject(o: any): boolean; +export function isObject(option: any): boolean { + return option?.toString === objectToString; +} + +// Disambiguates a scale options object (e.g., {color: {type: "linear"}}) from +// some other option (e.g., {color: "red"}). When creating standalone legends, +// this is used to test whether a scale is defined; this should be consistent +// with inferScaleType when there are no channels associated with the scale, and +// if this returns true, then normalizeScale must return non-null. +export function isScaleOptions(option: any): boolean { + return isObject(option) && (option.type !== undefined || option.domain !== undefined); +} + +// Disambiguates an options object (e.g., {y: "x2"}) from a channel value +// definition expressed as a channel transform (e.g., {transform: …}). +export function isOptions(option: any): option is {value?: any; channel?: any; transform: never} { + return isObject(option) && typeof (option as {transform: null}).transform !== "function"; +} + +// Disambiguates a sort transform (e.g., {sort: "date"}) from a channel domain +// sort definition (e.g., {sort: {y: "x"}}). +export function isDomainSort(sort: any): boolean { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return isObject(sort) && sort!.value === undefined && sort!.channel === undefined; +} + +// For marks specified either as [0, x] or [x1, x2], such as areas and bars. +// TODO: move this function to stack.ts? + +export function maybeZero( + x: Accessor | number | undefined, + x1: Accessor | number | undefined, + x2: Accessor | number | undefined, + x3: Accessor = identity +) { + if (x1 === undefined && x2 === undefined) { + // {x} or {} + (x1 = 0), (x2 = x === undefined ? x3 : x); + } else if (x1 === undefined) { + // {x, x2} or {x2} + x1 = x === undefined ? 0 : x; + } else if (x2 === undefined) { + // {x, x1} or {x1} + x2 = x === undefined ? 0 : x; + } + return [x1, x2]; +} + +// For marks that have x and y channels (e.g., cell, dot, line, text). +export function maybeTuple(x: T | undefined, y: T | undefined): [T | undefined, T | undefined] { + return x === undefined && y === undefined + ? [first as unknown as T | undefined, second as unknown as T | undefined] + : [x, y]; +} + +// A helper for extracting the z channel, if it is variable. Used by transforms +// that require series, such as moving average and normalize. +type ZOptions = { + fill?: ColorAccessor | null; + stroke?: ColorAccessor | null; + z?: Accessor | null; +}; +export function maybeZ({z, fill, stroke}: ZOptions = {}) { + if (z === undefined) [z] = maybeColorChannel(fill); + if (z === undefined) [z] = maybeColorChannel(stroke); + return z; +} + +// Returns a Uint32Array with elements [0, 1, 2, … data.length - 1]. +export function range(data: ArrayLike): Uint32Array { + const n = data.length; + const r = new Uint32Array(n); + for (let i = 0; i < n; ++i) r[i] = i; + return r; +} + +// Returns a filtered range of data given the test function. +export function where(data: ArrayLike, test: (d: any, i?: index, data?: ArrayLike) => boolean) { + return range(data).filter((i) => test(data[i], i, data)); +} + +// Returns an array [values[index[0]], values[index[1]], …]. +export function take(values: ValueArray, index: Series): ValueArray { + return map(index, (i: index) => values[i]); +} + +// Based on InternMap (d3.group). +export function keyof(value: Datum) { + return value !== null && typeof value === "object" ? value.valueOf() : value; +} + +// note: maybeInput doesn't type check if the field is an accessor +export function maybeInput(key: string, options: {[key: string]: any}) { + if (options[key] !== undefined) return options[key]; + switch (key) { + case "x1": + case "x2": + key = "x"; + break; + case "y1": + case "y2": + key = "y"; + break; + } + return options[key]; +} + +export function column(source: any): [GetColumn, SetColumn] { + let value: ValueArray; + return [ + { + transform: () => value, + label: labelof(source) + }, + (v) => ((value = v), v) + ]; +} +export type GetColumn = {transform: () => ValueArray; label?: string}; +type SetColumn = (v: T) => T; + +// Like column, but allows the source to be null. +export function maybeColumn(source: any): [GetColumn, SetColumn] | [null?] { + return source == null ? [source] : column(source); +} + +export function labelof(value: string): string; +export function labelof(value: null | undefined): undefined; +export function labelof(value: any & {label: string}): string; +export function labelof(value: any & {label: string}, defaultValue: string): string; +export function labelof(value: null | undefined, defaultValue?: T): T; +export function labelof(value: any, defaultValue?: string): string | undefined { + return typeof value === "string" + ? value + : value && (value as {label: string}).label != null + ? (value as {label: string}).label + : defaultValue; +} + +// Assuming that both x1 and x2 and lazy columns (per above), this derives a new +// a column that’s the average of the two, and which inherits the column label +// (if any). Both input columns are assumed to be quantitative. If either column +// is temporal, the returned column is also temporal. +export function mid(x1: GetColumn, x2: GetColumn): {transform(): ValueArray; label: string | undefined} { + return { + transform() { + const X1 = x1.transform(); + const X2 = x2.transform(); + return isTemporal(X1) || isTemporal(X2) + ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + map(X1, (_, i) => new Date((+X1[i]! + +X2[i]!) / 2)) // Do we need to handle null or undefined in either of these cases? + : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + map(X1, (_, i) => (+X1[i]! + +X2[i]!) / 2, Float64Array); // e.g. X1[i] == null ? X1[i] : X2[i] == null ? X2[i] : ... + }, + label: x1.label + }; +} + +// This distinguishes between per-dimension options and a standalone value. +export function maybeValue(value: any) { + return value === undefined || isOptions(value) ? value : {value}; +} + +// Coerces the given channel values (if any) to numbers. This is useful when +// values will be interpolated into other code, such as an SVG transform, and +// where we don’t wish to allow unexpected behavior for weird input. +export function numberChannel(source: Accessor | null | undefined): TransformMethod | null { + return source == null + ? null + : { + // TODO: figure out why data being Data | null | undefined doesn't + // match any of the valueof overloads. + transform: (data) => valueof(data as Data, source, Float64Array), + label: labelof(source) + }; +} + +export function isIterable(value: any): value is Iterable { + return value && typeof value[Symbol.iterator] === "function"; +} + +export function isTextual(values: Iterable): boolean { + for (const value of values) { + if (value == null) continue; + return typeof value !== "object" || value instanceof Date; + } + return false; +} + +export function isOrdinal(values: Iterable): boolean { + for (const value of values) { + if (value == null) continue; + const type = typeof value; + return type === "string" || type === "boolean"; + } + return false; +} + +export function isTemporal(values: Iterable): boolean { + for (const value of values) { + if (value == null) continue; + return value instanceof Date; + } + return false; +} + +// Are these strings that might represent dates? This is stricter than ISO 8601 +// because we want to ignore false positives on numbers; for example, the string +// "1192" is more likely to represent a number than a date even though it is +// valid ISO 8601 representing 1192-01-01. +export function isTemporalString(values: Iterable): boolean { + for (const value of values) { + if (value == null) continue; + return typeof value === "string" && isNaN(value as unknown as number) && (isoParse(value) as unknown as boolean); + } + return false; +} + +// Are these strings that might represent numbers? This is stricter than +// coercion because we want to ignore false positives on e.g. empty strings. +export function isNumericString(values: Iterable): boolean { + for (const value of values) { + if (value == null || value === "") continue; + return typeof value === "string" && !isNaN(value as unknown as number); + } + return false; +} + +export function isNumeric(values: Iterable): boolean { + for (const value of values) { + if (value == null) continue; + return typeof value === "number"; + } + return false; +} + +export function isFirst(values: IterableIterator, is: (d: Datum) => boolean) { + for (const value of values) { + if (value == null) continue; + return is(value); + } +} + +// Whereas isFirst only tests the first defined value and returns undefined for +// an empty array, this tests all defined values and only returns true if all of +// them are valid colors. It also returns true for an empty array, and thus +// should generally be used in conjunction with isFirst. +export function isEvery(values: IterableIterator, is: (d: Datum) => boolean): boolean { + for (const value of values) { + if (value == null) continue; + if (!is(value)) return false; + } + return true; +} + +// Mostly relies on d3-color, with a few extra color keywords. Currently this +// strictly requires that the value be a string; we might want to apply string +// coercion here, though note that d3-color instances would need to support +// valueOf to work correctly with InternMap. +// https://www.w3.org/TR/SVG11/painting.html#SpecifyingPaint +export function isColor(v: ColorAccessor | undefined): v is string { + if (typeof v !== "string") return false; + const value = v.toLowerCase().trim(); + return ( + value === "none" || + value === "currentcolor" || + (value.startsWith("url(") && value.endsWith(")")) || // , e.g. pattern or gradient + (value.startsWith("var(") && value.endsWith(")")) || // CSS variable + color(value) !== null + ); +} + +export function isNoneish(value: ColorAccessor | null | undefined): boolean { + return value == null || isNone(value); +} + +export function isNone(value: ColorAccessor | null | undefined): boolean { + return /^\s*none\s*$/i.test(value as string); +} + +export function isRound(value: string | undefined): boolean { + return /^\s*round\s*$/i.test(value as string); +} + +export function maybeFrameAnchor(value = "middle"): string { + return keyword(value, "frameAnchor", [ + "middle", + "top-left", + "top", + "top-right", + "right", + "bottom-right", + "bottom", + "bottom-left", + "left" + ]); +} + +// Like a sort comparator, returns a positive value if the given array of values +// is in ascending order, a negative value if the values are in descending +// order. Assumes monotonicity; only tests the first and last values. +export function order( + values: null | undefined | string[] | number[] | Float32Array | Float64Array +): number | undefined { + if (values == null) return; + const first = values[0]; + const last = values[values.length - 1]; + return descending(first, last); +} + +// Unlike {...defaults, ...options}, this ensures that any undefined (but +// present) properties in options inherit the given default value. +export function inherit(options: Record = {}, ...rest: Array>) { + let o = options; + for (const defaults of rest) { + for (const key in defaults) { + if (o[key] === undefined) { + const value = defaults[key]; + if (o === options) o = {...o, [key]: value}; + else o[key] = value; + } + } + } + return o; +} + +// Given an iterable of named things (objects with a name property), returns a +// corresponding object with properties associated with the given name. +export function Named(things: any): {[k: string]: unknown} { + console.warn("named iterables are deprecated; please use an object instead"); + const names = new Set(); + return Object.fromEntries( + Array.from(things, (thing) => { + const {name} = thing as {name: string}; + if (name == null) throw new Error("missing name"); + const key = `${name}`; + if (key === "__proto__") throw new Error(`illegal name: ${key}`); + if (names.has(key)) throw new Error(`duplicate name: ${key}`); + names.add(key); + return [name, thing]; + }) + ); +} + +export function maybeNamed(things: any): any { + return isIterable(things) ? Named(things) : things; +} diff --git a/test/legends/legends-test.ts b/test/legends/legends-test.ts index 298460b859..39a0de0857 100644 --- a/test/legends/legends-test.ts +++ b/test/legends/legends-test.ts @@ -1,5 +1,5 @@ import * as Plot from "@observablehq/plot"; -import * as assert from "assert"; +import assert from "assert"; import it from "../jsdom.js"; it(`Plot.legend({color: {type: "identity"}}) returns undefined`, () => { diff --git a/test/tsconfig.json b/test/tsconfig.json new file mode 100644 index 0000000000..e3203e06c0 --- /dev/null +++ b/test/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "esModuleInterop": true, + "allowSyntheticDefaultImports": true + }, + "include": ["../src/**/*", "**/*-test.ts"] +} diff --git a/test/types/arrayify-test.ts b/test/types/arrayify-test.ts new file mode 100644 index 0000000000..fc63b9c50d --- /dev/null +++ b/test/types/arrayify-test.ts @@ -0,0 +1,32 @@ +import assert from "assert"; +import {arrayify} from "../../src/options.js"; + +it("arrayify null, undefined", () => { + for (const a of [null, undefined]) { + assert.strictEqual(arrayify(a), a); + assert.strictEqual(arrayify(a, Float32Array), a); + assert.strictEqual(arrayify(a, Float64Array), a); + assert.strictEqual(arrayify(a, Array), a); + } +}); + +it("arrayify typed arrays", () => { + const a = new Uint8ClampedArray(10); + assert.strictEqual(arrayify(a), a); + assert.strictEqual("" + arrayify(a, Float64Array), "" + a); + assert.notStrictEqual(arrayify(a, Float64Array), a); + assert.strictEqual(arrayify(a, Float64Array)[Symbol.toStringTag], "Float64Array"); + assert.strictEqual("" + arrayify(a, Array), "" + a); + assert.notStrictEqual(arrayify(a, Array), a); + // TODO: get the below test to work. + // assert.strictEqual(arrayify(a, Array)[Symbol.toStringTag], undefined); +}); + +it("arrayify arrays", () => { + const a = [1, "test", 1.5]; + assert.strictEqual(arrayify(a), a); + assert.strictEqual(arrayify(a, undefined), a); + assert.strictEqual(arrayify(a, Array), a); + assert.deepStrictEqual("" + arrayify(a, Float64Array), "" + [1, NaN, 1.5]); + assert.deepStrictEqual("" + arrayify(a, Uint16Array), "" + [1, 0, 1]); +}); diff --git a/test/types/options-test.ts b/test/types/options-test.ts new file mode 100644 index 0000000000..bf9d9d299b --- /dev/null +++ b/test/types/options-test.ts @@ -0,0 +1,242 @@ +import {expectError, expectType} from "tsd"; +import type {Data, Row, Value, ValueArray} from "../../src/data.js"; +import {Accessor, arrayify, ColorAccessor, map, TransformMethod} from "../../src/options.js"; + +import { + constant, + field, + labelof, + maybeColorChannel, + maybeKeyword, + maybeNumberChannel, + percentile, + valueof +} from "../../src/options.js"; + +// valueof +// _____________________________________________________________________ + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const numberTransform: TransformMethod = { + transform: (data) => (data ? Array.from(data, (d) => (d ? +d + 1 : 0)) : []) +}; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const nullTransform: TransformMethod = { + transform: () => [1, 2, 3] +}; + +expectType(valueof({length: 10}, (_, i) => i)); +expectType(valueof([1, 2, 3], numberTransform)); +expectType(valueof([1, 2, 3], nullTransform)); +expectType(valueof({length: 10}, nullTransform)); +expectType(valueof([{one: "one", two: "two"}], "one")); +expectType(valueof([{one: 1, two: 1}], "one")); +expectType(valueof([{one: 1, two: 1}], "one", Uint8Array)); +expectType(valueof(Float32Array.of(1, 2, 3), (d) => d)); +expectType(valueof({length: 10}, new Date())); +expectType(valueof(undefined, (_, i) => i + 10)); +expectType(valueof(undefined, nullTransform)); +expectType(valueof(null, nullTransform)); +expectType(valueof({length: 10}, 1)); +expectType(valueof({length: 10}, true)); +expectType(valueof({length: 10}, true, Uint8Array)); +valueof([{one: "one", two: "two"}], (d) => { + expectType<{one: string; two: string}>(d); + return d.one; +}); +valueof([true, false], (d) => { + expectType(d); + return d; +}); +expectType(valueof([1, 2, 3], (d) => d * 2, Float32Array)); +expectType(valueof([1, 2, 3], (d) => d * 2, Float64Array)); +expectType(valueof([1, 2, 3], (d) => d * 2, Array)); +expectType(valueof({length: 10}, (_, i) => `My String #${i}`)); + +// no "ts-expect-error: red is not one of the keys", since it's a legal +// accessor, even though it returns an Array +expectType(valueof([{one: "one", two: "two"}], "red")); +// @ts-expect-error: red is not one of the keys +valueof(null, "red"); + +// field +// _____________________________________________________________________ + +expectType(field("key")({key: "value"})); +expectType(field("foo")({key: "value"})); + +// identity +// _____________________________________________________________________ + +// constant +// _____________________________________________________________________ + +expectType<"foo">(constant("foo")()); +expectType<1>(constant(1)()); +expectType(constant(true)()); +expectType(constant(false)()); +expectType(constant(null)()); + +// percentile +// _____________________________________________________________________ + +expectType(percentile("p99")([1, 2, 3, 4, 5], (i) => i)); + +// @ts-expect-error: the accessor function is required by percentile'e return type. +expectError(percentile("p99")([1, 2, 3, 4, 5])); + +// maybeColorChannel +// _____________________________________________________________________ + +expectType<[Accessor | undefined, string | null | undefined]>(maybeColorChannel("red")); +// eslint-disable-next-line @typescript-eslint/no-explicit-any +expectType<[ColorAccessor | undefined, string | null | undefined]>(maybeColorChannel(1)); + +// maybeNumberChannel +// _____________________________________________________________________ + +expectType<[Accessor | null | undefined, undefined] | [undefined, number | null]>(maybeNumberChannel(1)); + +// maybeKeyword +// _____________________________________________________________________ + +expectType(maybeKeyword(null, "foo", ["bar"])); +expectType(maybeKeyword(undefined, "foo", ["bar"])); +expectType(maybeKeyword("bar", "foo", ["bar"])); + +// keyword +// _____________________________________________________________________ + +// arrayify +// _____________________________________________________________________ + +expectType(arrayify(null)); +expectType(arrayify(undefined)); +expectType(arrayify(null, Float32Array)); +expectType(arrayify(undefined, Float64Array)); +expectType(arrayify([1, 2, 3])); +expectType(arrayify([1, 2, 3], undefined)); +expectType(arrayify([1, 2, 3], Float32Array)); +expectType(arrayify(new Float64Array([1, 2, 3]), Float64Array)); +expectType(arrayify(new Float64Array([1, 2, 3]), Float32Array)); + +// map +// _____________________________________________________________________ + +expectType(map({length: 10}, (_, i) => `Item #${i}`)); +expectType(map({length: 10}, (_, i) => `Item #${i}`, Array)); +expectType(map([1, 2, 3], (_, i) => `Item #${i}`)); +expectType(map([1, 2, 3], (d) => d ** 2)); +expectType(map([1, 2, 3], (d) => d ** 2)); +expectType(map([1, 2, 3], (d) => d ** 2, undefined)); +expectType(map([1, 2, 3], (d) => d ** 2, Float32Array)); +expectType(map([1, 2, 3], (d) => d ** 2, Float64Array)); +expectType(map([{one: 2}], (d) => d.one ** 2, Float64Array)); +expectType(map([true, false], (d) => (d ? 1 : 0), Float64Array)); +expectType(map([{one: 2}] as Data, field("one"))); +expectType(map([{one: 2}] as Data, field("one"), Float64Array)); + +// slice +// _____________________________________________________________________ + +// maybeZero +// _____________________________________________________________________ + +// maybeTuple +// _____________________________________________________________________ + +// maybeZ +// _____________________________________________________________________ + +// range +// _____________________________________________________________________ + +// where +// _____________________________________________________________________ + +// take +// _____________________________________________________________________ + +// keyof +// _____________________________________________________________________ + +// maybeInput +// _____________________________________________________________________ + +// column +// _____________________________________________________________________ + +// maybeColumn +// _____________________________________________________________________ + +// labelof +// _____________________________________________________________________ + +expectType(labelof("some label")); +expectType(labelof(undefined, "fallback")); +expectType(labelof(null, "fallback")); +expectType(labelof(undefined)); +expectType(labelof(null)); +expectType(labelof({label: "my label"}, "fallback")); +expectType(labelof({label: "my label"})); + +// mid +// _____________________________________________________________________ + +// maybeValue +// _____________________________________________________________________ + +// numberChannel +// _____________________________________________________________________ + +// isIterable +// _____________________________________________________________________ + +// isTextual +// _____________________________________________________________________ + +// isOrdinal +// _____________________________________________________________________ + +// isTemporalString +// _____________________________________________________________________ + +// isNumericString +// _____________________________________________________________________ + +// isNumeric +// _____________________________________________________________________ + +// isFirst +// _____________________________________________________________________ + +// isEvery +// _____________________________________________________________________ + +// isColor +// _____________________________________________________________________ + +// isNoneish +// _____________________________________________________________________ + +// isNone +// _____________________________________________________________________ + +// isRound +// _____________________________________________________________________ + +// maybeFrameAnchor +// _____________________________________________________________________ + +// order +// _____________________________________________________________________ + +// inherit +// _____________________________________________________________________ + +// Named +// _____________________________________________________________________ + +// maybeNamed +// _____________________________________________________________________ diff --git a/test/types/valueof-test.ts b/test/types/valueof-test.ts new file mode 100644 index 0000000000..853e9a0e7b --- /dev/null +++ b/test/types/valueof-test.ts @@ -0,0 +1,59 @@ +import assert from "assert"; +import {valueof} from "../../src/options.js"; + +it("valueof reads arrays", () => { + assert.deepStrictEqual( + valueof([1, 2, 3], (d) => d), + [1, 2, 3] + ); + assert.deepStrictEqual( + valueof([1, 2, 3], (d) => `${d}`, Array), + ["1", "2", "3"] + ); + assert.deepStrictEqual( + valueof([1, 2, 3], (d) => d, Float64Array), + Float64Array.of(1, 2, 3) + ); +}); + +// We don't expect the Datum to be complicated things, but the user can provide their +// own, if they also provide the proper accessor function; here's a way to type this: +it("valueof can read arrays of complicated things", () => { + assert.deepStrictEqual( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + valueof([(d: number) => d, new Promise(() => {})], (d: any) => `(${d})`), + ["(d=>d)", "([object Promise])"] + ); +}); + +it("data passed to valueof can be nullish and generated by the transform method", () => { + assert.deepStrictEqual(valueof(undefined, {transform: () => [1, "text"]}), [1, "text"]); + assert.deepStrictEqual(valueof(null, {transform: () => [1, "text"]}, Float32Array), Float32Array.of(1, NaN)); + assert.deepStrictEqual(valueof(null, {transform: () => new Float64Array(2)}, Array), [0, 0]); + + // ts type tests + valueof([1, 2, 3], (d: unknown) => d as number, Float32Array); + valueof(["1", 2, 3], (d: unknown) => d as string | number); + valueof(["1", 2, 3], (d: unknown) => d as string | number, Array); + valueof(["1", 2, 3], (d: unknown) => d as string | number, Float64Array); + valueof(["1", 2, 3], (d: unknown) => +(d as number), Float32Array); + valueof(new Set(["1", 2, 3]), (d: unknown) => +(d as number), Float32Array); +}); + +it("valueof does not crash on non iterable values with an accessor", () => { + for (const n of [null, undefined]) + assert.strictEqual( + valueof(n, () => 1), + n + ); +}); + +// A function is not a valid input Data +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-expect-error +valueof(() => {}, "red"); + +// A Promise is not a valid input Data +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-expect-error +valueof(new Promise(() => {}), "red"); diff --git a/yarn.lock b/yarn.lock index d47031e4b5..e5e2a19fe9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== @@ -221,6 +221,11 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== +"@tsd/typescript@~4.7.4": + version "4.7.4" + resolved "https://registry.yarnpkg.com/@tsd/typescript/-/typescript-4.7.4.tgz#f1e4e6c3099a174a0cb7aa51cf53f34f6494e528" + integrity sha512-jbtC+RgKZ9Kk65zuRZbKLTACf+tvFW4Rfq0JEMXrlmV3P3yme+Hm+pnb5fJRyt61SjIitcrC810wj7+1tgsEmg== + "@types/d3-array@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.0.3.tgz#87d990bf504d14ad6b16766979d04e943c046dac" @@ -431,6 +436,14 @@ "@types/d3-transition" "*" "@types/d3-zoom" "*" +"@types/eslint@^7.2.13": + version "7.29.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.29.0.tgz#e56ddc8e542815272720bb0b4ccc2aff9c3e1c78" + integrity sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng== + dependencies: + "@types/estree" "*" + "@types/json-schema" "*" + "@types/estree@*": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" @@ -472,11 +485,16 @@ dependencies: "@types/istanbul-lib-report" "*" -"@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== +"@types/minimist@^1.2.0": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" + integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== + "@types/mocha@^9.1.1": version "9.1.1" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" @@ -492,6 +510,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== +"@types/normalize-package-data@^2.4.0": + version "2.4.1" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301" + integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw== + "@types/resolve@1.17.1": version "1.17.1" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" @@ -661,6 +684,13 @@ ansi-colors@4.1.1: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -716,6 +746,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -783,6 +818,20 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== +camelcase-keys@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" + integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== + dependencies: + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" + +camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + camelcase@^6.0.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" @@ -1208,6 +1257,19 @@ debug@4, debug@4.3.4, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: dependencies: ms "2.1.2" +decamelize-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + integrity sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg== + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + decamelize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" @@ -1303,6 +1365,13 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + esbuild-android-64@0.14.49: version "0.14.49" resolved "https://registry.yarnpkg.com/esbuild-android-64/-/esbuild-android-64-0.14.49.tgz#9e4682c36dcf6e7b71b73d2a3723a96e0fdc5054" @@ -1466,6 +1535,25 @@ eslint-config-prettier@^8.5.0: resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== +eslint-formatter-pretty@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/eslint-formatter-pretty/-/eslint-formatter-pretty-4.1.0.tgz#7a6877c14ffe2672066c853587d89603e97c7708" + integrity sha512-IsUTtGxF1hrH6lMWiSl1WbGaiP01eT6kzywdY1U+zLc0MP+nwEnUiS9UI8IaOTUhTeQJLlCEWIbXINBH4YJbBQ== + dependencies: + "@types/eslint" "^7.2.13" + ansi-escapes "^4.2.1" + chalk "^4.1.0" + eslint-rule-docs "^1.1.5" + log-symbols "^4.0.0" + plur "^4.0.0" + string-width "^4.2.0" + supports-hyperlinks "^2.0.0" + +eslint-rule-docs@^1.1.5: + version "1.1.235" + resolved "https://registry.yarnpkg.com/eslint-rule-docs/-/eslint-rule-docs-1.1.235.tgz#be6ef1fc3525f17b3c859ae2997fedadc89bfb9b" + integrity sha512-+TQ+x4JdTnDoFEXXb3fDvfGOwnyNV7duH8fXWTPD1ieaBmB8omj7Gw/pMBBu4uI2uJCCU8APDaQJzWuXnTsH4A== + eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -1659,6 +1747,14 @@ find-up@5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + flat-cache@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" @@ -1794,7 +1890,7 @@ globals@^13.15.0: dependencies: type-fest "^0.20.2" -globby@^11.1.0: +globby@^11.0.1, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -1811,6 +1907,11 @@ graceful-fs@^4.2.9: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +hard-rejection@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -1838,6 +1939,18 @@ he@1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +hosted-git-info@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224" + integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA== + dependencies: + lru-cache "^6.0.0" + htl@0.3: version "0.3.1" resolved "https://registry.yarnpkg.com/htl/-/htl-0.3.1.tgz#13c5a32fa46434f33b84d4553dd37e58a80e8d8a" @@ -1892,6 +2005,11 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1922,6 +2040,16 @@ interval-tree-1d@1: dependencies: binary-search-bounds "^2.0.0" +irregular-plurals@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-3.3.0.tgz#67d0715d4361a60d9fd9ee80af3881c631a31ee2" + integrity sha512-MVBLKUTangM3EfRPFROhmWQQKRDsrgI83J8GS3jXy+OwYqiR2/aoWndYQ5416jLE3uaGgLH7ncme3X9y09gZ3g== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -1936,6 +2064,13 @@ is-builtin-module@^3.1.0: dependencies: builtin-modules "^3.0.0" +is-core-module@^2.5.0: + version "2.10.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.10.0.tgz#9012ede0a91c69587e647514e1d5277019e728ed" + integrity sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg== + dependencies: + has "^1.0.3" + is-core-module@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" @@ -1970,6 +2105,11 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== +is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== + is-plain-obj@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" @@ -2118,6 +2258,11 @@ jsdom@19: ws "^8.2.3" xml-name-validator "^4.0.0" +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -2128,6 +2273,11 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== +kind-of@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + levn@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" @@ -2144,6 +2294,18 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lines-and-columns@^1.1.6: + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -2156,7 +2318,7 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -log-symbols@4.1.0: +log-symbols@4.1.0, log-symbols@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== @@ -2198,6 +2360,34 @@ make-error@^1.3.6: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== +map-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg== + +map-obj@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" + integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== + +meow@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" + integrity sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize "^1.2.0" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^3.0.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.18.0" + yargs-parser "^20.2.3" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -2233,6 +2423,11 @@ mimic-response@^2.0.0: resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== + minimatch@5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" @@ -2254,6 +2449,15 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" +minimist-options@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" + integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + kind-of "^6.0.3" + minipass@^3.0.0: version "3.3.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.4.tgz#ca99f95dd77c43c7a76bf51e6d200025eee0ffae" @@ -2351,6 +2555,26 @@ nopt@^5.0.0: dependencies: abbrev "1" +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-package-data@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e" + integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA== + dependencies: + hosted-git-info "^4.0.1" + is-core-module "^2.5.0" + semver "^7.3.4" + validate-npm-package-license "^3.0.1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -2407,6 +2631,13 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" @@ -2414,6 +2645,13 @@ p-limit@^3.0.2: dependencies: yocto-queue "^0.1.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -2421,6 +2659,11 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -2428,6 +2671,16 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + parse5@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" @@ -2468,6 +2721,13 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatc resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +plur@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/plur/-/plur-4.0.0.tgz#729aedb08f452645fe8c58ef115bf16b0a73ef84" + integrity sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg== + dependencies: + irregular-plurals "^3.2.0" + postcss@^8.4.14: version "8.4.14" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" @@ -2527,6 +2787,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -2539,6 +2804,25 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +read-pkg-up@^7.0.0, read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -2555,6 +2839,14 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + regexpp@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" @@ -2570,7 +2862,7 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve@^1.17.0, resolve@^1.19.0, resolve@^1.22.1: +resolve@^1.10.0, resolve@^1.17.0, resolve@^1.19.0, resolve@^1.22.1: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -2642,7 +2934,7 @@ saxes@^5.0.1: dependencies: xmlchars "^2.2.0" -semver@^5.6.0: +"semver@2 || 3 || 4 || 5", semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -2652,7 +2944,7 @@ semver@^6.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.5, semver@^7.3.7: +semver@^7.3.4, semver@^7.3.5, semver@^7.3.7: version "7.3.7" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== @@ -2742,6 +3034,32 @@ sourcemap-codec@^1.4.8: resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.11" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz#50c0d8c40a14ec1bf449bae69a0ea4685a9d9f95" + integrity sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g== + stack-utils@^2.0.3: version "2.0.5" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5" @@ -2772,6 +3090,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -2798,6 +3123,14 @@ supports-color@^7.0.0, supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-hyperlinks@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" + integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -2863,6 +3196,23 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +trim-newlines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144" + integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw== + +tsd@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/tsd/-/tsd-0.22.0.tgz#2ff75cf3adff5136896abee1f2c5540497bf3b54" + integrity sha512-NH+tfEDQ0Ze8gH7TorB6IxYybD+M68EYawe45YNVrbQcydNBfdQHP9IiD0QbnqmwNXrv+l9GAiULT68mo4q/xA== + dependencies: + "@tsd/typescript" "~4.7.4" + eslint-formatter-pretty "^4.1.0" + globby "^11.0.1" + meow "^9.0.0" + path-exists "^4.0.0" + read-pkg-up "^7.0.0" + tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -2894,11 +3244,31 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-fest@^0.18.0: + version "0.18.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.18.1.tgz#db4bc151a4a2cf4eebf9add5db75508db6cc841f" + integrity sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + typescript-module-alias@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/typescript-module-alias/-/typescript-module-alias-1.0.2.tgz#a4027c887c89c4e90df1b9812344f76ba19c064e" @@ -2940,6 +3310,14 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + vite@3: version "3.0.0" resolved "https://registry.yarnpkg.com/vite/-/vite-3.0.0.tgz#b4675cb9ab83ec0803b9c952ffa6519bcce033a7" @@ -3085,7 +3463,7 @@ yargs-parser@20.2.4: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== -yargs-parser@^20.2.2: +yargs-parser@^20.2.2, yargs-parser@^20.2.3: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==