diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0da1e7f4..37b1ac14 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,17 +26,13 @@ jobs: --health-retries 5 steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v2.3.0 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - - name: Cache dependencies - uses: c-hive/gha-npm-cache@v1 - - - name: Update npm - run: npm install --global npm + cache: 'npm' - name: Install packages run: npm ci diff --git a/README.md b/README.md index 1b192004..370219f3 100644 --- a/README.md +++ b/README.md @@ -222,7 +222,7 @@ const studioSchema = new Schema(Studio, { }) ``` -When you create a `Schema`, it modifies the entity you handed it, adding getters and setters for the properties you define. The type those getters and setters accept and return are defined with the type parameter above. Valid values are: `string`, `number`, `boolean`, `string[]`, `date`, `point`, or `text`. +When you create a `Schema`, it modifies the entity you handed it, adding getters and setters for the properties you define. The type those getters and setters accept and return are defined with the type parameter above. Valid values are: `string`, `number`, `boolean`, `string[]`, `date`, `point`, `text`, or `binary`. The first three do exactly what you think—they define a property that is a [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String), a [Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number), or a [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean). `string[]` does what you'd think as well, specifically defining an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) of Strings. @@ -236,17 +236,20 @@ const point = { longitude: 12.34, latitude: 56.78 } A `text` field is a lot like a `string`. If you're just reading and writing objects, they are identical. But if you want to *search* on them, they are very, very different. I'll cover that in detail when I talk about [using RediSearch](#-using-redisearch) but the tl;dr is that `string` fields can only be matched on their whole value—no partial matches—and are best for keys while `text` fields have full-text search enabled on them and are optimized for human-readable text. -Additional field options can be set depending on the field type. These correspond to the [Field Options](https://redis.io/commands/ft.create/#field-options) available when creating a RediSearch full-text index. Other than the `separator` option, these only affect how content is indexed and searched. +A `binary` field is a binary blob of data using a `Buffer` object. For Hash data structures it will be stored as a binary field in Redis, for JSON data structures it will be serialized to a numeric array. The `binary` field can be indexed as a [Vector Similarity](https://redis.io/docs/stack/search/reference/vectors/) field. -| schema type | RediSearch type | `indexed` | `sortable` | `normalized` | `stemming` | `phonetic` | `weight` | `separator` | `caseSensitive` | -| -------------- | :-------------: | :-------: | :--------: | :----------: | :--------: | :--------: | :------: | :---------: | :-------------: | -| `string` | TAG | yes | HASH Only | HASH Only | - | - | - | yes | yes | -| `number` | NUMERIC | yes | yes | - | - | - | - | - | - | -| `boolean` | TAG | yes | HASH Only | - | - | - | - | - | - | -| `string[]` | TAG | yes | HASH Only | HASH Only | - | - | - | yes | yes | -| `date` | NUMERIC | yes | yes | - | | - | - | - | - | -| `point` | GEO | yes | - | - | | - | - | - | - | -| `text` | TEXT | yes | yes | yes | yes | yes | yes | - | - | +Additional field options can be set depending on the field type. These correspond to the [Field Options](https://redis.io/commands/ft.create/#field-options) avialable when creating a RediSearch full-text index. Other than the `separator` option, these only affect how content is indexed and searched. + +| schema type | RediSearch type | `indexed` | `sortable` | `normalized` | `stemming` | `phonetic` | `weight` | `separator` | `caseSensitive` | `vector` | +| -------------- | :-------------: | :-------: | :--------: | :----------: | :--------: | :--------: | :------: | :---------: | :-------------: | :------: | +| `string` | TAG | yes | HASH Only | HASH Only | - | - | - | yes | yes | - | +| `number` | NUMERIC | yes | yes | - | - | - | - | - | - | - | +| `boolean` | TAG | yes | HASH Only | - | - | - | - | - | - | - | +| `string[]` | TAG | yes | HASH Only | HASH Only | - | - | - | yes | yes | - | +| `date` | NUMERIC | yes | yes | - | - | - | - | - | - | - | +| `point` | GEO | yes | - | - | - | - | - | - | - | - | +| `text` | TEXT | yes | yes | yes | yes | yes | yes | - | - | - | +| `binary` | VECTOR | yes | - | - | - | - | - | - | - | yes | * `indexed`: true | false, whether this field is indexed by RediSearch (default true) * `sortable`: true | false, whether to create an additional index to optmize sorting (default false) @@ -256,6 +259,7 @@ Additional field options can be set depending on the field type. These correspon * `weight`: number, the importance weighting to use when ranking results (default 1) * `separator`: string, the character to delimit multiple tags (default '|') * `caseSensitive`: true | false, whether original letter casing is kept for search (default false) +* `vector`: object containing [Vector Similarity](https://redis.io/docs/stack/search/reference/vectors/) configuration Example showing additional options: @@ -269,6 +273,7 @@ const commentSchema = new Schema(Comment, { approved: { type: 'boolean', indexed: false }, iphash: { type: 'string', caseSensitive: true }, notes: { type: 'string', indexed: false }, + image: { type: 'binary', vector: { algorithm: 'FLAT', dim: 512, distance_metric: 'COSINE' } }, }) ``` diff --git a/lib/client.ts b/lib/client.ts index 2b338d05..f3d89efa 100644 --- a/lib/client.ts +++ b/lib/client.ts @@ -1,4 +1,4 @@ -import { createClient } from 'redis'; +import { createClient, commandOptions } from 'redis'; import { Repository } from './repository'; import { JsonRepository, HashRepository } from './repository'; import { Entity } from './entity/entity'; @@ -11,7 +11,7 @@ export type RedisConnection = ReturnType; * Alias for a JavaScript object used by HSET. * @internal */ -export type RedisHashData = { [key: string]: string }; +export type RedisHashData = { [key: string]: string | Buffer }; /** * Alias for any old JavaScript object used by JSON.SET. @@ -174,7 +174,7 @@ export class Client { if (keysOnly) command.push('RETURN', '0'); - return this.redis.sendCommand(command); + return this.redis.sendCommand(command, commandOptions({ returnBuffers: true })); } /** @internal */ @@ -204,7 +204,7 @@ export class Client { /** @internal */ async hgetall(key: string): Promise { this.validateRedisOpen(); - return this.redis.hGetAll(key); + return this.redis.hGetAll(commandOptions({ returnBuffers: true }), key); } /** @internal */ diff --git a/lib/entity/entity-value.ts b/lib/entity/entity-value.ts index 92dcfa71..3f753a01 100644 --- a/lib/entity/entity-value.ts +++ b/lib/entity/entity-value.ts @@ -3,4 +3,4 @@ import { Point } from "./point"; /** * Valid types for properties on an {@link Entity}. */ -export type EntityValue = string | number | boolean | Point | Date | any[] | null; +export type EntityValue = string | number | boolean | Point | Date | any[] | Buffer | null; diff --git a/lib/entity/entity.ts b/lib/entity/entity.ts index eff16339..299b51f3 100644 --- a/lib/entity/entity.ts +++ b/lib/entity/entity.ts @@ -8,6 +8,7 @@ import { EntityStringArrayField, EntityStringField, EntityTextField, + EntityBinaryField, EntityFieldConstructor, } from "./fields"; import { Schema } from "../schema/schema"; @@ -21,7 +22,8 @@ const ENTITY_FIELD_CONSTRUCTORS: Record 'text': EntityTextField, 'date': EntityDateField, 'point': EntityPointField, - 'string[]': EntityStringArrayField + 'string[]': EntityStringArrayField, + 'binary': EntityBinaryField, } /** diff --git a/lib/entity/fields/entity-binary-field.ts b/lib/entity/fields/entity-binary-field.ts new file mode 100644 index 00000000..55e1a38f --- /dev/null +++ b/lib/entity/fields/entity-binary-field.ts @@ -0,0 +1,45 @@ +import { EntityField } from "./entity-field"; +import { RedisHashData, RedisJsonData } from "../../client"; +import { EntityValue } from "../entity-value"; + +export class EntityBinaryField extends EntityField { + toRedisJson(): RedisJsonData { + const data: RedisJsonData = {}; + if (this.value !== null) { + const bytes = this.valueAsBuffer + const arr = new Float32Array(bytes.buffer, bytes.byteOffset, bytes.length / Float32Array.BYTES_PER_ELEMENT) + data[this.name] = [...arr] + } + return data; + } + + fromRedisJson(value: any) { + if (!this.isBuffer(value)) { + throw Error(`Non-binary value of '${value}' read from Redis for binary field.`) + } + this.value = value + } + + toRedisHash(): RedisHashData { + const data: RedisHashData = {}; + if (this.value !== null) data[this.name] = this.valueAsBuffer + return data; + } + + fromRedisHash(value: string | Buffer) { + if (!this.isBuffer(value)) { + throw Error(`Non-binary value of '${value}' read from Redis for binary field.`) + } + this.value = value as Buffer + } + + protected validateValue(value: EntityValue) { + super.validateValue(value); + if (value !== null && !this.isBuffer(value)) + throw Error(`Expected value with type of 'binary' but received '${value}'.`); + } + + private get valueAsBuffer(): Buffer { + return this.value as Buffer + } +} diff --git a/lib/entity/fields/entity-boolean-field.ts b/lib/entity/fields/entity-boolean-field.ts index 16eaa387..0910f3e2 100644 --- a/lib/entity/fields/entity-boolean-field.ts +++ b/lib/entity/fields/entity-boolean-field.ts @@ -9,10 +9,11 @@ export class EntityBooleanField extends EntityField { return data; }; - fromRedisHash(value: string) { - if (value === '0') { + fromRedisHash(value: string | Buffer) { + const str = value.toString() + if (str === '0') { this.value = false; - } else if (value === '1') { + } else if (str === '1') { this.value = true; } else { throw Error(`Non-boolean value of '${value}' read from Redis for boolean field.`); diff --git a/lib/entity/fields/entity-date-field.ts b/lib/entity/fields/entity-date-field.ts index 931ba906..4459ef30 100644 --- a/lib/entity/fields/entity-date-field.ts +++ b/lib/entity/fields/entity-date-field.ts @@ -20,8 +20,8 @@ export class EntityDateField extends EntityField { return data; } - fromRedisHash(value: string) { - const parsed = Number.parseFloat(value); + fromRedisHash(value: string | Buffer) { + const parsed = Number.parseFloat(value.toString()); if (Number.isNaN(parsed)) throw Error(`Non-numeric value of '${value}' read from Redis for date field.`); const date = new Date(); date.setTime(parsed * 1000); diff --git a/lib/entity/fields/entity-field.ts b/lib/entity/fields/entity-field.ts index a6893326..9c0b0f88 100644 --- a/lib/entity/fields/entity-field.ts +++ b/lib/entity/fields/entity-field.ts @@ -44,8 +44,8 @@ export abstract class EntityField { return data; } - fromRedisHash(value: string) { - this.value = value; + fromRedisHash(value: string | Buffer) { + this.value = value.toString(); } protected validateValue(value: EntityValue) { @@ -67,4 +67,8 @@ export abstract class EntityField { protected isBoolean(value: EntityValue) { return typeof value === 'boolean'; } + + protected isBuffer(value: EntityValue) { + return value instanceof Buffer; + } } diff --git a/lib/entity/fields/entity-number-field.ts b/lib/entity/fields/entity-number-field.ts index 548afe33..2f688e34 100644 --- a/lib/entity/fields/entity-number-field.ts +++ b/lib/entity/fields/entity-number-field.ts @@ -2,8 +2,8 @@ import { EntityField } from "./entity-field"; import { EntityValue } from "../entity-value"; export class EntityNumberField extends EntityField { - fromRedisHash(value: string) { - const number = Number.parseFloat(value); + fromRedisHash(value: string | Buffer) { + const number = Number.parseFloat(value.toString()); if (Number.isNaN(number)) throw Error(`Non-numeric value of '${value}' read from Redis for number field.`); this.value = number; } diff --git a/lib/entity/fields/entity-point-field.ts b/lib/entity/fields/entity-point-field.ts index a4d3f272..96b54cf9 100644 --- a/lib/entity/fields/entity-point-field.ts +++ b/lib/entity/fields/entity-point-field.ts @@ -29,9 +29,10 @@ export class EntityPointField extends EntityField { return data; }; - fromRedisHash(value: string) { - if (value.match(IS_COORD_PAIR)) { - const [longitude, latitude] = value.split(',').map(Number.parseFloat); + fromRedisHash(value: string | Buffer) { + const str = value.toString() + if (str.match(IS_COORD_PAIR)) { + const [longitude, latitude] = str.split(',').map(Number.parseFloat); this.value = { longitude, latitude }; } else { throw Error(`Non-point value of '${value}' read from Redis for point field.`); diff --git a/lib/entity/fields/entity-string-array-field.ts b/lib/entity/fields/entity-string-array-field.ts index eeb6a22a..e2d6f9ee 100644 --- a/lib/entity/fields/entity-string-array-field.ts +++ b/lib/entity/fields/entity-string-array-field.ts @@ -10,8 +10,8 @@ export class EntityStringArrayField extends EntityField { return data; } - fromRedisHash(value: string) { - this.value = value.split(this.separator); + fromRedisHash(value: string | Buffer) { + this.value = value.toString().split(this.separator); } protected validateValue(value: EntityValue) { diff --git a/lib/entity/fields/index.ts b/lib/entity/fields/index.ts index 7d112f05..0a6a6751 100644 --- a/lib/entity/fields/index.ts +++ b/lib/entity/fields/index.ts @@ -1,3 +1,4 @@ +export * from './entity-binary-field' export * from './entity-boolean-field' export * from './entity-date-field' export * from './entity-field-constructor' diff --git a/lib/schema/builders/hash-schema-builder.ts b/lib/schema/builders/hash-schema-builder.ts index 5a2091a0..a6b75edd 100644 --- a/lib/schema/builders/hash-schema-builder.ts +++ b/lib/schema/builders/hash-schema-builder.ts @@ -52,6 +52,11 @@ export class HashSchemaBuilder extends SchemaBuilder extends SchemaBuilder { protected buildWeight(field: WeightFieldDefinition) { return field.weight ? ['WEIGHT', field.weight.toString()] : [] } + + protected buildVector(field: BinaryFieldDefinition) { + // assume that indexed: false takes precedence + if (!(field.indexed ?? this.schema.indexedDefault) || !field.vector) { + return ['NOINDEX'] + } + + const results = [ + 'TYPE', field.vector.vector_type ?? 'FLOAT32', + 'DIM', field.vector.dim.toString(), + 'DISTANCE_METRIC', field.vector.distance_metric, + ] + + if (field.vector.initial_cap) { + results.push('INITIAL_CAP', field.vector.initial_cap.toString()) + } + + switch (field.vector.algorithm) { + case 'FLAT': + if (field.vector.block_size) { + results.push('BLOCK_SIZE', field.vector.block_size.toString()) + } + break + + case 'HNSW': + if (field.vector.m) { + results.push('M', field.vector.m.toString()) + } + if (field.vector.ef_construction) { + results.push('EF_CONSTRUCTION', field.vector.ef_construction.toString()) + } + if (field.vector.ef_runtime) { + results.push('EF_RUNTIME', field.vector.ef_runtime.toString()) + } + break + } + + return [ + 'VECTOR', + field.vector.algorithm, + results.length.toString(), + ...results, + ] + } } diff --git a/lib/schema/definition/binary-field-definition.ts b/lib/schema/definition/binary-field-definition.ts new file mode 100644 index 00000000..35ee6118 --- /dev/null +++ b/lib/schema/definition/binary-field-definition.ts @@ -0,0 +1,52 @@ +import { BaseFieldDefinition } from "./base-field-definition"; + +type Algorithm = 'FLAT' | 'HNSW' + +interface VectorParameters { + // vector algorithm to use + algorithm: Algorithm, + + // vector type, currently only FLOAT32 supported + vector_type?: 'FLOAT32', + + // vector dimension + dim: number, + + // Supported distance metric + distance_metric: 'L2' | 'IP' | 'COSINE', + + // Initial vector capacity in the index affecting memory allocation size of the index + initial_cap?: number, +} + +interface FlatVectorParameters extends VectorParameters { + algorithm: 'FLAT', + + // Block size to hold amount of vectors in a contiguous array + block_size?: number, // default 1,048,576 (1024*1024) +} + +interface HNSWVectorParameters extends VectorParameters { + algorithm: 'HNSW'; + + // Number of maximum allowed outgoing edges for each node in the graph in each layer + m?: number, + + // Number of maximum allowed potential outgoing edges candidates for each node in the + // graph, during the graph building + ef_construction?: number + + // Number of maximum top candidates to hold during the KNN search + ef_runtime?: number, // 10 +} + +type VectorAlgorithm = FlatVectorParameters | HNSWVectorParameters + +/** A field representing binary data. */ +export interface BinaryFieldDefinition extends BaseFieldDefinition { + /** Yep. It's a binary. */ + type: 'binary'; + + // vector parameters + vector?: VectorAlgorithm; +} diff --git a/lib/schema/definition/field-definition.ts b/lib/schema/definition/field-definition.ts index bf380da1..e2c637a0 100644 --- a/lib/schema/definition/field-definition.ts +++ b/lib/schema/definition/field-definition.ts @@ -5,6 +5,7 @@ import { PointFieldDefinition } from "./point-field-definition"; import { StringArrayFieldDefinition } from "./string-array-field-definition"; import { StringFieldDefinition } from "./string-field-definition"; import { TextFieldDefinition } from "./text-field-definition"; +import { BinaryFieldDefinition } from "./binary-field-definition"; /** Contains instructions telling how to map a property on an {@link Entity} to Redis. */ -export type FieldDefinition = StringFieldDefinition | TextFieldDefinition | NumberFieldDefinition | BooleanFieldDefinition | PointFieldDefinition | DateFieldDefinition | StringArrayFieldDefinition; +export type FieldDefinition = StringFieldDefinition | TextFieldDefinition | NumberFieldDefinition | BooleanFieldDefinition | PointFieldDefinition | DateFieldDefinition | StringArrayFieldDefinition | BinaryFieldDefinition; diff --git a/lib/schema/definition/index.ts b/lib/schema/definition/index.ts index df6a56ed..21ef2f3c 100644 --- a/lib/schema/definition/index.ts +++ b/lib/schema/definition/index.ts @@ -1,4 +1,5 @@ export * from './base-field-definition' +export * from './binary-field-definition' export * from './boolean-field-definition' export * from './casesensitive-field-definition' export * from './date-field-definition' diff --git a/lib/schema/definition/schema-field-type.ts b/lib/schema/definition/schema-field-type.ts index c13909a1..6476f909 100644 --- a/lib/schema/definition/schema-field-type.ts +++ b/lib/schema/definition/schema-field-type.ts @@ -1,4 +1,4 @@ /** * Valid types a {@link FieldDefinition}. */ -export type SchemaFieldType = 'string' | 'number' | 'boolean' | 'text' | 'date' | 'point' | 'string[]'; +export type SchemaFieldType = 'string' | 'number' | 'boolean' | 'text' | 'date' | 'point' | 'string[]' | 'binary'; diff --git a/lib/schema/schema.ts b/lib/schema/schema.ts index bcc6716e..3b821cdb 100644 --- a/lib/schema/schema.ts +++ b/lib/schema/schema.ts @@ -163,7 +163,8 @@ export class Schema { } private validateFieldDef(field: string, fieldDef: FieldDefinition) { - if (!['boolean', 'date', 'number', 'point', 'string', 'string[]', 'text'].includes(fieldDef.type)) - throw Error(`The field '${field}' is configured with a type of '${fieldDef.type}'. Valid types include 'boolean', 'date', 'number', 'point', 'string', 'string[]', and 'text'.`); + const fieldTypes = ['boolean', 'date', 'number', 'point', 'string', 'string[]', 'text', 'binary'] + if (!fieldTypes.includes(fieldDef.type)) + throw Error(`The field '${field}' is configured with a type of '${fieldDef.type}'. Valid types include ${fieldTypes.map(type => `'${type}'`).join(', ')}.`); } } diff --git a/lib/search/results-converter.ts b/lib/search/results-converter.ts index 14832d32..c7f4fb38 100644 --- a/lib/search/results-converter.ts +++ b/lib/search/results-converter.ts @@ -18,7 +18,7 @@ export abstract class SearchResultsConverter { } get ids(): Array { - return this.keys.map(key => (key as string).replace(/^.*:/, "")); + return this.keys.map(key => key.toString().replace(/^.*:/, "")); } get keys(): Array { @@ -42,12 +42,12 @@ export abstract class SearchResultsConverter { } export class HashSearchResultsConverter extends SearchResultsConverter { - protected arrayToEntity(id: string, array: Array): TEntity { + protected arrayToEntity(id: string, array: Array): TEntity { const keys = array.filter((_entry, index) => index % 2 === 0); const values = array.filter((_entry, index) => index % 2 !== 0); const hashData: RedisHashData = keys.reduce((object: any, key, index) => { - object[key] = values[index] + object[key.toString()] = values[index] return object }, {}); @@ -58,9 +58,10 @@ export class HashSearchResultsConverter extends SearchRe } export class JsonSearchResultsConverter extends SearchResultsConverter { - protected arrayToEntity(id: string, array: Array): TEntity { - const index = array.findIndex(value => value === '$') + 1; - const jsonString = array[index]; + protected arrayToEntity(id: string, array: Array): TEntity { + const items = array.map(item => item.toString()) + const index = items.findIndex(value => value === '$') + 1; + const jsonString = items[index]; const jsonData: RedisJsonData = JSON.parse(jsonString); const entity = new this.schema.entityCtor(this.schema, id); entity.fromRedisJson(jsonData); diff --git a/lib/search/search.ts b/lib/search/search.ts index 233b4fc7..098e2073 100644 --- a/lib/search/search.ts +++ b/lib/search/search.ts @@ -619,7 +619,8 @@ export class Search extends AbstractSearch { if (fieldDef.type === 'string') return new WhereString(this, field); if (fieldDef.type === 'string[]') return new WhereStringArray(this, field); + // TODO: use single definition of valid field types as per lib/schema.ts // @ts-ignore: This is a trap for JavaScript - throw new Error(`The field type of '${fieldDef.type}' is not a valid field type. Valid types include 'boolean', 'date', 'number', 'point', 'string', and 'string[]'.`); + throw new Error(`The field type of '${fieldDef.type}' is not a valid field type. Valid types include 'boolean', 'date', 'number', 'point', 'string', 'string[]', 'text', 'binary'.`); } } diff --git a/package-lock.json b/package-lock.json index 082d9c72..90e4ef0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,18 +9,19 @@ "version": "0.3.6", "license": "MIT", "dependencies": { - "redis": "^4.0.4", + "redis": "^4.5.0", "ulid": "^2.3.0" }, "devDependencies": { "@types/node": "^18.0.0", - "@vitest/ui": "^0.17.1", + "@vitest/coverage-c8": "^0.25.8", + "@vitest/ui": "^0.25.0", "c8": "^7.11.3", "tsup": "^6.1.2", "typedoc": "^0.23.2", "typedoc-plugin-markdown": "^3.13.1", "typescript": "^4.7.2", - "vitest": "^0.20.0" + "vitest": "^0.25.0" }, "engines": { "node": ">= 14" @@ -32,6 +33,379 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@esbuild/android-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", + "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.5.tgz", + "integrity": "sha512-BCWkmAqFoW6xXzz6Up16bU0vdZqe23UxkrabbrmXXUuH27Tts3LVcHFCi/dGLYa6ZqC/txhtJm2kAJdoyOfHxg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.5.tgz", + "integrity": "sha512-E0R7d0dy9+QlpMps8gJXXhtfn+fQFaTXbq8kV2u/HfHyyhxr4nIIuXZCcYxxA9LSKnsFBBbSQIGDUVY9FGgx0w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.5.tgz", + "integrity": "sha512-4HlbUMy50cRaHGVriBjShs46WRPshtnVOqkxEGhEuDuJhgZ3regpWzaQxXOcDXFvVwue8RiqDAAcOi/QlVLE6Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.5.tgz", + "integrity": "sha512-ZDCAxAPwbtKJ5YxRZusQKDFuywH+7YNKbilss0DCRPtXMxrKRZETcuSfcgIWGYBBc+ypdOazousx3yZss2Az0A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.5.tgz", + "integrity": "sha512-w0dJ8om4KiagLCHURgwxXVWzi5xa0W7F5woMxzWO+LDCebrlyZUhCIbSXUKa4qD3XbdG7K4Y8N4mLDRMkZzMuw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.5.tgz", + "integrity": "sha512-qCdC0T7XUxngX8otO4nmPUE/cHZfvF8jk+GMr9qkAGP0nIMACD7t/AWoY2N5rsn5/dOJ1VKM/aMF4wCFBP5AqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.5.tgz", + "integrity": "sha512-6crdpqwFjl+DObBgwaJMtB+VWrZd87Jy05gQTERysc1ujnUJNCJzemUcRDT5hM34dzTYThlXfFW32qQy9QpPGQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.5.tgz", + "integrity": "sha512-h84QZmBhBdEclyxf9Wm/UESY6ITI7/gYLNvj/3emhDd0ILAqwHdWnMDmKqqubrMcpb1O4sWOYRm7EZ+Av8eGiQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.5.tgz", + "integrity": "sha512-P1WNzGqy6ipvbt8iNoYY66+qUANCiM80D8bGJIU8jqSZ613eG0lUWBePi4xQazcNgIi9tSiCa9Ba3f4krXtQDw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.5.tgz", + "integrity": "sha512-r8wKqs+rl4gIT/xDB6CHMaYcvvyZ7tWf5LulH9NsDvgQEy3gIXQPR4Oy9tYrjM75uKkvBv1uw15Iz4EWsvve9Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.5.tgz", + "integrity": "sha512-0WMhOlwfeeAp6KMx3E6LZKDN6INk4Me8dwIw1XMSFvmE6r31vRnwXkrQlAk5FI44KZ/rIi+yynRZqEd7UJAV2g==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.5.tgz", + "integrity": "sha512-29x+DtRGcYH0Sh3QSnoF+D2SYkHLxwx5AugoGLIlVtcVqDb4fEb654d67k9VcAR2RiTAYUZ764KXzWB+ItQfgw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.5.tgz", + "integrity": "sha512-ZX4SSKOJUcuqFNDydfN4yCo9je9f1T72Pj+RLsAGRiuiREVCwRkXIBp810C01+MdPqYExp322kY78ISEq5XGLQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.5.tgz", + "integrity": "sha512-pYY86RiLD1s5RN8q0aMhWD44NiHmAZxv2bSzaNlL63/ibWETld+m6F+MPh9+ZNOqGJw53E/0qHukYI5Lm+1k7A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.5.tgz", + "integrity": "sha512-vsOwzKN+4NenUTyuoWLmg5dAuO8JKuLD9MXSeENA385XucuOZbblmOMwwgPlHsgVRtSjz38riqPJU2ALI/CWYQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.5.tgz", + "integrity": "sha512-ZhfELxpZLXg7OidX9MrjgQNhjhYx3GXm59EAQVZds8GTyOOPj+Hg7ttKenlXoV8PZVkoCm0dgoWXzhasZJGfWw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.5.tgz", + "integrity": "sha512-2HY2L0afN8IUgvxCAWY04bB6mhHSnC7YNGM2hmEkyAgP+n8jpZgGjiRokuk3AQ0g0IpX8h0KnS+xaznGEr5CGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.5.tgz", + "integrity": "sha512-Q7+HbDnW52LLW8YIU5h0sYZ23TvaaC0vuwiIbJUa91Qr77NKNJCe8stfunN1TRZo+6OwGpM3MrdUcUVUfr5wuA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.5.tgz", + "integrity": "sha512-KcegNS7IgLm/cAcjIW3kZyLiZi/p8I+A2a6OonDA77em9xHewdA2yTA+9pO4gr77MkXATcnDAFBrWw5oLHIZkQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.5.tgz", + "integrity": "sha512-ReUCJSzLNGH6WcvwjMzpEy2SX5GTZBeRTvCdklN4DT2YrgRIe82lYVikVHwA7fdiL3xHKvmdiicMqxE8QYmxrA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.5.tgz", + "integrity": "sha512-q00Jasz6/wCOD2XxRj4GEwj27u1zfpiBniL1ip3/YGGcYtvOoGKCNSS47sufO/8ixEgrSYDlkglSd6CxcS7m0g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=12" + } + }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -42,28 +416,28 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", - "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.13", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", - "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", - "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "dev": true, "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" } }, "node_modules/@nodelib/fs.scandir": { @@ -108,20 +482,20 @@ "dev": true }, "node_modules/@redis/bloom": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.0.2.tgz", - "integrity": "sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.1.0.tgz", + "integrity": "sha512-9QovlxmpRtvxVbN0UBcv8WfdSMudNZZTFqCsnBszcQXqaZb/TVe30ScgGEO7u1EAIacTPAo7/oCYjYAxiHLanQ==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/client": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.1.0.tgz", - "integrity": "sha512-xO9JDIgzsZYDl3EvFhl6LC52DP3q3GCMUer8zHgKV6qSYsq1zB+pZs9+T80VgcRogrlRYhi4ZlfX6A+bHiBAgA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.4.2.tgz", + "integrity": "sha512-oUdEjE0I7JS5AyaAjkD3aOXn9NhO7XKyPyXEyrgFDu++VrVBHUPnV6dgEya9TcMuj5nIJRuCzCm8ZP+c9zCHPw==", "dependencies": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", + "cluster-key-slot": "1.1.1", + "generic-pool": "3.9.0", "yallist": "4.0.0" }, "engines": { @@ -129,41 +503,41 @@ } }, "node_modules/@redis/graph": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.0.1.tgz", - "integrity": "sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", + "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/json": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.3.tgz", - "integrity": "sha512-4X0Qv0BzD9Zlb0edkUoau5c1bInWSICqXAGrpwEltkncUwcxJIGEcVryZhLgb0p/3PkKaLIWkjhHRtLe9yiA7Q==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", + "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/search": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.0.6.tgz", - "integrity": "sha512-pP+ZQRis5P21SD6fjyCeLcQdps+LuTzp2wdUbzxEmNhleighDDTD5ck8+cYof+WLec4csZX7ks+BuoMw0RaZrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.0.tgz", + "integrity": "sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@redis/time-series": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.3.tgz", - "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", + "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", "peerDependencies": { "@redis/client": "^1.0.0" } }, "node_modules/@types/chai": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", - "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, "node_modules/@types/chai-subset": { @@ -182,26 +556,60 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz", - "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==", + "version": "18.11.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.14.tgz", + "integrity": "sha512-0KXV57tENYmmJMl+FekeW9V3O/rlcqGQQJ/hNh9r8pKIj304pskWuEd8fCyNT86g/TpO0gcOTiLzsHLEURFMIQ==", "dev": true }, + "node_modules/@vitest/coverage-c8": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@vitest/coverage-c8/-/coverage-c8-0.25.8.tgz", + "integrity": "sha512-fWgzQoK2KNzTTNnDcLCyibfO9/pbcpPOMtZ9Yvq/Eggpi2X8lewx/OcKZkO5ba5q9dl6+BBn6d5hTcS1709rZw==", + "dev": true, + "dependencies": { + "c8": "^7.12.0", + "vitest": "0.25.8" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@vitest/ui": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-0.17.1.tgz", - "integrity": "sha512-B4PGDk5IZ10HT9GzR0NQ96VEphWY9dTf1yqBGNjPk2c7wQnhZJdHzv3tgFQiyFK5YR1cjtOV918QHCnptV4r5w==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-0.25.8.tgz", + "integrity": "sha512-wfuhghldD5QHLYpS46GK8Ru8P3XcMrWvFjRQD21KNzc9Y/qtJsqoC8KmT6xWVkMNw4oHYixpo3a4ZySRJdserw==", "dev": true, "dependencies": { "sirv": "^2.0.2" } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", "dev": true, - "engines": { + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { "node": ">=8" } }, @@ -227,9 +635,9 @@ "dev": true }, "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", @@ -295,9 +703,9 @@ } }, "node_modules/bundle-require": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-3.0.4.tgz", - "integrity": "sha512-VXG6epB1yrLAvWVQpl92qF347/UXmncQj7J3U8kZEbdVZ1ZkQyr4hYeL/9RvcE8vVVdp53dY78Fd/3pqfRqI1A==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-3.1.2.tgz", + "integrity": "sha512-Of6l6JBAxiyQ5axFxUM6dYeP/W7X2Sozeo/4EYB9sJhL+dqL7TKjg+shwxp6jlu/6ZSERfsYtIpSJ1/x3XkAEA==", "dev": true, "dependencies": { "load-tsconfig": "^0.2.0" @@ -310,9 +718,9 @@ } }, "node_modules/c8": { - "version": "7.11.3", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.11.3.tgz", - "integrity": "sha512-6YBmsaNmqRm9OS3ZbIiL2EZgi1+Xc4O24jL3vMYGE6idixYuGdy76rIfIdltSKDj9DpLNrcXSonUTR1miBD0wA==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz", + "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", @@ -336,23 +744,23 @@ } }, "node_modules/cac": { - "version": "6.7.12", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.12.tgz", - "integrity": "sha512-rM7E2ygtMkJqD9c7WnFU6fruFcN3xe4FM5yUmgxhZzIKJk4uHl9U/fhwdajGFQbQuv43FAUo1Fe8gX/oIKDeSA==", + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, "engines": { "node": ">=8" } }, "node_modules/chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", - "deep-eql": "^3.0.1", + "deep-eql": "^4.1.2", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", @@ -410,9 +818,9 @@ } }, "node_modules/cluster-key-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", - "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz", + "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==", "engines": { "node": ">=0.10.0" } @@ -451,13 +859,10 @@ "dev": true }, "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true }, "node_modules/cross-spawn": { "version": "7.0.3", @@ -491,15 +896,15 @@ } }, "node_modules/deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, "dependencies": { "type-detect": "^4.0.0" }, "engines": { - "node": ">=0.12" + "node": ">=6" } }, "node_modules/dir-glob": { @@ -521,11 +926,12 @@ "dev": true }, "node_modules/esbuild": { - "version": "0.14.47", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.47.tgz", - "integrity": "sha512-wI4ZiIfFxpkuxB8ju4MHrGwGLyp1+awEHAHVpx6w7a+1pmYIq8T9FGEVVwFo0iFierDoMj++Xq69GXWYn2EiwA==", + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.5.tgz", + "integrity": "sha512-te0zG5CDzAxhnBKeddXUtK8xDnYL6jv100ekldhtUk0ALXPXcDAtuH0fAR7rbKwUdz3bOey6HVq2N+aWCKZ1cw==", "dev": true, "hasInstallScript": true, + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -533,40 +939,43 @@ "node": ">=12" }, "optionalDependencies": { - "esbuild-android-64": "0.14.47", - "esbuild-android-arm64": "0.14.47", - "esbuild-darwin-64": "0.14.47", - "esbuild-darwin-arm64": "0.14.47", - "esbuild-freebsd-64": "0.14.47", - "esbuild-freebsd-arm64": "0.14.47", - "esbuild-linux-32": "0.14.47", - "esbuild-linux-64": "0.14.47", - "esbuild-linux-arm": "0.14.47", - "esbuild-linux-arm64": "0.14.47", - "esbuild-linux-mips64le": "0.14.47", - "esbuild-linux-ppc64le": "0.14.47", - "esbuild-linux-riscv64": "0.14.47", - "esbuild-linux-s390x": "0.14.47", - "esbuild-netbsd-64": "0.14.47", - "esbuild-openbsd-64": "0.14.47", - "esbuild-sunos-64": "0.14.47", - "esbuild-windows-32": "0.14.47", - "esbuild-windows-64": "0.14.47", - "esbuild-windows-arm64": "0.14.47" - } - }, - "node_modules/esbuild-darwin-64": { - "version": "0.14.47", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.47.tgz", - "integrity": "sha512-R6oaW0y5/u6Eccti/TS6c/2c1xYTb1izwK3gajJwi4vIfNs1s8B1dQzI1UiC9T61YovOQVuePDcfqHLT3mUZJA==", + "@esbuild/android-arm": "0.16.5", + "@esbuild/android-arm64": "0.16.5", + "@esbuild/android-x64": "0.16.5", + "@esbuild/darwin-arm64": "0.16.5", + "@esbuild/darwin-x64": "0.16.5", + "@esbuild/freebsd-arm64": "0.16.5", + "@esbuild/freebsd-x64": "0.16.5", + "@esbuild/linux-arm": "0.16.5", + "@esbuild/linux-arm64": "0.16.5", + "@esbuild/linux-ia32": "0.16.5", + "@esbuild/linux-loong64": "0.16.5", + "@esbuild/linux-mips64el": "0.16.5", + "@esbuild/linux-ppc64": "0.16.5", + "@esbuild/linux-riscv64": "0.16.5", + "@esbuild/linux-s390x": "0.16.5", + "@esbuild/linux-x64": "0.16.5", + "@esbuild/netbsd-x64": "0.16.5", + "@esbuild/openbsd-x64": "0.16.5", + "@esbuild/sunos-x64": "0.16.5", + "@esbuild/win32-arm64": "0.16.5", + "@esbuild/win32-ia32": "0.16.5", + "@esbuild/win32-x64": "0.16.5" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-arm": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.5.tgz", + "integrity": "sha512-eNkNuLSKpbZTH0BZklJ9B9Sml7fTIamhrQNBwftsEHCUuSLBVunzV3LfghryVGpE5lSkOwOfeX6gR6+3yLaEfQ==", "cpu": [ - "x64" + "arm" ], "dev": true, "optional": true, "os": [ - "darwin" + "android" ], + "peer": true, "engines": { "node": ">=12" } @@ -603,22 +1012,10 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/execa/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -632,9 +1029,9 @@ } }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -708,9 +1105,9 @@ "dev": true }, "node_modules/generic-pool": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", - "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", "engines": { "node": ">= 4" } @@ -733,6 +1130,18 @@ "node": "*" } }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -806,6 +1215,15 @@ "uglify-js": "^3.1.4" } }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -843,9 +1261,9 @@ } }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", + "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", "dev": true, "engines": { "node": ">= 4" @@ -880,9 +1298,9 @@ } }, "node_modules/is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -994,15 +1412,15 @@ } }, "node_modules/jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "dev": true }, "node_modules/lilconfig": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", - "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", + "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", "dev": true, "engines": { "node": ">=10" @@ -1057,9 +1475,9 @@ "dev": true }, "node_modules/loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", "dev": true, "dependencies": { "get-func-name": "^2.0.0" @@ -1087,9 +1505,9 @@ } }, "node_modules/marked": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", - "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.4.tgz", + "integrity": "sha512-Wcc9ikX7Q5E4BYDPvh1C6QNSxrjC9tBgz+A/vAhp59KXUgachw++uMvMKiSW8oA85nopmPZcEvBoex/YLMsiyA==", "dev": true, "bin": { "marked": "bin/marked.js" @@ -1148,10 +1566,13 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/mrmime": { "version": "1.0.1", @@ -1360,9 +1781,9 @@ } }, "node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "version": "8.4.20", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz", + "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==", "dev": true, "funding": [ { @@ -1454,16 +1875,16 @@ } }, "node_modules/redis": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.1.0.tgz", - "integrity": "sha512-5hvJ8wbzpCCiuN1ges6tx2SAh2XXCY0ayresBmu40/SGusWHFW86TAlIPpbimMX2DFHOX7RN34G2XlPA1Z43zg==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.5.1.tgz", + "integrity": "sha512-oxXSoIqMJCQVBTfxP6BNTCtDMyh9G6Vi5wjdPdV/sRKkufyZslDqCScSGcOr6XGR/reAWZefz7E4leM31RgdBA==", "dependencies": { - "@redis/bloom": "1.0.2", - "@redis/client": "1.1.0", - "@redis/graph": "1.0.1", - "@redis/json": "1.0.3", - "@redis/search": "1.0.6", - "@redis/time-series": "1.0.3" + "@redis/bloom": "1.1.0", + "@redis/client": "1.4.2", + "@redis/graph": "1.1.0", + "@redis/json": "1.0.4", + "@redis/search": "1.1.0", + "@redis/time-series": "1.0.4" } }, "node_modules/require-directory": { @@ -1527,15 +1948,16 @@ } }, "node_modules/rollup": { - "version": "2.75.7", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.7.tgz", - "integrity": "sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.7.4.tgz", + "integrity": "sha512-jN9rx3k5pfg9H9al0r0y1EYKSeiRANZRYX32SuNXAnKzh6cVyf4LZVto1KAuDnbHT03E1CpsgqDKaqQ8FZtgxw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.18.0", + "npm": ">=8.0.0" }, "optionalDependencies": { "fsevents": "~2.3.2" @@ -1564,12 +1986,6 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "node_modules/semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -1601,14 +2017,14 @@ } }, "node_modules/shiki": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", - "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", + "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==", "dev": true, "dependencies": { "jsonc-parser": "^3.0.0", "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" + "vscode-textmate": "^6.0.0" } }, "node_modules/signal-exit": { @@ -1641,12 +2057,15 @@ } }, "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", "dev": true, + "dependencies": { + "whatwg-url": "^7.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, "node_modules/source-map-js": { @@ -1693,10 +2112,22 @@ "node": ">=6" } }, + "node_modules/strip-literal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.0.tgz", + "integrity": "sha512-5o4LsH1lzBzO9UFH63AJ2ad2/S2AVx6NtjOcaz+VTT2h1RiRvbipW72z8M/lxEhcPHDBQwpDrnTF7sXy/7OwCQ==", + "dev": true, + "dependencies": { + "acorn": "^8.8.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/sucrase": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.22.0.tgz", - "integrity": "sha512-RZeE0UPxCjf99p4c9Sb27qRbsuZBd7TViR/q1P6TsUPYa/H2LIkaCPpio6F1nQksrynYA78KEBUnpxswZiPYcg==", + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.29.0.tgz", + "integrity": "sha512-bZPAuGA5SdFHuzqIhTAqt9fvNEo9rESqXIG3oiKdF8K4UmkQxC4KlNL3lVyAErXp+mPvUqZ5l13qx6TrDIGf3A==", "dev": true, "dependencies": { "commander": "^4.0.0", @@ -1793,10 +2224,16 @@ "node": ">=0.8" } }, + "node_modules/tinybench": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.1.tgz", + "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", + "dev": true + }, "node_modules/tinypool": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.2.4.tgz", - "integrity": "sha512-Vs3rhkUH6Qq1t5bqtb816oT+HeJTXfwt2cbPH17sWHIYKTotQIFPk3tf2fgqRrVyMDVOc1EnPgzIxfIulXVzwQ==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.3.0.tgz", + "integrity": "sha512-NX5KeqHOBZU6Bc0xj9Vr5Szbb1j8tUHIeD18s41aDJaPeC5QTdEhK0SpdpUrZlj2nv5cctNcSjaKNanXlfcVEQ==", "dev": true, "engines": { "node": ">=14.0.0" @@ -1857,22 +2294,22 @@ "dev": true }, "node_modules/tsup": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.1.2.tgz", - "integrity": "sha512-Hw4hKDHaAQkm2eVavlArEOrAPA93bziRDamdfwaNs0vXQdUUFfItvUWY0L/F6oQQMVh6GvjQq1+HpDXw8UKtPA==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.5.0.tgz", + "integrity": "sha512-36u82r7rYqRHFkD15R20Cd4ercPkbYmuvRkz3Q1LCm5BsiFNUgpo36zbjVhCOgvjyxNBWNKHsaD5Rl8SykfzNA==", "dev": true, "dependencies": { - "bundle-require": "^3.0.2", + "bundle-require": "^3.1.2", "cac": "^6.7.12", "chokidar": "^3.5.1", "debug": "^4.3.1", - "esbuild": "^0.14.25", + "esbuild": "^0.15.1", "execa": "^5.0.0", "globby": "^11.0.3", "joycon": "^3.0.1", "postcss-load-config": "^3.0.1", "resolve-from": "^5.0.0", - "rollup": "^2.74.1", + "rollup": "^3.2.5", "source-map": "0.8.0-beta.0", "sucrase": "^3.20.3", "tree-kill": "^1.2.2" @@ -1901,181 +2338,947 @@ } } }, - "node_modules/tsup/node_modules/source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "node_modules/tsup/node_modules/@esbuild/linux-loong64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" + } + }, + "node_modules/tsup/node_modules/esbuild-android-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-android-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-darwin-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-darwin-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-freebsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-freebsd-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-linux-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-linux-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-linux-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-linux-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-linux-mips64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-linux-ppc64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-linux-riscv64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-linux-s390x": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-netbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-openbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-sunos-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-windows-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-windows-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/tsup/node_modules/esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/typedoc": { + "version": "0.23.22", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.22.tgz", + "integrity": "sha512-5sJkjK60xp8A7YpcYniu3+Wf0QcgojEnhzHuCN+CkdpQkKRhOspon/9+sGTkGI8kjVkZs3KHrhltpQyVhRMVfw==", + "dev": true, + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.0.19", + "minimatch": "^5.1.0", + "shiki": "^0.11.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 14.14" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x" + } + }, + "node_modules/typedoc-plugin-markdown": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.14.0.tgz", + "integrity": "sha512-UyQLkLRkfTFhLdhSf3RRpA3nNInGn+k6sll2vRXjflaMNwQAAiB61SYbisNZTg16t4K1dt1bPQMMGLrxS0GZ0Q==", + "dev": true, + "dependencies": { + "handlebars": "^4.7.7" + }, + "peerDependencies": { + "typedoc": ">=0.23.0" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", + "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typescript": { + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ulid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.3.0.tgz", + "integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==", + "bin": { + "ulid": "bin/cli.js" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", + "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/vite": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz", + "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.15.9", + "postcss": "^8.4.18", + "resolve": "^1.22.1", + "rollup": "^2.79.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" + } + }, + "node_modules/vite/node_modules/esbuild-android-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild-android-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild-darwin-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild-darwin-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild-freebsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild-freebsd-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild-linux-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild-linux-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild-linux-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild-linux-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite/node_modules/esbuild-linux-mips64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "whatwg-url": "^7.0.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 8" + "node": ">=12" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "node_modules/vite/node_modules/esbuild-linux-ppc64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "cpu": [ + "ppc64" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=4" + "node": ">=12" } }, - "node_modules/typedoc": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.2.tgz", - "integrity": "sha512-THpC4vtb3wu1yck6YHzEc4ck6W4lScf8TD0Rg7XAetDih8BzP+ErYO0/6DtdzYcZyKkDwEoujkMeWW7CffCbrQ==", + "node_modules/vite/node_modules/esbuild-linux-riscv64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "lunr": "^2.3.9", - "marked": "^4.0.16", - "minimatch": "^5.1.0", - "shiki": "^0.10.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">= 14.14" - }, - "peerDependencies": { - "typescript": "4.6.x || 4.7.x" + "node": ">=12" } }, - "node_modules/typedoc-plugin-markdown": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.13.1.tgz", - "integrity": "sha512-Gx7pmvFNXAxbE9N2MuQNi5RwMVSH9lPxDBAaBNftaZ+ZzMO8YkDwir6aoXcWNq50qgG/eTs5CiKvLe33OVm2iQ==", + "node_modules/vite/node_modules/esbuild-linux-s390x": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "handlebars": "^4.7.7" - }, - "peerDependencies": { - "typedoc": ">=0.23.0" + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" } }, - "node_modules/typedoc/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/vite/node_modules/esbuild-netbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "balanced-match": "^1.0.0" + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" } }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "node_modules/vite/node_modules/esbuild-openbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "node_modules/vite/node_modules/esbuild-sunos-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "cpu": [ + "x64" + ], "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=4.2.0" + "node": ">=12" } }, - "node_modules/uglify-js": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.16.1.tgz", - "integrity": "sha512-X5BGTIDH8U6IQ1TIRP62YC36k+ULAa1d59BxlWvPUJ1NkW5L3FwcGfEzuVvGmhJFBu0YJ5Ge25tmRISqCmLiRQ==", + "node_modules/vite/node_modules/esbuild-windows-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "cpu": [ + "ia32" + ], "dev": true, "optional": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, + "os": [ + "win32" + ], "engines": { - "node": ">=0.8.0" + "node": ">=12" } }, - "node_modules/ulid": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.3.0.tgz", - "integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==", - "bin": { - "ulid": "bin/cli.js" + "node_modules/vite/node_modules/esbuild-windows-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" } }, - "node_modules/v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "node_modules/vite/node_modules/esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=10.12.0" + "node": ">=12" } }, - "node_modules/vite": { - "version": "2.9.12", - "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.12.tgz", - "integrity": "sha512-suxC36dQo9Rq1qMB2qiRorNJtJAdxguu5TMvBHOc/F370KvqAe9t48vYp+/TbPKRNrMh/J55tOUmkuIqstZaew==", + "node_modules/vite/node_modules/rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "dev": true, - "dependencies": { - "esbuild": "^0.14.27", - "postcss": "^8.4.13", - "resolve": "^1.22.0", - "rollup": "^2.59.0" - }, "bin": { - "vite": "bin/vite.js" + "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=12.2.0" + "node": ">=10.0.0" }, "optionalDependencies": { "fsevents": "~2.3.2" - }, - "peerDependencies": { - "less": "*", - "sass": "*", - "stylus": "*" - }, - "peerDependenciesMeta": { - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - } } }, "node_modules/vitest": { - "version": "0.20.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.20.3.tgz", - "integrity": "sha512-cXMjTbZxBBUUuIF3PUzEGPLJWtIMeURBDXVxckSHpk7xss4JxkiiWh5cnIlfGyfJne2Ii3QpbiRuFL5dMJtljw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.25.8.tgz", + "integrity": "sha512-X75TApG2wZTJn299E/TIYevr4E9/nBo1sUtZzn0Ci5oK8qnpZAZyhwg0qCeMSakGIWtc6oRwcQFyFfW14aOFWg==", "dev": true, "dependencies": { - "@types/chai": "^4.3.1", + "@types/chai": "^4.3.4", "@types/chai-subset": "^1.3.3", "@types/node": "*", - "chai": "^4.3.6", + "acorn": "^8.8.1", + "acorn-walk": "^8.2.0", + "chai": "^4.3.7", "debug": "^4.3.4", "local-pkg": "^0.4.2", - "tinypool": "^0.2.4", - "tinyspy": "^1.0.0", - "vite": "^2.9.12 || ^3.0.0-0" + "source-map": "^0.6.1", + "strip-literal": "^1.0.0", + "tinybench": "^2.3.1", + "tinypool": "^0.3.0", + "tinyspy": "^1.0.2", + "vite": "^3.0.0 || ^4.0.0" }, "bin": { "vitest": "vitest.mjs" @@ -2090,7 +3293,6 @@ "@edge-runtime/vm": "*", "@vitest/browser": "*", "@vitest/ui": "*", - "c8": "*", "happy-dom": "*", "jsdom": "*" }, @@ -2104,9 +3306,6 @@ "@vitest/ui": { "optional": true }, - "c8": { - "optional": true - }, "happy-dom": { "optional": true }, @@ -2115,16 +3314,25 @@ } } }, + "node_modules/vitest/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/vscode-oniguruma": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", - "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", "dev": true }, "node_modules/vscode-textmate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", - "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz", + "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==", "dev": true }, "node_modules/webidl-conversions": { @@ -2229,34 +3437,209 @@ "node": ">=10" } }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "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" + } + } + }, + "dependencies": { + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "@esbuild/android-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", + "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.5.tgz", + "integrity": "sha512-BCWkmAqFoW6xXzz6Up16bU0vdZqe23UxkrabbrmXXUuH27Tts3LVcHFCi/dGLYa6ZqC/txhtJm2kAJdoyOfHxg==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/android-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.5.tgz", + "integrity": "sha512-E0R7d0dy9+QlpMps8gJXXhtfn+fQFaTXbq8kV2u/HfHyyhxr4nIIuXZCcYxxA9LSKnsFBBbSQIGDUVY9FGgx0w==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/darwin-arm64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.5.tgz", + "integrity": "sha512-4HlbUMy50cRaHGVriBjShs46WRPshtnVOqkxEGhEuDuJhgZ3regpWzaQxXOcDXFvVwue8RiqDAAcOi/QlVLE6Q==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/darwin-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.5.tgz", + "integrity": "sha512-ZDCAxAPwbtKJ5YxRZusQKDFuywH+7YNKbilss0DCRPtXMxrKRZETcuSfcgIWGYBBc+ypdOazousx3yZss2Az0A==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.5.tgz", + "integrity": "sha512-w0dJ8om4KiagLCHURgwxXVWzi5xa0W7F5woMxzWO+LDCebrlyZUhCIbSXUKa4qD3XbdG7K4Y8N4mLDRMkZzMuw==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/freebsd-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.5.tgz", + "integrity": "sha512-qCdC0T7XUxngX8otO4nmPUE/cHZfvF8jk+GMr9qkAGP0nIMACD7t/AWoY2N5rsn5/dOJ1VKM/aMF4wCFBP5AqQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/linux-arm": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.5.tgz", + "integrity": "sha512-6crdpqwFjl+DObBgwaJMtB+VWrZd87Jy05gQTERysc1ujnUJNCJzemUcRDT5hM34dzTYThlXfFW32qQy9QpPGQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/linux-arm64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.5.tgz", + "integrity": "sha512-h84QZmBhBdEclyxf9Wm/UESY6ITI7/gYLNvj/3emhDd0ILAqwHdWnMDmKqqubrMcpb1O4sWOYRm7EZ+Av8eGiQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/linux-ia32": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.5.tgz", + "integrity": "sha512-P1WNzGqy6ipvbt8iNoYY66+qUANCiM80D8bGJIU8jqSZ613eG0lUWBePi4xQazcNgIi9tSiCa9Ba3f4krXtQDw==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/linux-loong64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.5.tgz", + "integrity": "sha512-r8wKqs+rl4gIT/xDB6CHMaYcvvyZ7tWf5LulH9NsDvgQEy3gIXQPR4Oy9tYrjM75uKkvBv1uw15Iz4EWsvve9Q==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/linux-mips64el": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.5.tgz", + "integrity": "sha512-0WMhOlwfeeAp6KMx3E6LZKDN6INk4Me8dwIw1XMSFvmE6r31vRnwXkrQlAk5FI44KZ/rIi+yynRZqEd7UJAV2g==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/linux-ppc64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.5.tgz", + "integrity": "sha512-29x+DtRGcYH0Sh3QSnoF+D2SYkHLxwx5AugoGLIlVtcVqDb4fEb654d67k9VcAR2RiTAYUZ764KXzWB+ItQfgw==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/linux-riscv64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.5.tgz", + "integrity": "sha512-ZX4SSKOJUcuqFNDydfN4yCo9je9f1T72Pj+RLsAGRiuiREVCwRkXIBp810C01+MdPqYExp322kY78ISEq5XGLQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/linux-s390x": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.5.tgz", + "integrity": "sha512-pYY86RiLD1s5RN8q0aMhWD44NiHmAZxv2bSzaNlL63/ibWETld+m6F+MPh9+ZNOqGJw53E/0qHukYI5Lm+1k7A==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/linux-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.5.tgz", + "integrity": "sha512-vsOwzKN+4NenUTyuoWLmg5dAuO8JKuLD9MXSeENA385XucuOZbblmOMwwgPlHsgVRtSjz38riqPJU2ALI/CWYQ==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/netbsd-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.5.tgz", + "integrity": "sha512-ZhfELxpZLXg7OidX9MrjgQNhjhYx3GXm59EAQVZds8GTyOOPj+Hg7ttKenlXoV8PZVkoCm0dgoWXzhasZJGfWw==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/openbsd-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.5.tgz", + "integrity": "sha512-2HY2L0afN8IUgvxCAWY04bB6mhHSnC7YNGM2hmEkyAgP+n8jpZgGjiRokuk3AQ0g0IpX8h0KnS+xaznGEr5CGw==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/sunos-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.5.tgz", + "integrity": "sha512-Q7+HbDnW52LLW8YIU5h0sYZ23TvaaC0vuwiIbJUa91Qr77NKNJCe8stfunN1TRZo+6OwGpM3MrdUcUVUfr5wuA==", "dev": true, - "engines": { - "node": ">=10" - } + "optional": true, + "peer": true }, - "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==", + "@esbuild/win32-arm64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.5.tgz", + "integrity": "sha512-KcegNS7IgLm/cAcjIW3kZyLiZi/p8I+A2a6OonDA77em9xHewdA2yTA+9pO4gr77MkXATcnDAFBrWw5oLHIZkQ==", "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true + "optional": true, + "peer": true + }, + "@esbuild/win32-ia32": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.5.tgz", + "integrity": "sha512-ReUCJSzLNGH6WcvwjMzpEy2SX5GTZBeRTvCdklN4DT2YrgRIe82lYVikVHwA7fdiL3xHKvmdiicMqxE8QYmxrA==", + "dev": true, + "optional": true, + "peer": true + }, + "@esbuild/win32-x64": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.5.tgz", + "integrity": "sha512-q00Jasz6/wCOD2XxRj4GEwj27u1zfpiBniL1ip3/YGGcYtvOoGKCNSS47sufO/8ixEgrSYDlkglSd6CxcS7m0g==", + "dev": true, + "optional": true, + "peer": true }, "@istanbuljs/schema": { "version": "0.1.3", @@ -2265,25 +3648,25 @@ "dev": true }, "@jridgewell/resolve-uri": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz", - "integrity": "sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", "dev": true }, "@jridgewell/sourcemap-codec": { - "version": "1.4.13", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz", - "integrity": "sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==", + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz", - "integrity": "sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==", + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", "dev": true, "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" } }, "@nodelib/fs.scandir": { @@ -2319,49 +3702,49 @@ "dev": true }, "@redis/bloom": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.0.2.tgz", - "integrity": "sha512-EBw7Ag1hPgFzdznK2PBblc1kdlj5B5Cw3XwI9/oG7tSn85/HKy3X9xHy/8tm/eNXJYHLXHJL/pkwBpFMVVefkw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.1.0.tgz", + "integrity": "sha512-9QovlxmpRtvxVbN0UBcv8WfdSMudNZZTFqCsnBszcQXqaZb/TVe30ScgGEO7u1EAIacTPAo7/oCYjYAxiHLanQ==", "requires": {} }, "@redis/client": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.1.0.tgz", - "integrity": "sha512-xO9JDIgzsZYDl3EvFhl6LC52DP3q3GCMUer8zHgKV6qSYsq1zB+pZs9+T80VgcRogrlRYhi4ZlfX6A+bHiBAgA==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.4.2.tgz", + "integrity": "sha512-oUdEjE0I7JS5AyaAjkD3aOXn9NhO7XKyPyXEyrgFDu++VrVBHUPnV6dgEya9TcMuj5nIJRuCzCm8ZP+c9zCHPw==", "requires": { - "cluster-key-slot": "1.1.0", - "generic-pool": "3.8.2", + "cluster-key-slot": "1.1.1", + "generic-pool": "3.9.0", "yallist": "4.0.0" } }, "@redis/graph": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.0.1.tgz", - "integrity": "sha512-oDE4myMCJOCVKYMygEMWuriBgqlS5FqdWerikMoJxzmmTUErnTRRgmIDa2VcgytACZMFqpAOWDzops4DOlnkfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", + "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", "requires": {} }, "@redis/json": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.3.tgz", - "integrity": "sha512-4X0Qv0BzD9Zlb0edkUoau5c1bInWSICqXAGrpwEltkncUwcxJIGEcVryZhLgb0p/3PkKaLIWkjhHRtLe9yiA7Q==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", + "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", "requires": {} }, "@redis/search": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.0.6.tgz", - "integrity": "sha512-pP+ZQRis5P21SD6fjyCeLcQdps+LuTzp2wdUbzxEmNhleighDDTD5ck8+cYof+WLec4csZX7ks+BuoMw0RaZrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.0.tgz", + "integrity": "sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==", "requires": {} }, "@redis/time-series": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.3.tgz", - "integrity": "sha512-OFp0q4SGrTH0Mruf6oFsHGea58u8vS/iI5+NpYdicaM+7BgqBZH8FFvNZ8rYYLrUO/QRqMq72NpXmxLVNcdmjA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", + "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", "requires": {} }, "@types/chai": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.3.tgz", - "integrity": "sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", "dev": true }, "@types/chai-subset": { @@ -2380,20 +3763,42 @@ "dev": true }, "@types/node": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.0.tgz", - "integrity": "sha512-cHlGmko4gWLVI27cGJntjs/Sj8th9aYwplmZFwmmgYQQvL5NUsgVJG7OddLvNfLqYS31KFN0s3qlaD9qCaxACA==", + "version": "18.11.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.14.tgz", + "integrity": "sha512-0KXV57tENYmmJMl+FekeW9V3O/rlcqGQQJ/hNh9r8pKIj304pskWuEd8fCyNT86g/TpO0gcOTiLzsHLEURFMIQ==", "dev": true }, + "@vitest/coverage-c8": { + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@vitest/coverage-c8/-/coverage-c8-0.25.8.tgz", + "integrity": "sha512-fWgzQoK2KNzTTNnDcLCyibfO9/pbcpPOMtZ9Yvq/Eggpi2X8lewx/OcKZkO5ba5q9dl6+BBn6d5hTcS1709rZw==", + "dev": true, + "requires": { + "c8": "^7.12.0", + "vitest": "0.25.8" + } + }, "@vitest/ui": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-0.17.1.tgz", - "integrity": "sha512-B4PGDk5IZ10HT9GzR0NQ96VEphWY9dTf1yqBGNjPk2c7wQnhZJdHzv3tgFQiyFK5YR1cjtOV918QHCnptV4r5w==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-0.25.8.tgz", + "integrity": "sha512-wfuhghldD5QHLYpS46GK8Ru8P3XcMrWvFjRQD21KNzc9Y/qtJsqoC8KmT6xWVkMNw4oHYixpo3a4ZySRJdserw==", "dev": true, "requires": { "sirv": "^2.0.2" } }, + "acorn": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", + "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -2416,9 +3821,9 @@ "dev": true }, "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", @@ -2469,18 +3874,18 @@ } }, "bundle-require": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-3.0.4.tgz", - "integrity": "sha512-VXG6epB1yrLAvWVQpl92qF347/UXmncQj7J3U8kZEbdVZ1ZkQyr4hYeL/9RvcE8vVVdp53dY78Fd/3pqfRqI1A==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-3.1.2.tgz", + "integrity": "sha512-Of6l6JBAxiyQ5axFxUM6dYeP/W7X2Sozeo/4EYB9sJhL+dqL7TKjg+shwxp6jlu/6ZSERfsYtIpSJ1/x3XkAEA==", "dev": true, "requires": { "load-tsconfig": "^0.2.0" } }, "c8": { - "version": "7.11.3", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.11.3.tgz", - "integrity": "sha512-6YBmsaNmqRm9OS3ZbIiL2EZgi1+Xc4O24jL3vMYGE6idixYuGdy76rIfIdltSKDj9DpLNrcXSonUTR1miBD0wA==", + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz", + "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", @@ -2498,20 +3903,20 @@ } }, "cac": { - "version": "6.7.12", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.12.tgz", - "integrity": "sha512-rM7E2ygtMkJqD9c7WnFU6fruFcN3xe4FM5yUmgxhZzIKJk4uHl9U/fhwdajGFQbQuv43FAUo1Fe8gX/oIKDeSA==", + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true }, "chai": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz", - "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", "dev": true, "requires": { "assertion-error": "^1.1.0", "check-error": "^1.0.2", - "deep-eql": "^3.0.1", + "deep-eql": "^4.1.2", "get-func-name": "^2.0.0", "loupe": "^2.3.1", "pathval": "^1.1.1", @@ -2552,9 +3957,9 @@ } }, "cluster-key-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz", - "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz", + "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==" }, "color-convert": { "version": "2.0.1", @@ -2584,13 +3989,10 @@ "dev": true }, "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true }, "cross-spawn": { "version": "7.0.3", @@ -2613,9 +4015,9 @@ } }, "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, "requires": { "type-detect": "^4.0.0" @@ -2637,39 +4039,45 @@ "dev": true }, "esbuild": { - "version": "0.14.47", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.47.tgz", - "integrity": "sha512-wI4ZiIfFxpkuxB8ju4MHrGwGLyp1+awEHAHVpx6w7a+1pmYIq8T9FGEVVwFo0iFierDoMj++Xq69GXWYn2EiwA==", - "dev": true, - "requires": { - "esbuild-android-64": "0.14.47", - "esbuild-android-arm64": "0.14.47", - "esbuild-darwin-64": "0.14.47", - "esbuild-darwin-arm64": "0.14.47", - "esbuild-freebsd-64": "0.14.47", - "esbuild-freebsd-arm64": "0.14.47", - "esbuild-linux-32": "0.14.47", - "esbuild-linux-64": "0.14.47", - "esbuild-linux-arm": "0.14.47", - "esbuild-linux-arm64": "0.14.47", - "esbuild-linux-mips64le": "0.14.47", - "esbuild-linux-ppc64le": "0.14.47", - "esbuild-linux-riscv64": "0.14.47", - "esbuild-linux-s390x": "0.14.47", - "esbuild-netbsd-64": "0.14.47", - "esbuild-openbsd-64": "0.14.47", - "esbuild-sunos-64": "0.14.47", - "esbuild-windows-32": "0.14.47", - "esbuild-windows-64": "0.14.47", - "esbuild-windows-arm64": "0.14.47" - } - }, - "esbuild-darwin-64": { - "version": "0.14.47", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.47.tgz", - "integrity": "sha512-R6oaW0y5/u6Eccti/TS6c/2c1xYTb1izwK3gajJwi4vIfNs1s8B1dQzI1UiC9T61YovOQVuePDcfqHLT3mUZJA==", + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.5.tgz", + "integrity": "sha512-te0zG5CDzAxhnBKeddXUtK8xDnYL6jv100ekldhtUk0ALXPXcDAtuH0fAR7rbKwUdz3bOey6HVq2N+aWCKZ1cw==", "dev": true, - "optional": true + "peer": true, + "requires": { + "@esbuild/android-arm": "0.16.5", + "@esbuild/android-arm64": "0.16.5", + "@esbuild/android-x64": "0.16.5", + "@esbuild/darwin-arm64": "0.16.5", + "@esbuild/darwin-x64": "0.16.5", + "@esbuild/freebsd-arm64": "0.16.5", + "@esbuild/freebsd-x64": "0.16.5", + "@esbuild/linux-arm": "0.16.5", + "@esbuild/linux-arm64": "0.16.5", + "@esbuild/linux-ia32": "0.16.5", + "@esbuild/linux-loong64": "0.16.5", + "@esbuild/linux-mips64el": "0.16.5", + "@esbuild/linux-ppc64": "0.16.5", + "@esbuild/linux-riscv64": "0.16.5", + "@esbuild/linux-s390x": "0.16.5", + "@esbuild/linux-x64": "0.16.5", + "@esbuild/netbsd-x64": "0.16.5", + "@esbuild/openbsd-x64": "0.16.5", + "@esbuild/sunos-x64": "0.16.5", + "@esbuild/win32-arm64": "0.16.5", + "@esbuild/win32-ia32": "0.16.5", + "@esbuild/win32-x64": "0.16.5" + }, + "dependencies": { + "@esbuild/android-arm": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.5.tgz", + "integrity": "sha512-eNkNuLSKpbZTH0BZklJ9B9Sml7fTIamhrQNBwftsEHCUuSLBVunzV3LfghryVGpE5lSkOwOfeX6gR6+3yLaEfQ==", + "dev": true, + "optional": true, + "peer": true + } + } }, "escalade": { "version": "3.1.1", @@ -2692,20 +4100,12 @@ "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" - }, - "dependencies": { - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - } } }, "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", + "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -2716,9 +4116,9 @@ } }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.14.0.tgz", + "integrity": "sha512-eR2D+V9/ExcbF9ls441yIuN6TI2ED1Y2ZcA5BmMtJsOkWOFRJQ0Jt0g1UwqXJJVAb+V+umH5Dfr8oh4EVP7VVg==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -2773,9 +4173,9 @@ "dev": true }, "generic-pool": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.8.2.tgz", - "integrity": "sha512-nGToKy6p3PAbYQ7p1UlWl6vSPwfwU6TMSWK7TTu+WUY4ZjyZQGniGGt2oNVvyNSpyZYSB43zMXVLcBm08MTMkg==" + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==" }, "get-caller-file": { "version": "2.0.5", @@ -2789,6 +4189,12 @@ "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", "dev": true }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -2837,6 +4243,14 @@ "source-map": "^0.6.1", "uglify-js": "^3.1.4", "wordwrap": "^1.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "has": { @@ -2867,9 +4281,9 @@ "dev": true }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.1.tgz", + "integrity": "sha512-d2qQLzTJ9WxQftPAuEQpSPmKqzxePjzVbpAVv62AQ64NTL+wR4JkrVqR/LqFsFEUsHDAiId52mJteHDFuDkElA==", "dev": true }, "inflight": { @@ -2898,9 +4312,9 @@ } }, "is-core-module": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.9.0.tgz", - "integrity": "sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", "dev": true, "requires": { "has": "^1.0.3" @@ -2979,15 +4393,15 @@ "dev": true }, "jsonc-parser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", - "integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "dev": true }, "lilconfig": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.5.tgz", - "integrity": "sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", + "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", "dev": true }, "lines-and-columns": { @@ -3024,9 +4438,9 @@ "dev": true }, "loupe": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz", - "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", "dev": true, "requires": { "get-func-name": "^2.0.0" @@ -3048,9 +4462,9 @@ } }, "marked": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.17.tgz", - "integrity": "sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.4.tgz", + "integrity": "sha512-Wcc9ikX7Q5E4BYDPvh1C6QNSxrjC9tBgz+A/vAhp59KXUgachw++uMvMKiSW8oA85nopmPZcEvBoex/YLMsiyA==", "dev": true }, "merge-stream": { @@ -3091,9 +4505,9 @@ } }, "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", "dev": true }, "mrmime": { @@ -3243,9 +4657,9 @@ "dev": true }, "postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "version": "8.4.20", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz", + "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==", "dev": true, "requires": { "nanoid": "^3.3.4", @@ -3285,16 +4699,16 @@ } }, "redis": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.1.0.tgz", - "integrity": "sha512-5hvJ8wbzpCCiuN1ges6tx2SAh2XXCY0ayresBmu40/SGusWHFW86TAlIPpbimMX2DFHOX7RN34G2XlPA1Z43zg==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-4.5.1.tgz", + "integrity": "sha512-oxXSoIqMJCQVBTfxP6BNTCtDMyh9G6Vi5wjdPdV/sRKkufyZslDqCScSGcOr6XGR/reAWZefz7E4leM31RgdBA==", "requires": { - "@redis/bloom": "1.0.2", - "@redis/client": "1.1.0", - "@redis/graph": "1.0.1", - "@redis/json": "1.0.3", - "@redis/search": "1.0.6", - "@redis/time-series": "1.0.3" + "@redis/bloom": "1.1.0", + "@redis/client": "1.4.2", + "@redis/graph": "1.1.0", + "@redis/json": "1.0.4", + "@redis/search": "1.1.0", + "@redis/time-series": "1.0.4" } }, "require-directory": { @@ -3336,9 +4750,9 @@ } }, "rollup": { - "version": "2.75.7", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.75.7.tgz", - "integrity": "sha512-VSE1iy0eaAYNCxEXaleThdFXqZJ42qDBatAwrfnPlENEZ8erQ+0LYX4JXOLPceWfZpV1VtZwZ3dFCuOZiSyFtQ==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.7.4.tgz", + "integrity": "sha512-jN9rx3k5pfg9H9al0r0y1EYKSeiRANZRYX32SuNXAnKzh6cVyf4LZVto1KAuDnbHT03E1CpsgqDKaqQ8FZtgxw==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -3353,12 +4767,6 @@ "queue-microtask": "^1.2.2" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -3381,14 +4789,14 @@ "dev": true }, "shiki": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz", - "integrity": "sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==", + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.11.1.tgz", + "integrity": "sha512-EugY9VASFuDqOexOgXR18ZV+TbFrQHeCpEYaXamO+SZlsnT/2LxuLBX25GGtIrwaEVFXUAbUQ601SWE2rMwWHA==", "dev": true, "requires": { "jsonc-parser": "^3.0.0", "vscode-oniguruma": "^1.6.1", - "vscode-textmate": "5.2.0" + "vscode-textmate": "^6.0.0" } }, "signal-exit": { @@ -3415,10 +4823,13 @@ "dev": true }, "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "requires": { + "whatwg-url": "^7.0.0" + } }, "source-map-js": { "version": "1.0.2", @@ -3452,10 +4863,19 @@ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", "dev": true }, + "strip-literal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.0.tgz", + "integrity": "sha512-5o4LsH1lzBzO9UFH63AJ2ad2/S2AVx6NtjOcaz+VTT2h1RiRvbipW72z8M/lxEhcPHDBQwpDrnTF7sXy/7OwCQ==", + "dev": true, + "requires": { + "acorn": "^8.8.1" + } + }, "sucrase": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.22.0.tgz", - "integrity": "sha512-RZeE0UPxCjf99p4c9Sb27qRbsuZBd7TViR/q1P6TsUPYa/H2LIkaCPpio6F1nQksrynYA78KEBUnpxswZiPYcg==", + "version": "3.29.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.29.0.tgz", + "integrity": "sha512-bZPAuGA5SdFHuzqIhTAqt9fvNEo9rESqXIG3oiKdF8K4UmkQxC4KlNL3lVyAErXp+mPvUqZ5l13qx6TrDIGf3A==", "dev": true, "requires": { "commander": "^4.0.0", @@ -3526,10 +4946,16 @@ "thenify": ">= 3.1.0 < 4" } }, + "tinybench": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.1.tgz", + "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", + "dev": true + }, "tinypool": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.2.4.tgz", - "integrity": "sha512-Vs3rhkUH6Qq1t5bqtb816oT+HeJTXfwt2cbPH17sWHIYKTotQIFPk3tf2fgqRrVyMDVOc1EnPgzIxfIulXVzwQ==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.3.0.tgz", + "integrity": "sha512-NX5KeqHOBZU6Bc0xj9Vr5Szbb1j8tUHIeD18s41aDJaPeC5QTdEhK0SpdpUrZlj2nv5cctNcSjaKNanXlfcVEQ==", "dev": true }, "tinyspy": { @@ -3575,35 +5001,203 @@ "dev": true }, "tsup": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.1.2.tgz", - "integrity": "sha512-Hw4hKDHaAQkm2eVavlArEOrAPA93bziRDamdfwaNs0vXQdUUFfItvUWY0L/F6oQQMVh6GvjQq1+HpDXw8UKtPA==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-6.5.0.tgz", + "integrity": "sha512-36u82r7rYqRHFkD15R20Cd4ercPkbYmuvRkz3Q1LCm5BsiFNUgpo36zbjVhCOgvjyxNBWNKHsaD5Rl8SykfzNA==", "dev": true, "requires": { - "bundle-require": "^3.0.2", + "bundle-require": "^3.1.2", "cac": "^6.7.12", "chokidar": "^3.5.1", "debug": "^4.3.1", - "esbuild": "^0.14.25", + "esbuild": "^0.15.1", "execa": "^5.0.0", "globby": "^11.0.3", "joycon": "^3.0.1", "postcss-load-config": "^3.0.1", "resolve-from": "^5.0.0", - "rollup": "^2.74.1", + "rollup": "^3.2.5", "source-map": "0.8.0-beta.0", "sucrase": "^3.20.3", "tree-kill": "^1.2.2" }, "dependencies": { - "source-map": { - "version": "0.8.0-beta.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", - "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "@esbuild/linux-loong64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "dev": true, + "optional": true + }, + "esbuild": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", "dev": true, "requires": { - "whatwg-url": "^7.0.0" + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" } + }, + "esbuild-android-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "dev": true, + "optional": true } } }, @@ -3614,15 +5208,15 @@ "dev": true }, "typedoc": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.2.tgz", - "integrity": "sha512-THpC4vtb3wu1yck6YHzEc4ck6W4lScf8TD0Rg7XAetDih8BzP+ErYO0/6DtdzYcZyKkDwEoujkMeWW7CffCbrQ==", + "version": "0.23.22", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.23.22.tgz", + "integrity": "sha512-5sJkjK60xp8A7YpcYniu3+Wf0QcgojEnhzHuCN+CkdpQkKRhOspon/9+sGTkGI8kjVkZs3KHrhltpQyVhRMVfw==", "dev": true, "requires": { "lunr": "^2.3.9", - "marked": "^4.0.16", + "marked": "^4.0.19", "minimatch": "^5.1.0", - "shiki": "^0.10.1" + "shiki": "^0.11.1" }, "dependencies": { "brace-expansion": { @@ -3635,9 +5229,9 @@ } }, "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.1.tgz", + "integrity": "sha512-362NP+zlprccbEt/SkxKfRMHnNY85V74mVnpUpNyr3F35covl09Kec7/sEFLt3RA4oXmewtoaanoIf67SE5Y5g==", "dev": true, "requires": { "brace-expansion": "^2.0.1" @@ -3646,24 +5240,24 @@ } }, "typedoc-plugin-markdown": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.13.1.tgz", - "integrity": "sha512-Gx7pmvFNXAxbE9N2MuQNi5RwMVSH9lPxDBAaBNftaZ+ZzMO8YkDwir6aoXcWNq50qgG/eTs5CiKvLe33OVm2iQ==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-3.14.0.tgz", + "integrity": "sha512-UyQLkLRkfTFhLdhSf3RRpA3nNInGn+k6sll2vRXjflaMNwQAAiB61SYbisNZTg16t4K1dt1bPQMMGLrxS0GZ0Q==", "dev": true, "requires": { "handlebars": "^4.7.7" } }, "typescript": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", - "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "version": "4.9.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", + "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", "dev": true }, "uglify-js": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.16.1.tgz", - "integrity": "sha512-X5BGTIDH8U6IQ1TIRP62YC36k+ULAa1d59BxlWvPUJ1NkW5L3FwcGfEzuVvGmhJFBu0YJ5Ge25tmRISqCmLiRQ==", + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", "dev": true, "optional": true }, @@ -3684,45 +5278,246 @@ } }, "vite": { - "version": "2.9.12", - "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.12.tgz", - "integrity": "sha512-suxC36dQo9Rq1qMB2qiRorNJtJAdxguu5TMvBHOc/F370KvqAe9t48vYp+/TbPKRNrMh/J55tOUmkuIqstZaew==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz", + "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==", "dev": true, "requires": { - "esbuild": "^0.14.27", + "esbuild": "^0.15.9", "fsevents": "~2.3.2", - "postcss": "^8.4.13", - "resolve": "^1.22.0", - "rollup": "^2.59.0" + "postcss": "^8.4.18", + "resolve": "^1.22.1", + "rollup": "^2.79.1" + }, + "dependencies": { + "@esbuild/linux-loong64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", + "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "dev": true, + "optional": true + }, + "esbuild": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", + "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.15.18", + "@esbuild/linux-loong64": "0.15.18", + "esbuild-android-64": "0.15.18", + "esbuild-android-arm64": "0.15.18", + "esbuild-darwin-64": "0.15.18", + "esbuild-darwin-arm64": "0.15.18", + "esbuild-freebsd-64": "0.15.18", + "esbuild-freebsd-arm64": "0.15.18", + "esbuild-linux-32": "0.15.18", + "esbuild-linux-64": "0.15.18", + "esbuild-linux-arm": "0.15.18", + "esbuild-linux-arm64": "0.15.18", + "esbuild-linux-mips64le": "0.15.18", + "esbuild-linux-ppc64le": "0.15.18", + "esbuild-linux-riscv64": "0.15.18", + "esbuild-linux-s390x": "0.15.18", + "esbuild-netbsd-64": "0.15.18", + "esbuild-openbsd-64": "0.15.18", + "esbuild-sunos-64": "0.15.18", + "esbuild-windows-32": "0.15.18", + "esbuild-windows-64": "0.15.18", + "esbuild-windows-arm64": "0.15.18" + } + }, + "esbuild-android-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", + "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "dev": true, + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", + "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "dev": true, + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", + "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "dev": true, + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", + "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", + "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "dev": true, + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", + "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "dev": true, + "optional": true + }, + "esbuild-linux-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", + "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "dev": true, + "optional": true + }, + "esbuild-linux-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", + "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", + "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "dev": true, + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", + "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "dev": true, + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", + "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "dev": true, + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", + "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "dev": true, + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", + "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "dev": true, + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", + "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "dev": true, + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", + "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "dev": true, + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", + "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "dev": true, + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", + "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "dev": true, + "optional": true + }, + "esbuild-windows-32": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", + "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "dev": true, + "optional": true + }, + "esbuild-windows-64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", + "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "dev": true, + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.15.18", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", + "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "dev": true, + "optional": true + }, + "rollup": { + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + } } }, "vitest": { - "version": "0.20.3", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.20.3.tgz", - "integrity": "sha512-cXMjTbZxBBUUuIF3PUzEGPLJWtIMeURBDXVxckSHpk7xss4JxkiiWh5cnIlfGyfJne2Ii3QpbiRuFL5dMJtljw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.25.8.tgz", + "integrity": "sha512-X75TApG2wZTJn299E/TIYevr4E9/nBo1sUtZzn0Ci5oK8qnpZAZyhwg0qCeMSakGIWtc6oRwcQFyFfW14aOFWg==", "dev": true, "requires": { - "@types/chai": "^4.3.1", + "@types/chai": "^4.3.4", "@types/chai-subset": "^1.3.3", "@types/node": "*", - "chai": "^4.3.6", + "acorn": "^8.8.1", + "acorn-walk": "^8.2.0", + "chai": "^4.3.7", "debug": "^4.3.4", "local-pkg": "^0.4.2", - "tinypool": "^0.2.4", - "tinyspy": "^1.0.0", - "vite": "^2.9.12 || ^3.0.0-0" + "source-map": "^0.6.1", + "strip-literal": "^1.0.0", + "tinybench": "^2.3.1", + "tinypool": "^0.3.0", + "tinyspy": "^1.0.2", + "vite": "^3.0.0 || ^4.0.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "vscode-oniguruma": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz", - "integrity": "sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", "dev": true }, "vscode-textmate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", - "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-6.0.0.tgz", + "integrity": "sha512-gu73tuZfJgu+mvCSy4UZwd2JXykjK9zAZsfmDeut5dx/1a7FeTk0XwJsSuqQn+cuMCGVbIBfl+s53X4T19DnzQ==", "dev": true }, "webidl-conversions": { diff --git a/package.json b/package.json index 41c9f5f1..e7112737 100644 --- a/package.json +++ b/package.json @@ -44,16 +44,17 @@ }, "devDependencies": { "@types/node": "^18.0.0", - "@vitest/ui": "^0.17.1", + "@vitest/coverage-c8": "^0.25.8", + "@vitest/ui": "^0.25.0", "c8": "^7.11.3", "tsup": "^6.1.2", "typedoc": "^0.23.2", "typedoc-plugin-markdown": "^3.13.1", "typescript": "^4.7.2", - "vitest": "^0.20.0" + "vitest": "^0.25.0" }, "dependencies": { - "redis": "^4.0.4", + "redis": "^4.5.0", "ulid": "^2.3.0" } -} +} \ No newline at end of file diff --git a/spec/functional/search/products.ts b/spec/functional/search/products.ts new file mode 100644 index 00000000..5cf6a755 --- /dev/null +++ b/spec/functional/search/products.ts @@ -0,0 +1,22 @@ +// Vector values taken from RedisInsight example (hex format to make comparing bytes with CLI slightly easier) +export const products = [{ + name: 'Mobile phone cover', + price: 50, + image: `55cb1d40f7d0853e18b63d3d120c913fd182893e323a703eac4efb3e8891213e520a03405d2a423d44fcc03e6bed1d3f48eaa43b0a5d863fd153bc3f4d8a023f000000004189713f41ef543ea1f74a3c434fc63ed24b5c3e92559c3db4066b3f6ff9c63e4920883c565b443efb7c063f000000001288fc3ee264d23f000000007303de3af93a1a3fc10fc73e00000000000000001f52403fc3c7fc3f03a7463f6a61813fe613d73c9132ce3f77ee093f794ac03fca66c73fc0b35d3f00000000cab1d63f4b08853fdb93f33d30b08d3ed9bc943cfdb7203c0803c53fe33f633f00000000a5a9963e524c7c3f2104253fe9db8e3e466a893db8c60a3f4032a33ffd9c583f00000000fb631f3f0e50383d7847223f7f5a5a3d9a5cea3ef0092540c341833ba534833c22a2333f28e6ba3e8a401b3f9b66a23b92336e3f2c8c9d3fcec1e43f744157404ef16a3f8a63393e4c422e3d00000000ffacd53eacf1803ec6de1f3f636aa03af052bd3e11c0bc3f1a24f33d437b043ea244a03e98a78b3dd86008407724a03e3f0a333dd676fb3d79ffd93d747c143f1f1ac83a874df33fe1f69b3f72cd9b409b945e3e3bd9043d6c12a13f186de03dc9ec293c1b83cf3d917a9d3d30b6513df375ec3d884c943d773f733db45ae13c6aee8e3eb7aa333fe8c64c3f6a97143f700d5e3cb63a483e2296393c0000000014703d3f94198f3e18c7153e7d2c4e3e323b413f54123f3d1026223de82f6f3d6a9d2e3fe2078d3f3796d33fadd6973e7b249a3c6f86413eb41e8f3e3d662d3f5123cd3ec1fd343f0498533fc48aff3dc8bf4f3ef64e3540dd13163eaa80143f5f70683ea7dee23faae9d13ec90d903fd62e173fc942db3c3203f23e68d03e3f6557793f6e37893f0330b23dea1f7f3e1f8e343e4ae1ca3eb21a303ffd6adf3e37c6003f0000000099f2213e922acd3e3736cd3e7d776b3f5ab7993d16f5453df6d5133bf4f0a53f6112343ef250d83dff01813f817b2840c5438f3e226e723e50b8da3cb6f5034026ca533c8754fb3e0000000041873a3f591f8e3f39f2323fdd13f43ef639f53e98f2e53f2bf24f3e3776af3f9ddba13e944cdb3e4c740b3fde93773e3c4af03d364fa93f3d52703dab40393f7601963e7441703ee654653fced4343fa787ac3f4ee4103f3db31a3ea803eb3e3983e93e000000003fc11a3e4e3db43f1df001402aca903cbf11503ec172333c720e2b3f49545c3d12299d3ebb57dc3f0e205c3e7de96f3f4584ce3f8196733cef6a583d4db3993d22567f3f253ade3ee27fa73fbb7a7e3fe5378c3e39ee133fccbd07401e6ec13fb65b0e3efdcb383f51a85940682aae3f64b1843d83a83b3fc0568b3e6c84223f5087863f3cc0323c671ae13c580a813fcaaed53da820f03d4d5b593df0e1be3f3b8bed3f21687d3f9ecfe23f0e15a83e9008a23f2abbf03db708c33e8df9384087c18f3f150f523e88aaae3e1588a83eef438d3ec74c1b3d1063a83e300c09404cecd03f0517cb3e843ba83e41e7f83dece4ee3ec359423eb3b9203fd982853e3fce723c146f813f365e9a3ef96f993fe8a1073e392b8e3f225d433d3c2dff3bde61a93faa56dc3e2cf810400545de3f1110ba3e0822143edeec7c3e65ab963eae98633f8308693cc5eab53d19e6bb3ec7a5cb3e9204953f117a5c3f886b6940d0fafa3e373f3d3f6a390d3ec5c7a53e00000000ce2f8c3ee5a7073f00000000872b783e4161cf3d32174f3c0000000054cd493c78c51b400fa2993d100bd03ce707d63fa1781f3f7c3ee53fe82053407cd9d13ed9a80840ac7a343eaa51113e2a51dd3f36c49c3cf4ed243f0f69093d1e915b3e28151b3e9a82a03c37b9ad3fb389713dc9722b40fa348e3fc337803fe789cb3dc8e6903f07308d3fffdee53df5e9243da795dc3ebdfb1b40955db63c3565133fc7803e3f0722003fdb87103f7994cd3f0668173c15e8cb3fa3b38e3d2aaa2d3e441bd43f099dd33ee53f2f3f1f94b93e0000000090ee613f598f484030ab283e843db83f0000000099e0be3f88d8793f3face13a41e1b83f5b8003406ece473f000000006b70893f5465cf3eb463623f3e849f3e70669e3b3682413f28554b3c5d368e3f7560243e7bdfaf3ec59bdf3ff82bef3dce4e423f0000000005b19f3ce434903eec712f3e40c8d13da9c3243e268ec23f000000002ede793e7ea20a3daefbfd3de6214f3ef9b1cb3fece9513ea77ac23ea9c4903e000000003fb7be3f6123b43e876b663ebdd6f53eef82303e6418a53f56746d3d77aa1a40da86a13fde72e83effd88b3d960bdd3d1d9d5d3e76da953f92c0ff3f8c6c813dc952e23ed130193fdd0ac03eac528f3abbcf393d87dc863ef3391a3f221d673fb800d73d2196973f00000000ef13a83e54a4173ef3fb2c3ffdadb43e00000000000000004cc0d33dc1539e3b5ba6c03fbbd9113daf0e413fcc62283d0ccb983d65da463e3fbd0b3f22c5d33e47f8773ea57e103ee1f03f3d2b12883b234c5c3e4889933f03a3e23da3f7993fc533663eb98ddd3f54a8b83ebcf5193a050fbf3f72fbba3ece4f313f516e863f510fca3e9abeaa3ffbe7fa3d3074843f0a758e3de8841d3ffb77b13e1fd14a3f8ce8ff3e2aa3c63b000000001610a93e0ab8ff3e9687b13e1c2b1c40637fdb3d91c6a83e16c98e3f6ce4213f628c383f4162fc3e7c44b03e8387803e40b5883c12622040229b0f3daf1c8f3fc044953ed1f0673e6197f33e3f09823f5809023eceea743fa310063ef20fa03cbeb4833cf394893fccc94e4065d7833e70a9913f28528e3d2e28a43e1053363f2136c43d1b34813daaae713f886add3ed587383f3260a93f2216503f000000004bac993e`, +}, { + name: 'Gold phone cover', + price: 78, + image: `262044403437ba3bac28ae3f51461e3f62a8223eff4db63edd1880404835053f0afd464091b6163fcafbc43f4e0c7f3f1695053f2ce8e93e68cc293fd0b6be3f51953d3cc338264054a5c63d779e163ebb82383f1418993e9ab8f23f5421b63f8187f13faee4aa3fe3ac373f0c919e3ee5c9883ee5b7083ef0ef15404c5d1b3f7f88073ce7c1064063e05e3fdd4b603d88d3ca3ea772a23fd6068240dbc6b53d678fba3e56516a3c1bd7d03faef2213fa5b14940e2f9dd3fff44023fa1a4a23d58cf463ff902953e00000000e5f50c3f45439f3f000000001076b03f799a003fd4cefa3e7bbef33e5dbb1840c026f03f70a1113faa22ed3c703b563dbc67653f28d4703f3c67f43de1426e3da23a0c3e81ddb23ea8c5873ceee9be3e45e86b4041fc943eee20e13dcad90c40fd711e3fcaeec23e3822153dc97dbd3ffbb3b93dd428e83fde0a35401268ac3fb480c23d94e6b83da2cc4c3fe8dd8f3f6618c53f5b7c723f38f3d23dee29883f1274aa3ff400c93e8acf093e0e9dbd3fd01b133e5b7063408cf5423fec34323e8071453ec9525d3e229baf3fa667423ed877033f33adaa3f73bed43fbf47c43dda57a53fc12e7b3ed0faa93f7206ba3e00d8e33d8f819c3ee17bb83f58b68a3e5e4e4b3e257fb13d54d1a33ef8cc223e2cbdf93e3bab5240dd229d3fc9992f3d01dadd3ec722033a1abda93d9d96cc3e0e902d3f52a9f33e6317aa3e63b1223f5733143f352c1b3fa52f263f805d083dddf511403da10f40f6c3c83ed079463f4ebb253f1074603fef26bb3ecc305f3e99f85940eb01c83fb890983ee616433f775a693f05c5fd3e92362f3f62adcb3e47020a40bc04493cf5dd813f6341ee3d5df2a03e0000000040f4183eec8211403603843f7077e33fcd899e3e0553a03fccb159405b96493f5456903e0000000074be4f3f1646313e1344263fde99443e8007aa3eb4f69b3db728423e6fd9963f05809b3ee68fc43f66fdb43e0a6ec13f5f79f33fe8151d3f59e7293f76d6e93d852e22405247d73e78943c3ee6de3c3d55a13a3f6a90933f0ab03f3e5e34713ee644ce3dd9a4ed3f4653213db4a2233fe3f9014005f7a73fa2821b3ff262903fa872383d4c964d3ec2721d3faf01af3e827e933e9bdf533cf36dae3f23b89840c457793f032eca3fbc19b13ef0bb6c3da856003f000000003489d73bbbde4e3f74a48040d65ec23d25182b3f0a851e3e2304803f5b00ba3cb60b3f3fa75c0a40f079f53e8579493f1a5e2440f954a13c00000000ad71143da38f763f4d0c2d3f1f7fb53f80ffe33f8d79683bffa0153fafe7353f98e7124012c7b03fb70a553fdb4c45402fe9733e95214a3f33d3134018d28e3d5b57093f2f9ce63fea7edf3ee343d03fee141e406c6a863dfb5b033e5f50213d36c8564009d3533fca99353ec53d633f3f07183f0d6b424006e9803dbb9ac73ceab17e4055fc863f1e97d13dc460ec3e3617233f91a5b63e052af43c16b08c3e02a8143ffa9d8f401338803d04ad833e41da0e3bf8489b3f493a4c3ff2dfe13f877242404e05033d09e732402fb00d408162a13fa5c9453ec1e72e3ff0358c3d3f78d13fcc67b13f1aadc43e10c7814040f1c53fbbd2303f54c78a3d1dea963edf1e9a3f0990c23e88ac593ea3e8e43e7fdcc33fc812b83eac02b03fac67c53f8d4db440a560993f90308f3e4c20483d5ac1023eb963f73abf18463f14734e3f1c228f3c60319c3e410df23e8ce1c63f000000007c9bc43d840e444000000000bf42823e3dfb123f18a0083fca75ce3f5e6ad23f1b41403f631b224083a3f63e288b0d3f9f222d3f00000000965c0140d50eb13defd0903f1e36123d9fc6c63e0736e53faf4a1a3e5b2d3e40366e903df00ca63d04d3423da0240340492fd63f8051023f2273663fa79e4c3d67613e40b079033d72cac93e98910540e72f2e405933ba3b8d26563f2dd19e3fb090b53f3780a83db3c4d73eb7ed4f408ccd0740ac5f583f72e8ce3e369bc93dc05bc33eff658140a05f083feade1e3fd662fe3bfbd1ae3f3d3da43f2114653d0498f63f43a3bf400723433fb6768c3e5286623fab24853f8503e73f612fd43e04f8623f703a803e7cfa853fe9bc813f9146a93d5e74ac3ec356af3f5c7d903b6e3f8c3f000000009a9bfa3ef848ae3e194f4a3f122e3c3e5b39213facc8573f2210523f363c7b3e6e29783e21cb193da636d73f1a5c0a40bb1cdb3ed230973fe136e63eea12b13d7267493fff47833ff40fdb3dc7e5633f11e0683fd656ca3f04c18d3efc6fcf3ff0ec473f2faf3f3f10060b3e4109f33ee2835b3c34538d3fa86d5740b6504a3c1907b93fb22e3a3e79accb3e5fedbf3e7fa8903d7909303e4463ad3e7f09643f4edd7c3f7913393fe822163f7f3c034039b3373fa7949a3f07a7bd3f347b7d3e49c54b3e7824d23f8710b13d44bd14400ad4f63f88ae393e7388f33d07a64e3e3b400d3f46c1023f9634b03f9f32033c0800253f28fe833ea1e9c63ddb37453f3396533f08d3a43c2c72543f9be3ec3ffcd7a340f4c2cd3ffc4b3b3de32b133fa1c10e3fdae2f33e68cbd93f0c640540ec071940a8659b3d5bd1793fabcadd3ece562a4087010f3e5dcb913f15c27f3e38ddc63def334d3f7901843f1402743e1422ff3f184b6a4045c4703f3735eb3e4758503f093c033f45e5223d4952d73e9939253f146dc13d9fdf293f94891c404efa843f346e623f49b9a23f44536f3f34d46c3e5e28783f00000000f92b8d3e6a09403f1984163e83f7a73ef833ae3fc8f52e404e42993fc761753fac9fa93ec9c4a53e5517bc3f1447463bc48a263ed979613f4726f73e36b6bb3c0d9c3c3d6c5b953f6b222b3cf46afe3e`, +}, { + name: 'Patio Light', + price: 120, + image: `35d4113f32cdd43dc803043e85ff453da392643fa1b3da3e12cc113e5b99db3e7401653fe23d213f2be8953f54c82d4080137e3d23bc953e2392843e2317104000000000ab58703f44826040aed8a53fce99c33f9146a03e2284283f0a659c3edd996a3ef619ed3f5edac53e0923853ed974403f3b13fe3f5b81b03e01ac1c3e6e0de63ec81f723f2a408c3ec8398b3f98455d406e52333fb43cb03f0d6fb53de6910c3f9a54843f92ad0e3dc788bf3f720c673f778b643f2354cc3f265b0d3f3337983edea2413e537a1040486a6b3f2e567b3f1668db3fbc6152409df0cd3f314d9c3db2f9893fc5c3053f72cca23f4760d13e04faa83f95f9543eab420840548f0b3f0923143ec5a6b73ff85aa33eb201aa3e5617fc3eaa557f3f190d3c401b77fb3f8735443f03a3853d9503f33f2284be3e10c8253f3847503faae4753f33109e3f15c6df3ff6b4d63de8310d3f059932405487293fe86c923bda5a373e479c3d3eea87cf3fd8367b3ff6c76e3f660de43cd0d69a3eed00163f9d0e0e400a175c3f9fd8a53d00000000e8be963ef83a673fda9a933fe1651540b9a34e3efc29df3dcada8d40a85cac3e14150a3fc800af3e39019b3f4d048d3fa3dc6d3ff0730f40c95bbc3eeaf9ce3f20b1203d801fe03cd1fbc93facb54a3fcd915a3f4457a13eac1cae3f132b193fe58b5a3ec7a57f3fd6ce9f3e18988c3f485ae83ebd88f23e37832f3ff981c83ee23f2240db66a03f5ee4343efeac033fe7021a3fbe47a13e7265f13ef0d47a3f10541d3f5fbfca3db286dd3e7a30983e37e4f63e409dbc3f52c5233e4159323f61a2254068f6183fe179483e5a38453f459a2b4095c0a83f2574b93ecd5fb63d1c00a43ee86f513f7046f03ff34eb63fa35ea03e814cb03fbc4aa93fdc7d1b3f6528993f72d1673ff7b8c23fdb0e8e3e58643c3f3fff293f59ab413ed65a013fc4eab53f7b75373f6a2d453f2637283f03d8563f28bdad3c38a1b33e112c313f90e2243f0156ac3fccd5803f34faf73d7bd4803e3b04cc3c7779a73ee6e1c93feed9323fc1128b3d12151f400de8b53d6f09cc3d0d02373fc850f43e79c7a83dc573263fe35c5d3fc9bfd53bb26aa63f96d1a43ddb6d163e2c7eca3fe6ad363f9963283f0d09983f7423063dc522333f8a02573f851d2a3f39f9fe3d0169143d4cc59a3e16f0fa3fa1ad213fb937153f23ded03dc4e91f4078c7893f000000007d0f223fc54f933ee108c13e9bace83fcba50f409223d33e8b8e993fb336db3edd442e3f2555c13ed40cd93ea618043e901ce03f0573da3d5573293f388e023ef6c6a33c63db193edabb334036be2b3fe24c893f22bdac3fff31bd3e087bb63f647c9f3ef4e95d3f30dead3ff9747d3ec386263fcf2c0e3f74d9ec3e6cfb9b3f09c2b23e80e3a13f1988733e15b7ca3e689b1e3f4716933f840ae03ea1a52540ca2b533f227c883e63c1073e2558ca3e70e9a83e1668b13f133e213fbb9fbd3f0d08723ff9f1553f2f09f03eac3cbc3e8d1b9c3f07e81e40c85e213ddd4109403fbe863eda0f3a3e0462cc3f3768ad3e140ebe3e5b3ab73e94cd1340ea89be3fe647483d7c150540830b173fd4bf1b404379093fb73fee3d6c37133f1d80ca3e9a99653fc979aa3f8ffb123f2a52143fb971373f9807923ff6ea3e3f5a05e73eaca1793e21db3440f7c0e13e784c514059cf943e33d3553f0fb2893cc4c655405f0e3c3f40b11340dea3233f52301b3f76c8ef3f9d1aa93e9ac4553e807b793ea599573fd9872e3f805b6440e69cf23d95d1ba3e22150d3ff4c3fd3e165f3740213e803d4813bd3f2c33df3edb8b8e3ef6de2d40af40d33f7949813ef011613bdae2e13f454d8b3e684c763fd22a953fb699963e322f583fd98b1a3f2f39283f03f1733f4d51f33f3c253d407601643e14282a3f3fb42e3e4d03263f24d0963ff962154001f0823d38d7f73f03dba73ed430893d3f8e263fe5319e3ee5c5de3f99d39d3d4e42404061ae2240918eb43fd6b7443c0cd1a53f77a7c240d6ad223f990db73f7dde3f408764ce3f3facc23f837dbb3e3aa39a3ea1b9de3c10505a3f7b7e443f03187a3f7c23b63f3952523ff8121d4062f7733fa331fb3f6825ee3c32bf0a404441b63f4d9c4f3d12ec7d3faffa853fbc940a3dae88823ff98b1c3f1b3e5a3f5158353e619bbf3db74e433fb9a81e3e096e5c3d2c7c7a3f5be0843eac75d13de194d23fe368a53eecd1903f417ceb3faf9fa13fca7dfb3f1157313fbb18d43e5d33ea3fd001af3eeec31f3e5f12333fd54b3b40129f993fabe81b4087fba83e11319e3fecc5013feaa4b23e79010e40a26dc33d4120b63f4409bb3f43a5473f9d0f533fc501913f3218673fda34833d7637fc3d1a70dc3fd6a8d93cfc859d3d18c7503f0c07a63fa2cf1f3fa7d2ae3f557a4d3e199ee93f944b723e8a30483c25ae3f4034b98e3ebc10263f5a5914401da23740f77cc73ef21a703f9f297a3ff63f8e3f25e7044021846f3f65a61c3f4c953b409ff8593fe56bb33e703bd03d2a84283e9a22c540cef5733d66873e409c4d963f896b373f4ab0a43e15555a3ec4053a3e3737f23eca13893fe17cb53f38d4943ffcaad23e0d4bb43f7492113f2ea7233fe56fe23efccec23f2245733e18c5c63ff678373e1422983f01e3ce3fea06323fd9258b3e3932cb3eaa2bcb3f5fd6073e90af3b3f2892f83ebd710a3eb4561440c1133c4021d3234007da1c3f7f2d1f3f39150640bf045c3fe337543c5d0b863f0a3e903fa5faee3fa27f6c3c6a3e673fa8891f3d7cb28c3fe132b13fb9d5d43fdea3b43fd9d7383edd9cdd3e85530f3c5a43dd3e2b151c3f6533b63ef8929b3fc2311f3ea534803e656dc93f`, +}, { + name: '2-seater sofa', + price: 400, + image: `a8cd873f83e1553fe701173f3fabc83c9fd6613f51aa343fb43b883ff173083f207d943ffa6e19401618a93ff600ff3fc410763f493d443f5d579a3f1f0ddc3f4e0bfd3d25fc2b3faf43453ed146783fb498713e486bcb3f8a7c6d3fe7e9aa3f59482b3f1c34013f03fdee3e9e412940035a313fa5967d3e7983043f1f93393f5220233f85d9ea3dd6eacc3db48e243ff22f414038947d3e3c784f3f381ac33ff128a03e51cfcb3f81716b3f3fddd83f3d5b063f3bf4f63d50a1a13ebb111040f7a3573e12d1963e78a2ba3f8d05053fe474103d3f03d53ec12b2a402ae43b3fb0ea613facf0573f032c0f3f2e22b83fdefebd3f631b6e3fddfc823e2816d43d0a2dab3f5e7e653f3f67423fda7bcd3e7f3cde3e75530f3f094e233e225bb43ee528113fc4de713ec0ab4b3ea6baad3fd3c19f3f68f4473d49b8c83e416bdd3e2c94673e948f893f7b8c4d3ebf903e4003837e3ea7eb633facd6fd3cb4930d3f32d705406237a63fc97c2c3e7ae4143e98b9ba3e5b4e2b3ea6e24d3f67d8053fc4f049401a59623fb426be3f9fcbff3e5904153f707dc63f811bbe3e21c9833fda22163f9fa9f03ef39a3d3d8c381c3e2e3d2e3f41453c40ae0f1e3f0b721f3f8afe9c3ddb492d3e1b72403fa6baa13f2a517340482af53e10213e3fdbfb7d3f014e473e283b2840a4289a3fcc29e83f1b6af73f484b043e8420de3fd4b5853ec48a9d3f3784aa3ee14a833d1556eb3f6d5b933f5f64ce3f908ebd3e1452493fc161cc3e0ad08e3e122aae3d15676640394cbe3fefc3d43e905dde3faf9c433e8622a23c9d04683ea009104052cbda3f24689d3e5ee3b43fb2b92e40000000004c87e13fc3f3ae3ec4f2af3e4720083f25763d3fa767323f8a506f3ee395c43f5e9107402819973e8a49033f806a9b408e8c883fe15a943f372dcc3e22ff1b3fde3bae3f21c9a33f2259803e07d15c3d8576fa3f4d45d63e6fdc3c408d41b43f7824fa3daefb853e1a6dae3d167ce73eb7b20b4054a0963e7db4c73e74f1484004fe7b3f29e31f3f0433183fa9191b3f7280573f91746b3d3d17263f1bfea23d833b1b40099baf3e22d58a40086bff3d794df73e56d56e40bd531c4034cc8b3f5801a83ed4efed3f18ec3d3f770e043d7b82823e12e90d3fa55f033f967fb13f14cdac3ff35e6c3eb30cd43d5272373ede6bdd3e283cd63e7663573f907ad83e21c31f40de97803faaed643f1266a93f5451153f375b433e9a86ad3f4eb6d63fb8aa233f75a21040a776723f83d4f23d5aaed93ee6405d3e49b2063fb465853f7e5a143fccc19d39a2e8283f700b023f58e1d03ee1a01b3e7d62ac3bbf1adb3c25f87b3ff9d2283e30daa73f7953203f23b8533f3cc0833fa593403f339ab03c143e733f9d28f03e19e5d23ff342a23ee1e1683e437e4f3e8cb9bf3e16cc2a3f40d7033fccb4bb3e22258b3fec446a3e9d0ba63f7f94e73efb7fd83f651bb13e894c883f18b45c3f9f0bfe3e11b0ea3e52bd813fb88d9d3d0574043fdb05ef3e3931eb3ed82f4c3e7c688f3b28be013f988eb53e5db9e03ff755423feede163f8af6253f2adb21401259b63f3082963d2c7aa63fc7cfa83ef2cdf63d6c88133fb6541f3fbbf2c73ff0a2ec3fac75b13eb92810407cd5a53efda7003eb9604e3ee31fa93f32da173fdbd0383e402d2d3f964f2a3f68b0c13e45c81a3f94f4f03fc1ada33ea363bb3d4459e03ced6a023eb724f33e66a7093faa88cb3e64e2153f88feb83ff31d003e4708933fca7bf63fdf02c23eae2fb03ec7db133f4ec5153f50f5b13f5f25423f157f8c3ef9e8fd3e3991353fa1eb243ed4703140ef72af3e2a2ba43c386b143e8cd4843ea74b443e6895f13c7f2d0b40da5731405b33653f0358e93f799ba83e89b4ef3ed96ac23fe352463f6b9d823fb685aa3e3cd3e13cb2fd1540cde8fc3ebb39103f5e3ac03e0e6dcd3f78be373f7759bf3f33e6833f94309f3f50b4653f00000000f77f0840d619cb3ff0b3353fff7dec3e50e2483f95693b3f47b43d3ff7183b3f2846e03f6b0e4b40bdd7423f81eea53fb498853e10b02240b914253f3495443d10e8323f7433483ec569773fbf90f83fb450063e2c89373ecaa807406569fa3e1d708f3fade6143e2b07943fa77e9340108d2540a57d7a3e7854093f0729643f55e22d3f77020f3e946ed33ff9f025402118413ea7541f3f3792a63dbdf4933e7cd6363eca9e773faed1813f0715753e016df83de1730b3f7084113e66893c3fff723e40571882405306903f7b988f3fde962a3fb7a4a33ee17ce23fe1a02e3f8cf18c3fa3d9ea3f3d7ccb3facb2873f8d0e793fc7e02c3f1f4de63f9c2b1b3f30345c3f8e42823d49aab43d9b56e63f61add23f9072b93d7013dd3d47994a3fdd49b33ef83ea03ec813c23f2ab0233e3707e93f142e4e3efbf68640ef4bb23f053fd23f41829c3eb8404a3f5d41833e43d6a73e6e74063ba86f813d3fe3d43d1eb2af3f8841c23f1fa06f3e3f11e04022512b3f34ccb13e9ee8b23d7994c03fbcf8ba3f925fea3fd43ca53f3c66ca3e0e2bad3ca22fee3f70ba733f4ad3713e19ff6f3d4ca77a3ce2b3623fd18ef13e7718d93ee0be9e3f78211f3fac1c1640147741401f697c3ef5ff193f4c20283f01ea9d3f74903c40d9decf3f67420a3e4a1e7f3f4402aa3ee3f8413d9e3ec73f5a22d83f55700a3f48cabb3e99feff3e580d813f5581eb3f59f5803fca4cad3fd6ba1b3f051fdb3e2284a53f4a9f174077eed03e3205163f0bb4243f70d1c43fc7e72b3f66590e40d5c2873f22f1283f8d6e713fc359c93e58c0943f8a66b13db2bfce3e5d28303dc8f7543f3fb0c73c2ddd8c3f94db23405042443f6241a33f37407d3d`, +}, { + name: 'Comfy Chair', + price: 200, + image: `5101003f8b25923f1db69e3f1465113fdec3993b1000813f321fb33cc1d53f3ff9e68e3f2ec10840c869023f4082b03fe1711b3fd0fcff3debc3753e7086be3f1f2f8d3ec3acbf3f5059433fc8e2e43eae18093e6a935c3fafd41f3f3b48fa3d2e2a8a3f00000000688ef93e88a4083fe8439b3e33428a3f2b2ce13eb09d263f8c44113eb0fed83e907fd43eb90bca3d38c21c3fe1b4c23e87426e409de2a23da3030b3f0f0e8f3fb919283e414c883f98c7ca3e4cbcdf3fe767a03e4148683d433802400059173e6cb4c03f362f1240db64b53e9560613fa155c03fd5a7bd3f6a7db83e167a843f9bb5433ebfdcd33f3c72383f8dff673e785d9a3e6bf5223ef08e8e3fc4fc153fba7a8d3f4cf9bd3e32ab593e3b8f1e3e03e3813fb896a73f3f7e473f157b463e59306a3fe8ff973cc794b33f3fa74c3e14af573e1f9a85402631143e83fb8b3f88a8b73af8f9013f4df51540a799eb3e45fa1a3ef6d9223f67ab8b3f3faa6a3e951fbe3fbf33903fea9a853e3d10123e66435e3e5599c43f44b90a404869bb3e5f908f3e511bbf3ed111713dc77bc03d17ac0e3fd63b8f3f95c1353d826f83409d0e103f8965033f9e9d313f9e0ecf3f65760a3ed57a703db26e0d3e08f8bd3d6ea78d3f21428f3e65a7803f12c2df3f7b97083d6e8abb3f70af883f197a753d7b3e4e3e8096023ef760803fbde3283ccad13e409eb84f3e3ff1503e5bc0833fea91bd3e7377d93f039fe23f764e2e3d4eb4e73e65c1b03e32989b3f0a1f133d4a63833f2c8ea43fcc8a253fd84e6c3e0c59883e98b1713d3435653e22673a3e4d00eb3c7dff163fc0a1b03ed98f493f1a251f3f08d9783f83b6dc3fdf001a3f6149983e8083f33eb816643f1569023ff33dc63d5ebcb73e874a6b3e50d2873e28798f3e89764a409138da3b6a9ad63fa7f8503e14f51c3d49ca793e44015c3fbf65603eb9b2f93ec8bb8a3e1822ee3de17bfe3fd93a243fdeba0e3ef2f7553e657d8a3fa86ca53e9e64613e22a20c3e5e55af3e2eb2b03f928c323fccfec63ee880423dd2b9e63d7d602e3e2a288b3e2525a93d9abf483d0ccfaa3e7f0ff23daa57c340cef7d03d256abe3e44d32d3f1fc9703fe3874a3f847eb23f386bb73ff0dd3b3fd474bf3f085ced3d2a10b23ea25dd13f98b39e3fada5803f3257853f8f830d3fe81f9e3ebf50c33e72e6c43fe154c23fdb64ec3fb820463da1fc403e39809d3e482ed63f4d3fc83dc7cf9c3f59f4c63eb56ba23e9ab9f63ef423ba3f674a793f3f055d3d1d7c063ec4b7303ff32c5f3f0a18ca3ef87d5a3e513a1e3fec22f73c2f11263f6eefb13ed98a7e3f386e243e8cdd12406135023f32dd7e3ff9dd963d2a77393d839d6a40eabf193cda02ad3e0838433f65beab3fa68b043ed03d653f16ac483d9b43c33daf02f23ba565863e66568a3f8f3da23c4ed8ee3f5ed0223f7682693f7cece53edb2e6b3fc4ad293e829c183f2146003e6c600c40a684bf3f49e96e3dc126313fe24ec53ededa783f7823a13de7bbe83e9d39583f9f3f333e04c7613f61d4343f61a3463d66cf583f6cf0b13ee1ac463fe5d7843fb9fc353de59aeb3e509cc23e11bf7c3d447f103f9ffde43fe1dc3a3eb34a183f301e3c3f7feb453c9242683ec4c12b3e82e3133f557e6f3c2f2c443f8a1b01409042893f943d853f4e114d402ab7a23f5d09483f1d3f0f4083ef623ed61f433ea544d43e0e92fe3e38f0283fea7d033fb8288a3e0dcddf3fb78cde3e28ab2f3f84854340548b473fc758013b78449a3ef5b6803f9b65ce3f96d5603fd2928e3fe15424407479e53dff78c13f395f0440f025b73ef9b2a33e6ba2373fa51f5a3f30f1143f895eaf3efbdb283f22ae333e95d2e73f45dce33db2070a4091e91d3ef8d98e3dd9cfd03fb46e7c3e2fe8433ed15dc53e7092893fea6e853f48a48a3f2646ea3f63e98a3eb31c2d3eb722593eedc1883ed26b8e3e114d6a3dac019e3f4e9f943f1567b23f6f6a254079d3243fa5ee5b3e70fc0e3f5b894740162a873f0e14d73f625f0e3fecf84f40fc360d3f22adf73daa6cad3e30212c3f01a68a3ddae0393f3248703de8afad3dabd0e23f7949083ec86c7d3ffd2dbf3f091eb73e5f6d9c3da6b7223e6b3edb3e150c9d3e81363e3fb420be3f9de9ba3bf3dcdd3e8f99113eb9cafe3d2ceb3b3fa558ac3f7356063eb236f93e1d4cdf3ecc5db53ec4b2423ea2b5823fdb19413e4a57603f8bac1c407d57c53fe2e25b3f84399e3fbcf9973fdd93153f498da93f3c53623ffb929e3eb7a6343fd4f8f63f768dd13f885d153fcdd11440befe8a3e6ee900406d75013f95e97f3f54b4303fb37a953fda9ce23de70c3c3f747eb13e6efe913de2cf613e68a5633e19cb633f1a228f3e0c71b23eb5718e3e9d06ec3faf5c2f3e5907103f592ccb402128463fc8e2e93e6ed22e3ff61d243fef81f43f9535b03f84a22c3f86689d3fc3050a3f7d209a3e28ae033f8c62883f486c283f39a6d93d44d28a40d4cecd3d019c363fefbeaf3f7e30923eb28d033d30db343e77a3f83ed185023f18fe7f407690d53ed066213d58ad983efda3723f2b6ab83d6adee33ddea5ed3d3f87813f40cc033f48cb953fffba163eac9bca3d74c7923f262fdd3ee5080a3fc40efb3e99692d3f80573c3d9622933fa2b8aa3e186afa3f5dfda63f6b9201402212e73f6fa8033ffb78123fd70da43f07899d3cc171b13fd1f8f83a68ddf33f4d84e43db9ac8b3f1b6b1940d171503f224e153e6a9c773e31650b3f5baa283f30c2bd3b00000000623ad03f70482b3da918923f7c6cc23de80dd93fc586f33e956e743f26a0a93e61c4b03e2a787e3cd9c7bd3efbe1d73fdb3ca13e5a601f3f1fc9623e`, +}] diff --git a/spec/functional/search/vector-hash.spec.ts b/spec/functional/search/vector-hash.spec.ts new file mode 100644 index 00000000..dc742fd6 --- /dev/null +++ b/spec/functional/search/vector-hash.spec.ts @@ -0,0 +1,98 @@ +import { createClient } from 'redis'; + +import { products } from './products'; +import { Client } from '$lib/client'; +import { Schema } from '$lib/schema/schema'; +import { Entity } from '$lib/entity/entity'; +import { Repository } from '$lib/repository'; +import { removeAll } from '../helpers/redis-helper'; + +describe("Vector HASH", () => { + let redis: ReturnType + let client: Client + let repository: Repository + let entityIDs: string[] + + // define the interface, just for TypeScript + interface Product { + name: string; + price: number; + image: Buffer; + } + + // define the entity class and add any business logic to it + class Product extends Entity { + } + + beforeAll(async () => { + // establish an existing connection to Redis + redis = createClient(); + redis.on('error', (err) => console.log('Redis Client Error', err)); + await redis.connect(); + + // get a client use an existing Redis connection + client = await new Client().use(redis); + + await removeAll(client, 'ProductHASH:') + + entityIDs = [] + }) + + afterAll(async () => { + await removeAll(client, 'ProductHASH:') + + await repository.dropIndex(); + + // close the client + await client.close() + }) + + it("demo", async () => { + let schema = new Schema( + Product, { + name: { type: 'text' }, + price: { type: 'number' }, + image: { type: 'binary', vector: { algorithm: 'FLAT', dim: 512, distance_metric: 'COSINE', initial_cap: 5, block_size: 5 } }, + }, { + prefix: 'ProductHASH', + dataStructure: 'HASH', + }); + + repository = client.fetchRepository(schema); + + await repository.createIndex(); + + async function loadProduct(product: { name: string, price: number, image: string }) { + let entity = await repository.createEntity(); + entity.name = product.name + entity.price = product.price + entity.image = Buffer.from(product.image, 'hex') + return await repository.save(entity); + } + + for (const product of products) { + const entityID = await loadProduct(product) + entityIDs.push(entityID) + } + + // TODO: figure out rawSearch / where query encoding is happening ... + + // execute a raw search for the first product image ... + const results = await redis.sendCommand([ + 'FT.SEARCH', 'ProductHASH:index', '*=>[KNN 2 @image $query_vector]', 'PARAMS', '2', + 'query_vector', Buffer.from(products[0].image, 'hex'), + 'RETURN', '3', '__image_score", "name", "price', + 'SORTBY', '__image_score', + 'DIALECT', '2' + ]) as any[] + + // ... and we should get the first 2 products back in order + expect(results).toBeDefined() + expect(results).toBeInstanceOf(Array) + expect(results.length).toBe(5) + expect(results[1]).toBe('ProductHASH:' + entityIDs[0]) + expect(parseFloat(results[2][1])).toBeLessThan(1e-4) + expect(results[3]).toBe('ProductHASH:' + entityIDs[1]) + expect(parseFloat(results[4][1])).toBeGreaterThan(0.2) + }); +}); diff --git a/spec/functional/search/vector-json.spec.ts b/spec/functional/search/vector-json.spec.ts new file mode 100644 index 00000000..3f59f44f --- /dev/null +++ b/spec/functional/search/vector-json.spec.ts @@ -0,0 +1,98 @@ +import { createClient } from 'redis'; + +import { products } from './products'; +import { Client } from '$lib/client'; +import { Schema } from '$lib/schema/schema'; +import { Entity } from '$lib/entity/entity'; +import { Repository } from '$lib/repository'; +import { removeAll } from '../helpers/redis-helper'; + +describe("Vector JSON", () => { + let redis: ReturnType + let client: Client + let repository: Repository + let entityIDs: string[] + + // define the interface, just for TypeScript + interface Product { + name: string; + price: number; + image: Buffer; + } + + // define the entity class and add any business logic to it + class Product extends Entity { + } + + beforeAll(async () => { + // establish an existing connection to Redis + redis = createClient(); + redis.on('error', (err) => console.log('Redis Client Error', err)); + await redis.connect(); + + // get a client use an existing Redis connection + client = await new Client().use(redis); + + await removeAll(client, 'ProductJSON:') + + entityIDs = [] + }) + + afterAll(async () => { + await removeAll(client, 'ProductJSON:') + + await repository.dropIndex(); + + // close the client + await client.close() + }) + + it("demo", async () => { + let schema = new Schema( + Product, { + name: { type: 'text' }, + price: { type: 'number' }, + image: { type: 'binary', vector: { algorithm: 'FLAT', dim: 512, distance_metric: 'COSINE', initial_cap: 5, block_size: 5 } }, + }, { + prefix: 'ProductJSON', + dataStructure: 'JSON', + }); + + repository = client.fetchRepository(schema); + + await repository.createIndex(); + + async function loadProduct(product: { name: string, price: number, image: string }) { + let entity = await repository.createEntity(); + entity.name = product.name + entity.price = product.price + entity.image = Buffer.from(product.image, 'hex') + return await repository.save(entity); + } + + for (const product of products) { + const entityID = await loadProduct(product) + entityIDs.push(entityID) + } + + // TODO: figure out rawSearch / where query encoding is happening ... + + // execute a raw search for the first product image ... + const results = await redis.sendCommand([ + 'FT.SEARCH', 'ProductJSON:index', '*=>[KNN 2 @image $query_vector]', 'PARAMS', '2', + 'query_vector', Buffer.from(products[0].image, 'hex'), + 'RETURN', '3', '__image_score", "name", "price', + 'SORTBY', '__image_score', + 'DIALECT', '2' + ]) as any[] + + // ... and we should get the first 2 products back in order + expect(results).toBeDefined() + expect(results).toBeInstanceOf(Array) + expect(results.length).toBe(5) + expect(results[1]).toBe('ProductJSON:' + entityIDs[0]) + expect(parseFloat(results[2][1])).toBeLessThan(1e-4) + expect(results[3]).toBe('ProductJSON:' + entityIDs[1]) + expect(parseFloat(results[4][1])).toBeGreaterThan(0.2) + }); +}); diff --git a/spec/helpers/example-data.ts b/spec/helpers/example-data.ts index 777b8403..1b77edf6 100644 --- a/spec/helpers/example-data.ts +++ b/spec/helpers/example-data.ts @@ -59,6 +59,9 @@ export const SOME_MORE_STRINGS: Array = ['charlie', 'delta', 'echo']; export const SOME_MORE_STRINGS_JSON: string = JSON.stringify(SOME_MORE_STRINGS); export const SOME_MORE_STRINGS_JOINED: string = SOME_MORE_STRINGS.join('|'); +export const A_BUFFER = Buffer.from(`52b85e3f9a9919becdcc0c3f8fc2f53c333333bf5c8f02bfae47613f295c0f3ecdcc4cbf9a9919bec3f5a83e0ad723bc`, 'hex') +export const A_BUFFER_VALUES = [0.8700000047683716, -0.15000000596046448, 0.550000011920929, 0.029999999329447746, -0.699999988079071, -0.5099999904632568, 0.8799999952316284, 0.14000000059604645, -0.800000011920929, -0.15000000596046448, 0.33000001311302185, -0.009999999776482582] + export type SampleEntityData = { aString: string | null; anotherString: string | null; diff --git a/spec/unit/client/client-hgetall.spec.ts b/spec/unit/client/client-hgetall.spec.ts index f6982b18..a266d02b 100644 --- a/spec/unit/client/client-hgetall.spec.ts +++ b/spec/unit/client/client-hgetall.spec.ts @@ -1,11 +1,11 @@ -import { redis } from '../helpers/mock-redis' -import { Client } from '$lib/client'; +import { redis, commandOptions } from '../helpers/mock-redis' +import { Client, RedisHashData } from '$lib/client'; describe("Client", () => { let client: Client; - let result: { [key: string]: string }; + let result: RedisHashData beforeEach(() => { client = new Client() @@ -20,7 +20,7 @@ describe("Client", () => { }); it("passes the command to redis", async () => { - expect(redis.hGetAll).toHaveBeenCalledWith('foo'); + expect(redis.hGetAll).toHaveBeenCalledWith(commandOptions({ returnBuffers: true }), 'foo'); }); it("returns the value from redis", async () => { diff --git a/spec/unit/client/client-search.spec.ts b/spec/unit/client/client-search.spec.ts index da20aa6a..0b401d00 100644 --- a/spec/unit/client/client-search.spec.ts +++ b/spec/unit/client/client-search.spec.ts @@ -1,4 +1,4 @@ -import { redis } from '../helpers/mock-redis' +import { redis, commandOptions } from '../helpers/mock-redis' import { Client } from '$lib/client'; @@ -22,7 +22,9 @@ describe("Client", () => { query: 'query' }); expect(redis.sendCommand).toHaveBeenCalledWith([ - 'FT.SEARCH', 'index', 'query']); + 'FT.SEARCH', 'index', 'query'], + commandOptions({ returnBuffers: true }) + ); }); it("sends the expect command when given a limit", async () => { @@ -32,7 +34,9 @@ describe("Client", () => { limit: { offset: 0, count: 5 } }); expect(redis.sendCommand).toHaveBeenCalledWith([ - 'FT.SEARCH', 'index', 'query', 'LIMIT', '0', '5']); + 'FT.SEARCH', 'index', 'query', 'LIMIT', '0', '5'], + commandOptions({ returnBuffers: true }) + ); }); it("sends the expected command when given a sort", async () => { @@ -42,7 +46,9 @@ describe("Client", () => { sort: { field: 'sortField', order: 'ASC' } }); expect(redis.sendCommand).toHaveBeenCalledWith([ - 'FT.SEARCH', 'index', 'query', 'SORTBY', 'sortField', 'ASC']); + 'FT.SEARCH', 'index', 'query', 'SORTBY', 'sortField', 'ASC'], + commandOptions({ returnBuffers: true }) + ); }); it("sends the expected command when keysOnly is set to false", async () => { @@ -52,7 +58,9 @@ describe("Client", () => { keysOnly: false }); expect(redis.sendCommand).toHaveBeenCalledWith([ - 'FT.SEARCH', 'index', 'query']); + 'FT.SEARCH', 'index', 'query'], + commandOptions({ returnBuffers: true }) + ); }); it("sends the expected command when keysOnly is set to true", async () => { @@ -62,7 +70,9 @@ describe("Client", () => { keysOnly: true }); expect(redis.sendCommand).toHaveBeenCalledWith([ - 'FT.SEARCH', 'index', 'query', 'RETURN', '0']); + 'FT.SEARCH', 'index', 'query', 'RETURN', '0'], + commandOptions({ returnBuffers: true }) + ); }); it("sends the expected command with all options", async () => { @@ -75,7 +85,9 @@ describe("Client", () => { }); expect(redis.sendCommand).toHaveBeenCalledWith([ 'FT.SEARCH', 'index', 'query', 'LIMIT', '0', '5', - 'SORTBY', 'sortField', 'ASC', 'RETURN', '0']); + 'SORTBY', 'sortField', 'ASC', 'RETURN', '0'], + commandOptions({ returnBuffers: true }) + ); }); }); diff --git a/spec/unit/entity/entity-binary-field.spec.ts b/spec/unit/entity/entity-binary-field.spec.ts new file mode 100644 index 00000000..23132896 --- /dev/null +++ b/spec/unit/entity/entity-binary-field.spec.ts @@ -0,0 +1,171 @@ +import { FieldDefinition } from "../../../lib"; +import { EntityBinaryField } from "$lib/entity/fields"; +import { A_DATE, A_NUMBER, A_NUMBER_STRING, A_POINT, A_STRING, SOME_STRINGS, A_BUFFER_VALUES, A_BUFFER } from "../../helpers/example-data"; + +const FIELD_NAME = 'foo'; +const FIELD_DEF: FieldDefinition = { type: 'binary' }; +const EXPECTED_NULL_JSON_DATA = {}; +const EXPECTED_NULL_HASH_DATA = {}; +const EXPECTED_JSON_DATA = { foo: A_BUFFER_VALUES }; +const EXPECTED_HASH_DATA = { foo: A_BUFFER }; + +describe("EntityBinaryField", () => { + + let field: EntityBinaryField; + + describe("when created", () => { + + beforeEach(() => { + field = new EntityBinaryField(FIELD_NAME, FIELD_DEF) + }); + + it("has the expected alias", () => expect(field.name).toBe(FIELD_NAME)); + it("has a value of null", () => expect(field.value).toBeNull()); + it("converts to the expected Redis JSON data", () => expect(field.toRedisJson()).toEqual(EXPECTED_NULL_JSON_DATA)); + it("converts to the expected Redis Hash data", () => expect(field.toRedisHash()).toEqual(EXPECTED_NULL_HASH_DATA)); + + describe("when loaded from Redis JSON data", () => { + beforeEach(() => field.fromRedisJson(A_BUFFER)); + it("has the expected value", () => expect(field.value).toEqual(A_BUFFER)); + }); + + it("complains when loaded from invalid Redis Json data", () => { + // @ts-ignore: JavaScript trap + expect(() => field.fromRedisJson('foo')) + .toThrow("Non-binary value of 'foo' read from Redis for binary field."); + }); + + describe("when loaded from Redis Hash data", () => { + beforeEach(() => field.fromRedisHash(A_BUFFER)); + it("has the expected value", () => expect(field.value).toEqual(A_BUFFER)); + }); + + it("complains when loaded from invalid Redis Hash data", () => { + // @ts-ignore: JavaScript trap + expect(() => field.fromRedisHash('foo')) + .toThrow("Non-binary value of 'foo' read from Redis for binary field."); + }); + + describe("when created with a buffer", () => { + beforeEach(() => { + field.value = A_BUFFER + }); + it("has the expected value", () => expect(field.value).toBe(A_BUFFER)); + it("converts to the expected Redis JSON data", () => expect(field.toRedisJson()).toEqual(EXPECTED_JSON_DATA)); + it("converts to the expected Redis Hash data", () => expect(field.toRedisHash()).toEqual(EXPECTED_HASH_DATA)); + }); + + describe("when created with a null", () => { + beforeEach(() => { + field.value = A_BUFFER; // set it to something else first + field.value = null; + }); + it("has the expected value", () => expect(field.value).toBeNull()); + it("converts to the expected Redis JSON data", () => expect(field.toRedisJson()).toEqual(EXPECTED_NULL_JSON_DATA)); + it("converts to the expected Redis Hash data", () => expect(field.toRedisHash()).toEqual(EXPECTED_NULL_HASH_DATA)); + }); + + it("cannot be set to undefined", () => { + // @ts-ignore: JavaScript trap + expect(() => field.value = undefined) + .toThrow("Property cannot be set to undefined. Use null instead."); + }); + + it("cannot be set to a string", () => { + // @ts-ignore: JavaScript trap + expect(() => field.value = A_STRING) + .toThrow(`Expected value with type of 'binary' but received '${A_STRING}'.`); + }); + + it("cannot be set to a boolean", () => { + // @ts-ignore: JavaScript trap + expect(() => field.value = true) + .toThrow(`Expected value with type of 'binary' but received 'true'.`); + }); + + it("cannot be set to a Number", () => { + // @ts-ignore: JavaScript trap + expect(() => field.value = A_NUMBER) + .toThrow(`Expected value with type of 'binary' but received '${A_NUMBER}'.`); + }); + + it("cannot be set to a Point", () => { + // @ts-ignore: JavaScript trap + expect(() => field.value = A_POINT) + .toThrow(`Expected value with type of 'binary' but received '${A_POINT}'.`); + }); + + it("cannot be set to a Date", () => { + // @ts-ignore: JavaScript trap + expect(() => field.value = A_DATE) + .toThrow(`Expected value with type of 'binary' but received '${A_DATE}'.`); + }); + + it("cannot be set to an array of strings", () => { + // @ts-ignore: JavaScript trap + expect(() => field.value = SOME_STRINGS) + .toThrow(`Expected value with type of 'binary' but received '${SOME_STRINGS}'.`); + }); + }); + + describe("when created with an alias", () => { + beforeEach(() => { + field = new EntityBinaryField(FIELD_NAME, { type: 'binary', alias: 'bar' }) + }); + it("has the aliased name", () => expect(field.name).toBe('bar')); + }); + + describe("when created with a buffer", () => { + beforeEach(() => { + field = new EntityBinaryField(FIELD_NAME, FIELD_DEF, A_BUFFER) + }); + it("has the expected value", () => expect(field.value).toBe(A_BUFFER)); + it("converts to the expected Redis JSON data", () => expect(field.toRedisJson()).toEqual(EXPECTED_JSON_DATA)); + it("converts to the expected Redis Hash data", () => expect(field.toRedisHash()).toEqual(EXPECTED_HASH_DATA)); + }); + + describe("when created with a null", () => { + beforeEach(() => { + field = new EntityBinaryField(FIELD_NAME, FIELD_DEF, null) + }); + it("has the expected value", () => expect(field.value).toBeNull()); + it("converts to the expected Redis JSON data", () => expect(field.toRedisJson()).toEqual(EXPECTED_NULL_JSON_DATA)); + it("converts to the expected Redis Hash data", () => expect(field.toRedisHash()).toEqual(EXPECTED_NULL_HASH_DATA)); + }); + + it("complains when created with a string", () => { + // @ts-ignore: JavaScript trap + expect(() => new EntityBinaryField(FIELD_NAME, FIELD_DEF, A_STRING)) + .toThrow(`Expected value with type of 'binary' but received '${A_STRING}'.`); + }); + + it("complains when created with a boolean", () => { + // @ts-ignore: JavaScript trap + expect(() => new EntityBinaryField(FIELD_NAME, FIELD_DEF, true)) + .toThrow(`Expected value with type of 'binary' but received 'true'.`); + }); + + it("complains when created with a Number", () => { + // @ts-ignore: JavaScript trap + expect(() => new EntityBinaryField(FIELD_NAME, FIELD_DEF, A_NUMBER)) + .toThrow(`Expected value with type of 'binary' but received '${A_NUMBER}'.`); + }); + + it("complains when created with a Point", () => { + // @ts-ignore: JavaScript trap + expect(() => new EntityBinaryField(FIELD_NAME, FIELD_DEF, A_POINT)) + .toThrow(`Expected value with type of 'binary' but received '${A_POINT}'.`); + }); + + it("complains when created with a Date", () => { + // @ts-ignore: JavaScript trap + expect(() => new EntityBinaryField(FIELD_NAME, FIELD_DEF, A_DATE)) + .toThrow(`Expected value with type of 'binary' but received '${A_DATE}'.`); + }); + + it("complains when created with an array of strings", () => { + // @ts-ignore: JavaScript trap + expect(() => new EntityBinaryField(FIELD_NAME, FIELD_DEF, SOME_STRINGS)) + .toThrow(`Expected value with type of 'binary' but received '${SOME_STRINGS}'.`); + }); +}); diff --git a/spec/unit/helpers/mock-redis.ts b/spec/unit/helpers/mock-redis.ts index a4124ffb..8564cf04 100644 --- a/spec/unit/helpers/mock-redis.ts +++ b/spec/unit/helpers/mock-redis.ts @@ -13,5 +13,6 @@ export const redis = { } export const createClient = vi.fn(() => redis) +export const commandOptions = vi.fn() -vi.mock('redis', () => ({ createClient })) \ No newline at end of file +vi.mock('redis', () => ({ createClient, commandOptions })) \ No newline at end of file diff --git a/spec/unit/schema/binary-hash-fields.spec.ts b/spec/unit/schema/binary-hash-fields.spec.ts new file mode 100644 index 00000000..aa2734a3 --- /dev/null +++ b/spec/unit/schema/binary-hash-fields.spec.ts @@ -0,0 +1,146 @@ +import { Schema } from '$lib/schema/schema'; +import { Entity } from '$lib/entity/entity'; +import { SchemaDefinition } from '$lib/schema/definition'; +import { DataStructure } from '$lib/schema/options'; + +describe("Schema", () => { + describe.each([ + + ["that defines an unindexed binary", { + schemaDef: { aField: { type: 'binary' } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'NOINDEX' + ] + }], + + ["that defines a FLAT / 512 / COSINE vector for a HASH", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'FLAT', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'VECTOR', 'FLAT', '6', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE' + ] + }], + + ["that defines a FLAT / 256 / IP vector for a HASH", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'FLAT', dim: 256, distance_metric: 'IP' } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'VECTOR', 'FLAT', '6', 'TYPE', 'FLOAT32', 'DIM', '256', 'DISTANCE_METRIC', 'IP' + ] + }], + + ["that defines a FLAT / 1024 / L2 vector for a HASH", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'FLAT', dim: 1024, distance_metric: 'L2' } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'VECTOR', 'FLAT', '6', 'TYPE', 'FLOAT32', 'DIM', '1024', 'DISTANCE_METRIC', 'L2' + ] + }], + + ["that defines a FLAT / 512 / COSINE vector with block_size for a HASH", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'FLAT', dim: 512, distance_metric: 'COSINE', block_size: 512*512 } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'VECTOR', 'FLAT', '8', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE', 'BLOCK_SIZE', '262144' + ] + }], + + ["that defines an aliased FLAT / 512 / COSINE vector for a HASH", { + schemaDef: { aField: { type: 'binary', alias: 'anotherField', vector: { algorithm: 'FLAT', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'anotherField', 'VECTOR', 'FLAT', '6', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE' + ] + }], + + // NOTE: it makes little sense to do this, but maybe someone wants to turn off indexing + // but keep the schema definition, so we'll assume that NOINDEX should take precendence + ["that defines an unindexed FLAT vector for a HASH", { + schemaDef: { aField: { type: 'binary', indexed: false, vector: { algorithm: 'FLAT', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'NOINDEX' + ] + }], + + ["that defines a HNSW / 512 / COSINE vector for a HASH", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'VECTOR', 'HNSW', '6', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE' + ] + }], + + ["that defines a HNSW / 256 / IP vector for a HASH", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 256, distance_metric: 'IP' } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'VECTOR', 'HNSW', '6', 'TYPE', 'FLOAT32', 'DIM', '256', 'DISTANCE_METRIC', 'IP' + ] + }], + + ["that defines a HNSW / 1024 / L2 vector for a HASH", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 1024, distance_metric: 'L2' } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'VECTOR', 'HNSW', '6', 'TYPE', 'FLOAT32', 'DIM', '1024', 'DISTANCE_METRIC', 'L2' + ] + }], + + ["that defines a HNSW / 512 / COSINE vector with M for a HASH", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE', m: 8 } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'VECTOR', 'HNSW', '8', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE', 'M', '8' + ] + }], + + ["that defines a HNSW / 512 / COSINE vector with EF_CONSTRUCTION for a HASH", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE', ef_construction: 250 } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'VECTOR', 'HNSW', '8', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE', 'EF_CONSTRUCTION', '250' + ] + }], + + ["that defines a HNSW / 512 / COSINE vector with EF_RUNTIME for a HASH", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE', ef_runtime: 20 } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'VECTOR', 'HNSW', '8', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE', 'EF_RUNTIME', '20' + ] + }], + + ["that defines an aliased HNSW / 512 / COSINE vector for a HASH", { + schemaDef: { aField: { type: 'binary', alias: 'anotherField', vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'anotherField', 'VECTOR', 'HNSW', '6', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE' + ] + }], + + // NOTE: it makes little sense to do this, but maybe someone wants to turn off indexing + // but keep the schema definition, so we'll assume that NOINDEX shoudl take precendence + ["that defines an unindexed HNSW vector for a HASH", { + schemaDef: { aField: { type: 'binary', indexed: false, vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'HASH', + expectedRedisSchema: [ + 'aField', 'NOINDEX' + ] + }], + + ])("%s", (_, data) => { + + class TestEntity extends Entity {} + + it("generates a Redis schema for the field", () => { + let schemaDef = data.schemaDef; + let dataStructure = data.dataStructure as DataStructure; + let expectedRedisSchema = data.expectedRedisSchema; + + let schema = new Schema(TestEntity, schemaDef, { dataStructure }); + expect(schema.redisSchema).toEqual(expectedRedisSchema); + }); + }); +}); diff --git a/spec/unit/schema/binary-json-fields.spec.ts b/spec/unit/schema/binary-json-fields.spec.ts new file mode 100644 index 00000000..a998bea0 --- /dev/null +++ b/spec/unit/schema/binary-json-fields.spec.ts @@ -0,0 +1,146 @@ +import { Schema } from '$lib/schema/schema'; +import { Entity } from '$lib/entity/entity'; +import { SchemaDefinition } from '$lib/schema/definition'; +import { DataStructure } from '$lib/schema/options'; + +describe("Schema", () => { + describe.each([ + + ["that defines an unindexed binary", { + schemaDef: { aField: { type: 'binary' } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS', 'aField', 'NOINDEX' + ] + }], + + ["that defines a FLAT / 512 / COSINE vector for a JSON", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'FLAT', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS', 'aField', 'VECTOR', 'FLAT', '6', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE' + ] + }], + + ["that defines a FLAT / 256 / IP vector for a JSON", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'FLAT', dim: 256, distance_metric: 'IP' } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS', 'aField', 'VECTOR', 'FLAT', '6', 'TYPE', 'FLOAT32', 'DIM', '256', 'DISTANCE_METRIC', 'IP' + ] + }], + + ["that defines a FLAT / 1024 / L2 vector for a JSON", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'FLAT', dim: 1024, distance_metric: 'L2' } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS', 'aField', 'VECTOR', 'FLAT', '6', 'TYPE', 'FLOAT32', 'DIM', '1024', 'DISTANCE_METRIC', 'L2' + ] + }], + + ["that defines a FLAT / 512 / COSINE vector with block_size for a JSON", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'FLAT', dim: 512, distance_metric: 'COSINE', block_size: 512*512 } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS', 'aField', 'VECTOR', 'FLAT', '8', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE', 'BLOCK_SIZE', '262144' + ] + }], + + ["that defines an aliased FLAT / 512 / COSINE vector for a JSON", { + schemaDef: { aField: { type: 'binary', alias: 'anotherField', vector: { algorithm: 'FLAT', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.anotherField', 'AS', 'anotherField', 'VECTOR', 'FLAT', '6', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE' + ] + }], + + // NOTE: it makes little sense to do this, but maybe someone wants to turn off indexing + // but keep the schema definition, so we'll assume that NOINDEX should take precendence + ["that defines an unindexed FLAT vector for a JSON", { + schemaDef: { aField: { type: 'binary', indexed: false, vector: { algorithm: 'FLAT', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS', 'aField', 'NOINDEX' + ] + }], + + ["that defines a HNSW / 512 / COSINE vector for a JSON", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS', 'aField', 'VECTOR', 'HNSW', '6', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE' + ] + }], + + ["that defines a HNSW / 256 / IP vector for a JSON", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 256, distance_metric: 'IP' } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS', 'aField', 'VECTOR', 'HNSW', '6', 'TYPE', 'FLOAT32', 'DIM', '256', 'DISTANCE_METRIC', 'IP' + ] + }], + + ["that defines a HNSW / 1024 / L2 vector for a JSON", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 1024, distance_metric: 'L2' } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS', 'aField', 'VECTOR', 'HNSW', '6', 'TYPE', 'FLOAT32', 'DIM', '1024', 'DISTANCE_METRIC', 'L2' + ] + }], + + ["that defines a HNSW / 512 / COSINE vector with M for a JSON", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE', m: 8 } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS', 'aField', 'VECTOR', 'HNSW', '8', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE', 'M', '8' + ] + }], + + ["that defines a HNSW / 512 / COSINE vector with EF_CONSTRUCTION for a JSON", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE', ef_construction: 250 } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS', 'aField', 'VECTOR', 'HNSW', '8', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE', 'EF_CONSTRUCTION', '250' + ] + }], + + ["that defines a HNSW / 512 / COSINE vector with EF_RUNTIME for a JSON", { + schemaDef: { aField: { type: 'binary', vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE', ef_runtime: 20 } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS','aField', 'VECTOR', 'HNSW', '8', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE', 'EF_RUNTIME', '20' + ] + }], + + ["that defines an aliased HNSW / 512 / COSINE vector for a JSON", { + schemaDef: { aField: { type: 'binary', alias: 'anotherField', vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.anotherField', 'AS', 'anotherField', 'VECTOR', 'HNSW', '6', 'TYPE', 'FLOAT32', 'DIM', '512', 'DISTANCE_METRIC', 'COSINE' + ] + }], + + // NOTE: it makes little sense to do this, but maybe someone wants to turn off indexing + // but keep the schema definition, so we'll assume that NOINDEX shoudl take precendence + ["that defines an unindexed HNSW vector for a JSON", { + schemaDef: { aField: { type: 'binary', indexed: false, vector: { algorithm: 'HNSW', dim: 512, distance_metric: 'COSINE' } } } as SchemaDefinition, + dataStructure: 'JSON', + expectedRedisSchema: [ + '$.aField', 'AS','aField', 'NOINDEX' + ] + }], + + ])("%s", (_, data) => { + + class TestEntity extends Entity {} + + it("generates a Redis schema for the field", () => { + let schemaDef = data.schemaDef; + let dataStructure = data.dataStructure as DataStructure; + let expectedRedisSchema = data.expectedRedisSchema; + + let schema = new Schema(TestEntity, schemaDef, { dataStructure }); + expect(schema.redisSchema).toEqual(expectedRedisSchema); + }); + }); +}); diff --git a/spec/unit/schema/schema.spec.ts b/spec/unit/schema/schema.spec.ts index d63c497b..d5742511 100644 --- a/spec/unit/schema/schema.spec.ts +++ b/spec/unit/schema/schema.spec.ts @@ -154,12 +154,12 @@ describe("Schema", () => { it("throws an exception when the type is missing on a field definition", () => // @ts-ignore: JavaScript test expect(() => new Schema(TestEntity, { aField: {} })) - .toThrow("The field 'aField' is configured with a type of 'undefined'. Valid types include 'boolean', 'date', 'number', 'point', 'string', 'string[]', and 'text'.")); + .toThrow("The field 'aField' is configured with a type of 'undefined'. Valid types include 'boolean', 'date', 'number', 'point', 'string', 'string[]', 'text', 'binary'.")); it("throws an exception when the type is invalid on a field definition", () => // @ts-ignore: JavaScript test expect(() => new Schema(TestEntity, { aField: { type: 'foo' } })) - .toThrow("The field 'aField' is configured with a type of 'foo'. Valid types include 'boolean', 'date', 'number', 'point', 'string', 'string[]', and 'text'.")); + .toThrow("The field 'aField' is configured with a type of 'foo'. Valid types include 'boolean', 'date', 'number', 'point', 'string', 'string[]', 'text', 'binary'.")); it("throws an exception when the data structure is invalid", () => { // @ts-ignore: JavaScript test diff --git a/vitest.config.js b/vitest.config.js index 8c088788..0f4478e5 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -1,24 +1,21 @@ import { defineConfig } from 'vitest/config' -import path from "path" +import path from 'path' export default defineConfig({ - test: { - globals: true, - clearMocks: true, - isolate: false, - coverage: { - provider: 'istanbul', - exclude: [ - 'spec/*' - ] - }, - exclude: [ - './node_modules/**', - ] - }, - resolve: { - alias: { - "$lib": path.resolve(__dirname, "./lib"), - }, - }, -}) \ No newline at end of file + test: { + globals: true, + clearMocks: true, + isolate: true, + threads: true, + coverage: { + provider: 'c8', + exclude: ['spec/*'], + }, + exclude: ['./node_modules/**'], + }, + resolve: { + alias: { + $lib: path.resolve(__dirname, './lib'), + }, + }, +})